⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 6通道遥控器程序
💻 C
字号:
/************************************
*	6通道航模遥控器初级版ICC程序	*
* 功    能:6通道比例遥控PPM编码	*
* 电    路:6_RC_ZJ.SCH				*
* 建立日期:2010年05月17日			*
* 版    本:V10.01					*
* 设 计 者:周长洪					*
* 修改日期:2010年05月17日			*
* 主控芯片:Mega16L-8AU				*
* 时钟频率:外部8.0000Mhz			*
* 编译系统:ICCAVR6.31A				*
************************************/
#include <iom16v.h>
#include <macros.h>
#include "delay.h"

//简化数据类型定义
#define uchar unsigned char
#define uint  unsigned int

//端口和数据宏定义
//PPM输出端口定义
#define PPM_CLR	PORTD &= ~(1<<5)
#define PPM_SET PORTD |= 1<<5
#define PPM_TG	PORTD ^= 1<<5

//蜂鸣器端口定义
#define	SPK_CLR	PORTD &= ~(1<<4)
#define	SPK_SET	PORTD |= 1<<4
#define	SPK_TG	PORTD ^= 1<<4

//LED灯端口定义
#define	LED_OFF	PORTA &= ~(1<<7)
#define	LED_ON	PORTA |= 1<<7
#define	LED_TG	PORTA ^= 1<<7

//常用参数定义
#define	zhd		580				//定义定时修正参数
#define	fxsj	2183			//定义反向数据参数
#define sysc	20				//定义微调时响声时长ms
#define sysc1	100				//定义微调中点响声时长
#define sysc2	400				//定义微调端点响声时长
#define dy1		505				//定义电压保护1:7.4V
#define dy2		477				//定义电压保护2:7.0V
#define wtcs	4				//定义微调步进长度

//数据定义
uint ch_ad[6];					//定义通道数据
uint ch_sj[6];					//定义ADC数据
uint dy_sj=1000;				//定义电压数据
uint ch_wt[4];					//定义1-4通道中点数据
uchar	flag = 0;				//定义通道号
uchar	ch_fx = 0;				//定义通道反向数据
uchar	a=0;					//普通数据

/****************************
*		端口初始化			*
****************************/
void port_init(void)
	{
	PORTA = 0x00;
	DDRA  = 0x80;			//A口除PA7外,为ADC输入
	PORTB = 0xFF;
	DDRB  = 0x00;			//B口为电子微调输入,上拉
	PORTC = 0xFF;
	DDRC  = 0x00;			//C口为通道正反向、混控输入
	PORTD = 0x00;
	DDRD  = 0xFF;			//D口为输出
	}

/****************************
*		蜂鸣器函数			*
****************************/
void spk(uchar k,uint time)
	{
	for(;k;k--)
		{
		SPK_SET;
		delay_ms(time);
		SPK_CLR;
		delay_ms(50);
		}
	}

/********************************
*		EEPROM读取函数一		*
* 功能描述:读取1-4微调数据		*
* 入    口:无					*
* 返 回 值:无					*
* 固定地址:0-7 八字节			*
********************************/
void ee_read(void)
    {
	uchar da[8];
	uchar k;
	for(k=0;k<8;k++)
		{
		while(EECR & (1 << EEWE));
		EEARH = 0;
		EEARL = k;				//读出地址高字节数据的位置
		EECR |= (1 << EERE);	//启动读数据
		da[k] = EEDR;			//读出数据
		}
		
	for(k=0;k<4;k++)			//合成数据
		{
		ch_wt[k] = (da[2*k+1]<<8)+da[2*k];
		}
	}

/********************************
*		EEPROM写入函数一		*
* 功能描述:写入1-4微调数据		*
* 入    口:需写入的数据和位置	*
* 返 回 值:无					*
* 固定地址:0-7 八字节			*
********************************/
void ee_write(uint da,uchar n)
    {
	EEARH = 0;
	EEARL = 2*n;			//写入地址数据的位置
	EEDR = da & 0xFF;		//需写入的数据低字节
	EECR |= (1 << EEMWE);
	EECR |= (1 << EEWE);	//启动写入
	delay_ms(10);			//延时等待
	
	EEARH = 0;
	EEARL = 2*n+1;			//写入地址数据的位置
	EEDR = da >> 8;			//需写入的数据高字节
	EECR |= (1 << EEMWE);
	EECR |= (1 << EEWE);	//启动写入
	delay_ms(10);			//延时等待
	}

/****************************
*		AD转换函数			*
****************************/
uint ADC_Convert(void)
	{
	uint temp1,temp2;
	temp1=ADCL;
	temp2=ADCH;
	temp2=(temp2<<8)+temp1;
	return(temp2);
	}

/****************************
*		AD初始化函数		*
****************************/
void adc_init(void)
	{
	ADMUX=0x40;				//选择第0通道ADC;V为基准
	ADCSRA=0xE7;			//125K转换速率,自由转换模式;启动AD转换器;
	SFIOR = 0x00;
	delay_ms(200);			//延时等待系统稳定
	}

/****************************
*		TC0初始化函数		*
* 功    能:产生20mS帧周期	*
* 预 分 频:1024			*
* 工作模式:比较匹配中断	*
* 时钟频率:外部8.0000Mhz	*
****************************/
void timer0_init(void)
	{
	TCCR0 = 0x00;
	TCNT0 = 0x63;
	TCCR0 = 0x05;
	}

/****************************
*		TC0中断入口函数		*
****************************/
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
	{
	TCNT0  = 0x63;			//重装初值
	TCNT1H = 0x00;			//装TC1初值:产生400uS间隔
	TCNT1L = 0x00;
	OCR1A  = 400;
	TCCR1B = 0x02;
	TIMSK |= 0x10;			//比较匹配中断
	PPM_SET;				//输出先置高
	}

/****************************
*		TC1初始化函数		*
* 功    能:产生各脉冲		*
* 预 分 频:8				*
* 工作模式:比较匹配中断	*
* 时钟频率:外部8.0000Mhz	*
****************************/
void timer1_init(void)
	{
	TCCR1B = 0x00;
	TCCR1A = 0x00;
//	TCCR1B = 0x02;
	}

/****************************
*		TC1中断入口函数		*
****************************/
#pragma interrupt_handler timer1_ovf_isr:iv_TIMER1_COMPA
void timer1_ovf_isr(void)
	{
	TCNT1H = 0;
	TCNT1L = 0;

	flag ++;
	switch(flag)
		{
		case 1:
			OCR1A  = ch_ad[0];
			PPM_CLR;			//置0
			break;
		case 3:
			OCR1A  = ch_ad[1];
			PPM_CLR;			//置0
			break;
		case 5:
			OCR1A  = ch_ad[2];
			PPM_CLR;			//置0
			break;
		case 7:
			OCR1A  = ch_ad[3];
			PPM_CLR;			//置0
			break;
		case 9:
			OCR1A  = ch_ad[4];
			PPM_CLR;			//置0
			break;
		case 11:
			OCR1A  = ch_ad[5];
			PPM_CLR;			//置0
			break;
		case 13:
			PPM_CLR;			//置0
			flag = 0;
			TIMSK &= ~0x10;		//关闭TC1中断,等待下一帧到来
			TCCR1B = 0x00;
			break;
		default:
			OCR1A  = 400;
			PPM_SET;			//置1
			break;
		}
	}

/****************************
*		器件初始化函数		*
****************************/
void init_devices(void)
	{
	CLI();
	port_init();
	timer0_init();
	timer1_init();
	
	adc_init();
	
	MCUCR = 0x00;
	GICR  = 0x00;
	TIMSK = 0x01;			//开启TC0溢出中断
//	TIMSK = 0x45;
	SEI();
	}

/********************************
*		电压读取函数			*
* 入口参数:无					*
********************************/
void v_read(void)
	{
	uchar k;
	for(k=0;k<6;k++)
		{
		ADMUX=0x40+k;				//选择输入端电压通道
		delay_us(500);				//延时稳定
		ch_sj[k] = ADC_Convert();	//读电压
		delay_us(5);
		ch_sj[k] = ADC_Convert();	//再读电压
		}
	ADMUX=0x46;						//选择输入端电压通道
	delay_us(500);					//延时稳定
	dy_sj = ADC_Convert();
	delay_us(5);
	dy_sj = ADC_Convert();
	delay_us(50);
	}

/********************************
*		混控功能函数			*
* 功能描述:实现两通道混控		*
* 入口参数:需混控的通道号		*
********************************/
void mix1(uchar a,uchar b)
	{
	ch_sj[a]=(ch_sj[a]+ch_sj[b])/2;
	ch_sj[b]=511+ch_sj[a]/2-ch_sj[b]/2;
	}

/****************************
*			主函数			*
****************************/
void main(void)
	{
	unsigned char	m=0;
	unsigned char	n=0;
	unsigned char	a=0;
	unsigned char	z=0,f=0;
	unsigned char	flag=0;	//定义数据标志

	init_devices();			//器件初始化
	
	ee_read();
	
	LED_ON;
	spk(1,800);

	while(1)
		{
		v_read();
		ch_fx = PINC;		//读通道反向开关状态
		f ++;
		if(f>100)
			{
			f = 0;
			z = ch_fx ^ z;
			switch(z)
				{
				case 0x01:
					ch_wt[0] = 580;
					ee_write(ch_wt[0],0);
					break;
				case 0x02:
					ch_wt[1] = 580;
					ee_write(ch_wt[1],1);
					break;
				case 0x04:
					ch_wt[2] = 580;
					ee_write(ch_wt[2],2);
					break;
				case 0x08:
					ch_wt[3] = 580;
					ee_write(ch_wt[3],3);
					break;
				default:break;
				}
			z = PINC;
			}
		if((ch_fx & 0x40)==0)	//飞翼混控开
			{
			mix1(0,1);			//1、2通道混控
			}
			
		if((ch_fx & 0x80)==0)	//V型混控开
			{
			mix1(1,3);			//2、4通道混控
			}
		
		if((ch_fx & 0xC0)==0)	//襟翼混控开
			{
			mix1(0,5);			//1、6通道混控
			}

		if(ch_fx & 0x01)		//1通道数据计算
			{
			ch_ad[0] = ch_sj[0]+ch_wt[0]; //正向
			}
		else
			{
			ch_ad[0] = fxsj-ch_sj[0]-ch_wt[0]; //反向
			}
			
		if(ch_fx & 0x02)		//2通道数据计算
			{
			ch_ad[1] = ch_sj[1]+ch_wt[1]; //正向
			}
		else
			{
			ch_ad[1] = fxsj-ch_sj[1]-ch_wt[1]; //反向
			}
		
		if(ch_fx & 0x04)		//3通道数据计算
			{
			ch_ad[2] = ch_sj[2]+ch_wt[2]; //正向
			}
		else
			{
			ch_ad[2] = fxsj-ch_sj[2]-ch_wt[2]; //反向
			}
		
		if(ch_fx & 0x08)		//4通道数据计算
			{
			ch_ad[3] = ch_sj[3]+ch_wt[3]; //正向
			}
		else
			{
			ch_ad[3] = fxsj-ch_sj[3]-ch_wt[3]; //反向
			}
		
		if(ch_fx & 0x10)		//5通道数据计算
			{
			ch_ad[4] = ch_sj[4]+zhd; //正向
			}
		else
			{
			ch_ad[4] = fxsj-ch_sj[4]-zhd; //反向
			}
		
		if(ch_fx & 0x20)		//6通道数据计算
			{
			ch_ad[5] = ch_sj[5]+zhd; //正向
			}
		else
			{
			ch_ad[5] = fxsj-ch_sj[5]-zhd; //反向
			}
		
		m = ~PINB;
		if(m)
			{
			delay_ms(20);
			if(m==~PINB)
				{
				switch(m)
					{
					case 0x01:
						if(ch_wt[0]<700)
							{
							ch_wt[0] += wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[0]=700;
							spk(1,sysc2);
							}
						if(ch_wt[0]==580)spk(1,sysc1);
						ee_write(ch_wt[0],0);
						break;

					case 0x02:
						if(ch_wt[0]>460)
							{
							ch_wt[0] -= wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[0]=460;
							spk(1,sysc2);
							}
						if(ch_wt[0]==580)spk(1,sysc1);
						ee_write(ch_wt[0],0);
						break;
				
					case 0x04:
						if(ch_wt[1]<700)
							{
							ch_wt[1] += wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[1]=700;
							spk(1,sysc2);
							}
						if(ch_wt[1]==580)spk(1,sysc1);
						ee_write(ch_wt[1],1);
						break;
					
					case 0x08:
						if(ch_wt[1]>460)
							{
							ch_wt[1] -= wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[1]=460;
							spk(1,sysc2);
							}
						if(ch_wt[1]==580)spk(1,sysc1);
						ee_write(ch_wt[1],1);
						break;
				
					case 0x10:
						if(ch_wt[2]<700)
							{
							ch_wt[2] += wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[2]=700;
							spk(1,sysc2);
							}
						if(ch_wt[2]==580)spk(1,sysc1);
						ee_write(ch_wt[2],2);
						break;
					
					case 0x20:
						if(ch_wt[2]>460)
							{
							ch_wt[2] -= wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[2]=460;
							spk(1,sysc2);
							}
						if(ch_wt[2]==580)spk(1,sysc1);
						ee_write(ch_wt[2],2);
						break;
				
					case 0x40:
						if(ch_wt[3]<700)
							{
							ch_wt[3] += wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[3]=700;
							spk(1,sysc2);
							}
						if(ch_wt[3]==580)spk(1,sysc1);
						ee_write(ch_wt[3],3);
						break;
					
					case 0x80:
						if(ch_wt[3]>460)
							{
							ch_wt[3] -= wtcs;
							spk(1,sysc);
							}
						else
							{
							ch_wt[3]=460;
							spk(1,sysc2);
							}
						if(ch_wt[3]==580)spk(1,sysc1);
						ee_write(ch_wt[3],3);
						break;
				
					default:break;
					}
				delay_ms(200);
				}
			}
/*		while(m=~PINB)
			{
			delay_ms(10);
			}*/
		if(dy_sj<dy1)			//如果电压低于7.4V
			{
			if(dy_sj>dy2)		//电压大于7V:慢闪报警
				{
				n ++;
				if(n>=100)
					{
					n=0;
					LED_TG;
					spk(1,20);
					}
				}
			else				//电压小于7V:快闪报警
				{
				LED_TG;
				spk(1,20);
				}
			}
		}
	}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -