最近在接了一个项目,要求各个设备能够联网(不是互联网)控制。nrf24l01刚好有这个功能。但是之前只做过一对一的通信,还是用例程的那一种。我在想,用两个地址,共用同一个通道应该也可以完成。后来他又要求发过去的数据还要能回传,这下我只好来研究多通道通信了。
多机通信和一对一通信基本上相同,就是要配置其他通道的地址和使能其他通道的有效数据宽度,还有自动应答。
这是接收机的:
void NRF24L01_Init_RX(void)
{
CE=0;
CSN=1;
SCK=0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH);
SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);
SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);
SPI_Write_Reg(WRITE_REG + RF_CH, 40);
SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F);
SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f);
}
由于我用的是KeilC51和MDK5共存的,所以注释复制过来之后就成了乱码,在此贴图一张:
NRF24L01_Init_Rx(void)
下面就到了发送机了的配置了:
void NRF24L01_Init_TX(uint8_t *ADDRn)
{
CE=0;
CSN=1;
SCK=0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, (uint8_t*)ADDRn, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH);
SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);
SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);
SPI_Write_Reg(WRITE_REG + RF_CH, 40);
SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0xff);
SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);
SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E);
}
同样:
NRF24L01_Init_TX(uint8_t *ADDRn)
发送给其他通道,只要改成其他通道的地址就可以了,不用改通道号,现在还不知道为什么。
接下来就是发送函数:
uint8_t nRF24L01_TxPacket(unsigned char * tx_buf)
{
uint8_t Return_Flag=0;
CE=0;
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
Delayms(2);
Return_Flag = Check_ACK(1);
return Return_Flag;
}
由于我是通过电脑串口控制上位机,发给某一个下位机,然后再发回到我的上位机中,最后回传到电脑,所以没有数据抢答的问题。
最后再说一句,要配置第N个的通道,前N个通道也必须被配置,要不然配置不成功。
最后贴上上位机程序:
#include #include #include "nrf24l01.h" #include "delay.h" #define uint32_t unsigned int #define uint8_t unsigned char uint8_t const RX_ADDRESS[TX_ADR_WIDTH]= {0x01,0x13,0x5C,0x0C,0x03}; //本地地址 uint8_t const RX_ADDRESS1[TX_ADR_WIDTH]={0x02,0x13,0x5C,0x0C,0x03}; //本地地址1 extern uint8_t Rx_Buf[32]; extern uint8_t Tx_Buf[32]; /**********************************RNF24L01状态标志位************************************************/ uint8_t bdata sta; sbit RX_DR =sta^6; sbit TX_DS =sta^5; sbit MAX_RT =sta^4; /**********************************NRF24L01管脚与单片机接口定义**************************************/ sbit MISO =P3^4; sbit MOSI =P3^6; sbit SCK =P3^3; sbit CE =P3^2; sbit CSN =P3^5; sbit IRQ =P3^7; /*************************************************************************** 函数名称:uchar SPI_RW(uint8_t dat) 函数功能:NRF24L01的SPI写时序 函数备注: ***************************************************************************/ uint8_t SPI_RW(uint8_t dat) { uint8_t i; for(i=0;i<8;i++) { MOSI = (dat & 0x80); dat = (dat << 1); SCK = 1; dat |= MISO; SCK = 0; } return(dat); } /*************************************************************************** 函数名称:uint8_t SPI_Read(uint8_t cmd_reg) 函数功能:NRF24L01的SPI读时序 函数备注: ***************************************************************************/ uint8_t SPI_Read(uint8_t cmd_reg) { uint8_t value; CSN = 0; SPI_RW(cmd_reg); value = SPI_RW(0); CSN = 1; return(value); } /*************************************************************************** 函数名称:void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value) 函数功能:写入NRF24L01寄寄存器和从NRF24L01寄存器中读出 函数备注: ***************************************************************************/ void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value) { CSN = 0; SPI_RW(cmd_reg); SPI_RW(value); CSN = 1; } /*************************************************************************** 函数名称:uint8_t SPI_Read_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num) 函数功能:从NRF24L01寄存器中读出数据 函数备注:reg:为寄存器地址,pBuf:为待读出数据地址,uint8_t:读出数据的个数 ***************************************************************************/ uint8_t SPI_Read_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num) { uint8_t status,i; CSN = 0; status = SPI_RW(cmd_reg); for(i=0;i return(status); } /*************************************************************************** 函数名称:void SPI_Write_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num) 函数功能:在NRF24L01寄存器中写入数据 函数备注:reg:为寄存器地址,pBuf:为待写入数据地址,uint8_t:写入数据的个数 ***************************************************************************/ void SPI_Write_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num) { uint8_t i; CSN = 0; //SPI使能 SPI_RW(cmd_reg); for(i=0; i } /*************************************************************************** 函数名称:uint8_t nRF24L01_RxPacket(uint8_t* rx_buf) 函数功能:数据读取后放入rx_buf接收缓冲区中 函数备注: ***************************************************************************/ uint8_t nRF24L01_RxPacket(uint8_t* rx_buf) { uint8_t flag; CE = 1; //很重要!启动接收! Delayms(1); sta=SPI_Read(READ_REG+STATUS); // 读取状态寄存其来判断数据接收状况 //寄存器前面要加是读还是写 if(RX_DR) // 判断是否接收到数据 如果置1则说明接到数据并且放置在接收缓存器 { CE = 0; SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH); //这本来就是指令,不用加,意思说去缓存器里读 flag =1; //读取数据完成标志 } SPI_Write_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志 return flag; } /************************************************** 函数:Check_ACK(bit clear) 描述:检查接收设备有无接收到数据包,设定没有收到应答信 号是否重发 /**************************************************/ uint8_t Check_ACK(bit clear) { while(IRQ); sta = SPI_RW(NOP); // 返回状态寄存器 if(MAX_RT) if(clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发 SPI_RW(FLUSH_TX); //清空寄存器,很重要!!! SPI_Write_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中断标志 IRQ = 1; if(TX_DS) return(0x01); else return(0x00); } /*************************************************************************** 函数名称:void nRF24L01_TxPacket(unsigned char * tx_buf) 函数功能:发送 tx_buf中数据 函数备注: ***************************************************************************/
上一篇:按键PWM控制led亮度单片机源程序
下一篇:ESP8266无线18B20温度手机接收有源代码和开源
推荐阅读
史海拾趣
在成都启臣微电子股份有限公司成立之初,公司就致力于集成电路及系统产品的设计、生产与销售。面对激烈的市场竞争,启臣微坚持创新,投入大量研发资源,终于在高性能功率管理集成电路领域取得了重大技术突破。这一突破不仅提升了公司的市场竞争力,也为公司赢得了业界的广泛认可。
为了进一步提升竞争力,BERGQUIST公司开始寻求产业链整合和战略合作。公司与上游原材料供应商建立了长期稳定的合作关系,确保原材料的质量和供应稳定性。同时,公司还与下游电子设备制造商开展深度合作,共同研发定制化的热管理解决方案。这些举措不仅降低了公司的运营成本,还提高了产品的市场竞争力。
在追求经济效益的同时,DIOFIT公司也积极履行社会责任,致力于环保事业。他们注重节能减排和资源循环利用,采用环保材料和生产工艺,降低产品对环境的污染。同时,DIOFIT公司还积极参与各类公益活动,为社会发展和环境保护贡献自己的力量。
Murata是一家历史悠久的电子元器件公司,他们早在电子设备发展的初期就认识到了EMI滤波器的重要性。随着电子产品的不断小型化,Murata看到了小型化EMI滤波器的巨大市场需求。他们通过与多家科研机构和高校合作,成功研发出了一系列高性能、小型化的EMI滤波器。这些滤波器不仅性能优越,而且体积小巧,非常适合用于现代电子设备中。Murata因此赢得了大量的市场份额,并成为了EMI滤波器领域的佼佼者。
随着电子行业的快速发展和变革,Fascomp面临着前所未有的挑战。为了应对这些挑战,公司决定进行转型升级。一方面,公司加大了对人工智能、物联网等新兴技术的研发投入;另一方面,公司还优化了生产流程和管理模式,提高了生产效率和产品质量。这些举措使Fascomp在行业中保持了领先地位。
本帖最后由 paulhyde 于 2014-9-15 03:33 编辑 来源:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3648721&bbs_page_no=1&bbs_id=9999 暑假学校里做机器人比赛,就是做出一个人型机器人来互相对打,要求无线控制的。 我因为去年做过这个 ...… 查看全部问答∨ |
|
应用场合不同,选择交流或直流取决于线圈,直流接触器的线圈只能通直流,交流接触器的线圈只能通交流工作。一般来说,在交流回路当中,主回路用的交流,辅助助回路一般都是从主回路上取电做控制回路,那么控制回路显然也是交流的,那么就要用交流接 ...… 查看全部问答∨ |
|
#include <STM8S105C_S.h> #define uchar unsigned char #define uint unsigned int #define data_out PB_DDR|=0X04; #define data_in PB_DDR&=~0X04; #define scl_H PB_ODR|=0X02; #define scl_L PB_ODR&=~0X02; #define sda_ ...… 查看全部问答∨ |
|
lowlevel_init.S的system_clock_init函数放到C语言下面实现——更好处理 在uboot原来的代码里,有系统时钟的初始化函数,在board/samsung/smdkv210/lowlevel_init.S的system_clock_init函数,我大概看了一下,寄存器不一样,而且是汇编写的,所以我就改成用c语言来实现,在BL1阶段初始化一下,BL2阶段就不用重新初始化了 ...… 查看全部问答∨ |
两种加法电路与对应的描述方程。 先对第一种分析,图示第一种比较简单,我们知道运放的Vin-=Vin+。所以第一个电路图上三个电阻的公共节点电势Vin-=0. (V1/R1)+(V2/R2)=(0-Vout)/RF。移项处理后就得到了公式中的第一个:Vout=-(Rf/R1)*V1-(RF/R2 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 下载有礼:数据中心养生秘籍《福禄克数据中心解决方案》等你带回家!
- 6月6日 Microchip 直播|利用单片机设计安全关键型应用时应采取的最佳实践方法
- 助人为乐,打榜领奖: EEWORLD月度问答榜换新推出~
- 你有原创,我有豪礼!(原创精选评选第7期)
- NI labview、CompactDAQ技术集锦
- 看是德科技利用校准降低仪器测量不确定度、提高测试精度 直播享好礼!
- 好书共读 | 《控制之美(卷2)——最优化控制MPC与卡尔曼滤波器》
- 团结起来,问倒TI专家团!!!
- 有奖直播 | 英飞凌新型固态隔离器的创新技术与应用设计
- 下载有礼|是德科技电子书 《通过了解测试精度的基础知识, 提高良率并降低风险》,不做“差不多先生”