历史上的今天
今天是:2024年11月25日(星期一)
2019年11月25日 | NRF24L01无线模块多机通信单片机程序 上位机+下位机
2019-11-25 来源:51hei
最近在接了一个项目,要求各个设备能够联网(不是互联网)控制。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中数据 函数备注: ***************************************************************************/
史海拾趣
|
我们公司现在做一个报警控制器,需要支持Contact Id 协议,但自己以前没有做过,而且那个协议文档写的不是很清楚,希望以前做过的能指点一下,或者也可以和我们公司合作(你以前做过硬件电路和软件实现)。 QQ:275556641 Email: yuangangaaa@163 ...… 查看全部问答> |
|
想问一下Core OS\\Core OS Services\\USB Host Support下的内容已经Add to OS Desgin,但USB的键盘和鼠标还是没有用,并且开机时蜂鸣器长响,是什么原因? 另外,Device Drivers\\USB Function 和USB Host 之间的区别?… 查看全部问答> |
|
LED怀表”这是一个DIY作品,作者觉得这可能是第一个LED怀表,来自Paul,其对祖父留下来的一个旧怀表进行改造,当然能用的也只有怀表的外壳。 怀表里面一共安装了133个LED,每一个都是手工焊接而成,LED可显示60秒、60分钟和12小时,另外还有一 ...… 查看全部问答> |
|
我下的iar ewarm5.30照别个说的方法怎么补能破解呢? 未命名.JPG (53.53 KB) 下载次数:7 2010-6-15 20:52 … 查看全部问答> |
|
帮忙看看2407点灯的程序吧,为什么lacc #8语句中输入>8的数时,在单步调试运行时,延时程序就跳不出来了,好像死机了似的。可是lacc #8语句中输入<=8的数就什么问题都没有。快帮忙看看吧,我都在这个问题上停留好长 ...… 查看全部问答> |




