背景图片
萝丽6通接收机二代G版(程序) - 啊和的博客

萝丽6通接收机二代G版(程序) - 啊和的博客 萝丽6通接收机二代G版(程序) - 啊和的博客

萝丽6通接收机二代G版(程序)

#include<reg52.h>
#include<intrins.h>
#define u8 unsigned char
#define u16 unsigned int

sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;

sbit LED=P3^6;	//定义指示灯

sbit CH1=P1^7;	//定义6个通道输出
sbit CH2=P1^6;
sbit CH3=P1^5;
sbit CH4=P1^4;
sbit CH5=P1^3;
sbit CH6=P1^2;

sbit MDO=P3^3;	//定义无线模块的管脚
sbit SCK=P3^4;
sbit CE=P3^5;
sbit IRQ=P3^2;
sbit MDI=P1^1;
sbit CSN=P1^0;



sfr P1M0=0x92;	//单片机IO口配置寄存器地址
sfr P3M0=0xb2;

u8 rx[17];		//接收的6字节数据
u8 tx[17]={0xc3,0x3c,12};
u8 k,n,w,tt,m;
u8 channel,connecting,hopping_turn;
bit cha,chb,chc,chd,che;

u8 missing_data[4];
u8 address[5];
u8 hopping[5];
bit first;
bit lose;
bit jump_1,jump_2;

bit restar;

void delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 11;
	j = 168;
	do
	{
		while (--j);
	} while (--i);
}

void delay4us()		//@12.000MHz
{
	unsigned char i;

	i = 8;
	while (--i);
}

void delay(u8 i)
{
	while(i--)
	delay4us();
}
void delay_ms(u8 i)
{
	while(i--)
	delay1ms();
}
u8 EEPROM_read(u8 address)
{
	IAP_CMD=0x01;
	IAP_ADDRH=0;
	IAP_ADDRL=address;
	IAP_TRIG=0x5a;			//EEPROM读写密码,不同系列单片机不同
	IAP_TRIG=0xa5; 
	return IAP_DATA;
}

void EEPROM_write(u8 address,u8 byte)
{
	IAP_CMD=0x02;
	IAP_DATA=byte;
	IAP_ADDRH=0;
	IAP_ADDRL=address;
	IAP_TRIG=0x5a;
	IAP_TRIG=0xa5; 
	
}

void EEPROM_clean(u8 address)
{
	IAP_CMD=0x03;
	IAP_ADDRH=0;
	IAP_ADDRL=address;
	IAP_TRIG=0x5a;
	IAP_TRIG=0xa5;
}

void DATA_read()
{
	IAP_CONTR=0x82;
	if(EEPROM_read(0)!=0xf5)	 
	{
	   first=1;
	   missing_data[0]=127;
	   missing_data[1]=127;
	   missing_data[2]=0;
	   missing_data[3]=127;
	}
	else
	{
	   	hopping[0]=EEPROM_read(1);
		hopping[1]=EEPROM_read(2);
		hopping[2]=EEPROM_read(3);
		hopping[3]=EEPROM_read(4);
		hopping[4]=EEPROM_read(5);
		address[0]=EEPROM_read(6);
		address[1]=EEPROM_read(7);
		address[2]=EEPROM_read(8);
		address[3]=EEPROM_read(9);
		address[4]=EEPROM_read(10);

		missing_data[0]=EEPROM_read(11);
		missing_data[1]=EEPROM_read(12);
		missing_data[2]=EEPROM_read(13);
		missing_data[3]=EEPROM_read(14);
	}
	
 
	IAP_CONTR=0;
}
void DATA_save()
{
	IAP_CONTR=0x82;
		EEPROM_clean(0);
		EEPROM_write(0,0xf5);
		EEPROM_write(1,hopping[0]);
		EEPROM_write(2,hopping[1]);
		EEPROM_write(3,hopping[2]);
		EEPROM_write(4,hopping[3]);
		EEPROM_write(5,hopping[4]);
		EEPROM_write(6,address[0]);
		EEPROM_write(7,address[1]);
		EEPROM_write(8,address[2]);
		EEPROM_write(9,address[3]);
		EEPROM_write(10,address[4]);

		EEPROM_write(11,missing_data[0]);
		EEPROM_write(12,missing_data[1]);
		EEPROM_write(13,missing_data[2]);
		EEPROM_write(14,missing_data[3]);

		IAP_CONTR=0;
}


u8 SPI(u8 byte)
{
	u8 i;
	for(i=0;i<8;i++)
	{
		MDI=(byte&0x80);
		SCK=1;
		byte<<=1;
		byte|=MDO;
		SCK=0;
	}
	return byte;
}

void REG_write(u8 address,u8 command)
{
	CSN=0;
	SPI(0x20+address);
	SPI(command);
	CSN=1;
}
/*
u8 REG_read(u8 address)
{
	u8 m;
	CSN=0;
	SPI(address);
	m=SPI(0);
	CSN=1;
	return m;
}	*/

void FIFO_write(u8 DATA_OUT[],u8 lengh)
{
	u8 i;
	CSN=0;
	SPI(0xa0);
	for(i=0;i<lengh;i++)
	SPI(DATA_OUT[i]);
	CSN=1;
}
void FIFO_read(u8 DATA_IN[],u8 lengh)		//读取接收数据缓冲区
{
	u8 i;
	CSN=0;
	SPI(0x61);	//读取命令
	for(i=0;i<lengh;i++)
	DATA_IN[i]=SPI(0);	   
	CSN=1;
}
/*
void TX_address(u8 DATA_IN[])
{
	CE=0;
	CSN=0;		 
	SPI(0x20+0x10);
	SPI(DATA_IN[0]);
	SPI(DATA_IN[1]);
	SPI(DATA_IN[2]);
	SPI(DATA_IN[3]);
	SPI(DATA_IN[4]);
	CSN=1;  
	CE=1;
}  */
void RX_address(u8 DATA_IN[])
{
	CE=0;
	CSN=0;		 
	SPI(0x20+0x0a);
	SPI(DATA_IN[0]);
	SPI(DATA_IN[1]);
	SPI(DATA_IN[2]);
	SPI(DATA_IN[3]);
	SPI(DATA_IN[4]);
	CSN=1;  
	CE=1;
}
void RX_mode()				 
{
	CE=0;		//先关闭模块,才能写命令寄存器
	REG_write(0x00,0x3b); //CRC,8 bit,Power on,RX
	CE=1;
} 				   
	
void TX_mode()				 
{
	CE=0;		 
	REG_write(0x00,0x0a);  
	CE=1;
}	 
void  TX_power_set(u8 H)
{
	CE=0;
	if(H)REG_write(0x06,0x27);		 
	else REG_write(0x06,0x21);  
	CE=1;
}
void TX_size_set(u8 l)
{
	CE=0;
	REG_write(0x11,l);  
	CE=1;
}
void channel_set(u8 c)
{
	CE=0;		 
	REG_write(0x05,c);  
	CE=1;
}


void NRF_init()
{	
	CE=0;
	SCK=0;
	REG_write(0x01,0x00); //unable ACK
	REG_write(0x02,0x01); //enable P0_RX
	REG_write(0x04,0x00); //unable ACK
	CE=0;	
	RX_mode(); 			  //CRC,8 bit,Power on,TX
	channel_set(66);
	TX_power_set(1);
	TX_size_set(8);
//	TX_address(address);
}

void initial()
{	
	 u8 t;
	
	CH5=0;			//如果CH5与CH6被短接,重新对码
	delay1ms();
	if(CH6==0)		  //新增修正通道6插上舵机不能用的BUG
	{
		P1M0=0x08;	  //插上舵机也会使CH6为0,所以将CH5设为推挽
		CH5=1;
		delay1ms();
		if(CH6)restar=1;   //如果CH6被拉高,说明5/6通道短接,启动重新对码
	}
	else restar=0;	  //如果CH5=0,CH6仍为1,则5/6通道无连接

	 
	CH5=1;

	LED=0;		//点亮指示灯1毫秒再关闭,表示单片机正常工作
	P1M0=0xfc;	//将6通道输出IO口配置为大电流推挽模式,保证正常驱动电调与舵机
	TMOD=0x11;	//允许两个定时器中断	
	IE=0x8a;
	  
	if(restar)first=1;

	DATA_read();  
	NRF_init();
	delay1ms();connecting=1;

	if(first)
	{
		TX_size_set(17);
		while(connecting)
		{
			while(IRQ);
			FIFO_read(rx,17);		//读取接收数据
			CE=0;
			REG_write(0x07,0x40);	//清除无线模块中断信号
			CE=1;
			if(rx[0]==0xaa&&rx[1]==0x55)
			{
				hopping[0]=rx[2];
				hopping[1]=rx[3];
				hopping[2]=rx[4];
				hopping[3]=rx[5];
				hopping[4]=rx[6];
				address[0]=rx[7];
				address[1]=rx[8];
				address[2]=rx[9];
				address[3]=rx[10];
				address[4]=rx[11];

				if(rx[12]==1)
				{
					missing_data[0]=rx[13];
					missing_data[1]=rx[14];
					missing_data[2]=rx[15];
					missing_data[3]=rx[16];
				}
				connecting=0;
			}
		}
	
		connecting=1;
		while(connecting)
		{
			TX_mode();		
			channel_set(66);TX_size_set(17);
			
			delay1ms();delay1ms();
			FIFO_write(tx,17);
			delay1ms();delay1ms();
			RX_mode();
			channel_set(hopping[0]);
			while(1)
			{
				delay1ms();
				if(IRQ==0)
				{
					FIFO_read(rx,17);		//读取接收数据
					CE=0;
					REG_write(0x07,0x40);	//清除无线模块中断信号
					CE=1;	 
					 	connecting=0;
				}
				t++;if(t>30){t=0;break;}
			}
			  
		} 
		LED=1;
		DATA_save();
		TX_size_set(8);
		RX_address(address);
	}
	else
	{
		RX_address(address);	
	} 
//	while(1);
}
																		     

main()
{	
	delay_ms(200);delay_ms(200);//开机延时以避过电源波动
	initial();

		TR0=1;		//打开定时器0,开始统计信号
	LED=1;
	channel_set(hopping[0]);
	lose=1; 
	while(1)
	{	
		while(IRQ&&lose);TR1=1;	//等待无线模块的中断信号,直到第一个有效信号再开始输出6通道信号
		if(lose)
		{
			 tt=0;m=0;jump_1=0;jump_2=0;		//收到有效信号后刷新定时器0、跳频器
			k++;				//每收到一个有效信号自加一
			FIFO_read(rx,8);		//读取接收数据
			CE=0;
			REG_write(0x07,0x40);	//清除无线模块中断信号
			CE=1;
			hopping_turn++;
			if(hopping_turn>4)hopping_turn=0;
			channel_set(hopping[hopping_turn]);
		}
		else
		{
		 	hopping_turn++;
			if(hopping_turn>4)hopping_turn=0;
			channel_set(hopping[hopping_turn]);
			lose=1;
		}
		
	
	}
}

void et0()interrupt 1			//定时器0用作信号统计,定时周期65ms
{
	tt++;w++;

	if(w==15)			//每秒统计接收到的有效信号数量,小于20个点亮LED示警,表示信号微弱
		{
			if(k<20)LED=0;
			else LED=1;
			k=0;w=0;
		}
	if(tt>30)//如果tt增长到30,表示已经有两秒未收到有效信号,执行失控保护舵量
	{
		tt=30;
		rx[0]=missing_data[0];
		rx[1]=missing_data[1];
		rx[2]=missing_data[2];
		rx[3]=missing_data[3];
	}	
}

void et1()interrupt 3	//定时器1用作信号输出,定时周期3ms
{
	TH1=0xf4,TL1=0x47;
	
	m++;					//两个标志位循环跳频
	if(jump_1==0)
	{
		if(m>7)lose=0,jump_1=1,jump_2=0;	  //未收到信号,开始第一跳
	}
	else
	{
		if(jump_2==0)
		{
			if(m>14)lose=0,jump_2=1;		 //第一跳之后仍无信号,开始第二跳
		}
		else
		{
			 if(m>22)m=0,lose=0,jump_1=0;	 //第二跳之后仍无信号,复位重新跳。
		}		
	}
		
	n++;
	if(n==6)n=0;		//轮流输出6通道信号,整个周期18ms,输出频率55HZ
	switch(n)
	{
		case 0:CH1=1,delay1ms(),delay(rx[0]),CH1=0;break;//1ms固定高电平,256级控制,每级4us
		case 1:CH2=1,delay1ms(),delay(rx[1]),CH2=0;break;//舵机控制原理,0.5ms高电平对应最左端
		case 2:CH3=1,delay1ms(),delay(rx[2]),CH3=0;break;//1.5ms高电平对应舵机中点
		case 3:CH4=1,delay1ms(),delay(rx[3]),CH4=0;break;//2.5ms高电平对应舵机最右端
		case 4:CH5=1,delay1ms(),delay(rx[4]),CH5=0;break;//实际控制取1至2ms
		case 5:CH6=1,delay1ms(),delay(rx[5]),CH6=0;break;
	}
						//每次输出信号费时1至2ms,剩余时间空闲,跳回主程序接收新数据
}


评论 0

挤眼 亲亲 咆哮 开心 想想 可怜 糗大了 委屈 哈哈 小声点 右哼哼 左哼哼 疑问 坏笑 赚钱啦 悲伤 耍酷 勾引 厉害 握手 耶 嘻嘻 害羞 鼓掌 馋嘴 抓狂 抱抱 围观 威武 给力
提交评论

清空信息
关闭评论