毕昇杯之无线通信模块
在这个比赛中,我们使用的是24L01这个无线模块,说句实在话,这个模块的功能不是很强大,出错的机率比较大,加上这个模块需要3.3v供电,所以对于5v的系统来讲,这个模块算比较麻烦的一个,这个模块比较容易坏,也许就是取电哪里,我开始没有共地的原因吧!!!
网络上有许多无线的模块,我觉得开始的时候就不应该选择这个无线,因为模块越简单,编程就越复杂,加上我需要4块单片机之间进行通信,其实程序也就是2对1,温湿度采集单片机A,刷卡采集B,屏幕处理C,以及网络模块D,开始无线程序只是简单的一对一,项目开始的时候,就应该把节点搭建好,否则的话,程序就要进行一次大的调整
在这里我们的项目就因为调试无线程序,大改了好几次,最终实现的只是A,B对C发送数据,之后复制C这个节点到D,那样A,B也可以对D发送数据,但是这样的程序上有个很大的bug,就是c和D不能进行通信,这样对硬件的调整有相当的坑爹了,为了弥补C和D可以同时控制硬件的难题,我们采用了双头开关,也就是使用卧室灯可以由两个开关进行控制这个原理,这样C和D就可以同时控制硬件
也许到这里,一切的问题貌似结束了,但是,双头开关导致的先天不足,在项目后期,就就完全暴露了,因为双头开关只是仅仅控制灯的开灭,但是却不能使用进一步的算法,比如控制几盏灯以什么样的亮度开着,不能控制风扇以什么样的转速转动,这些都是先天的设计导致的一大败笔~~~~但不得不承认,这样的硬件结构,实现起来比较可靠,他们蔬菜大棚使用的是用一块单片机对硬件进行处理,但是好像不怎么可靠,也许双头开关刚好弥补了无线的不足吧!!!!
好了无线的使用心得就总结到这里,下面看一下如何使用无线搭建两个节点的
程序下载地址:http://download.csdn.net/detail/generoius/7140597
下面具体看一下无线通信是怎么样实现的
温湿度传感器,开发板A的程序:发送地址为:unchar code TxAddr[]={0x34,0x43,0x10,0x10,0x01};
刷卡模块,开发板B的发送地址为:unchar code TxAddr[]={0xc2,0xc2,0xc2,0xc2,0xc1};//发送地址
主机接收处理地址为开发板c的接收地址:unchar code RxAddr0[]={0x34,0x43,0x10,0x10,0x01};//编号3接收地址这个地址和发送方地址一样!
unchar code RxAddr1[]={0xc2,0xc2,0xc2,0xc2,0xc1};
可以看出主机同时可以接收两个地址传送过来的信号,这里便是通道0和通道1共同监控的地址
接下来在看变量设置,在主机中定义了如下两个数组,用来监控接收回来的数据
unchar RevTempDate0[16];//同道0接收数据
unchar RevTempDate1[16];//同道1接收数据
之后在看寄存器设置:
这里板子A和板子B的设置都是相差不多,因为主要是发送,所以寄存器设置是一样的
void NRFSetTxMode(unchar *TxDate) {//发送模式 CE=0; NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度 NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同 NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据 /******下面有关寄存器配置**************/ NRFWriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答 NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0 NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次 NRFWriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40 NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 NRFWriteReg(W_REGISTER+CONFIG,0x0e); // CRC使能,16位CRC校验,上电 CE=1; Delay(5);//保持10us秒以上 }
这里主要值做好板子c的接收设置,熟悉datasheet的人,就会知道nrf24l01有6个通道,可以同时监控6个节点传过来的数据,这个与起性比价形成鲜明的对比
void NRFSetRXMode() { CE=0; NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,RxAddr0,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址 NRFWriteTxDate(W_REGISTER+RX_ADDR_P1,RxAddr1,TX_ADDR_WITDH); // 接收设备接收通道1使用和发送设备相同的发送地址 NRFWriteReg(W_REGISTER+EN_AA,0x03); // 使能数据通道0和1自动应答 NRFWriteReg(W_REGISTER+EN_RXADDR,0x03); // 使能接收通道0和1 NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH); // 接收通道0选择和发送通道相同有效数据宽度 NRFWriteReg(W_REGISTER+RX_PW_P1,TX_DATA_WITDH); // 接收通道1选择和发送通道相同有效数据宽度 NRFWriteReg(W_REGISTER+RF_CH,0x40);// 选择射频通道0x40 NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 NRFWriteReg(W_REGISTER+CONFIG,0x0f); // CRC使能,16位CRC校验,上电,接收模式 CE = 1; NRFDelay(5); }
再来看他是如何区分来自不同通道的数据的
void GetDate() { unchar RX_P_NO;//接收通道号 sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器 if(RX_DR) // 判断是否接收到数据 { RX_P_NO=sta&0x0e;//获取通道号 CE=0;//待机 switch(RX_P_NO) { case 0x00:NRFReadRxDate(R_RX_PAYLOAD,RevTempDate0,RX_DATA_WITDH);break;// 从RXFIFO读取数据通道0 case 0x02:NRFReadRxDate(R_RX_PAYLOAD,RevTempDate1,RX_DATA_WITDH);break;// 从RXFIFO读取数据通道1 default:break; } lcd_pos(1,0); write_string(RevTempDate0); lcd_pos(2,0); write_string(RevTempDate1); MAX232SendDate();//发送数据到上位机 NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标 CSN=0; NRFSPI(FLUSH_RX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!! CSN=1; } //NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标 }
我没有在往下面研究了,到这里的无线发送就够用了,还有一个事情,就是多看datasheet,结合例子看,调试程序串口是个好东西,好了,无线总结到这里!!
版权所有,转载请注明链接地址:http://www.cnblogs.com/fengdashen/p/3642757.html
技术讨论QQ:1070937053