nrf24l01是适合初学入门的无线模块_第1页
nrf24l01是适合初学入门的无线模块_第2页
nrf24l01是适合初学入门的无线模块_第3页
nrf24l01是适合初学入门的无线模块_第4页
nrf24l01是适合初学入门的无线模块_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、24l01 的多机通信采用频分多子的方法,只需要在接受端对不同的通道配置地址即可。发送端使用相应的地址作为本机地址。接受数据时通过读取STATUS中相关位即可得知接收的是哪个通道的数据。以下仅给出多对一的通信代码。至于一对多,以及多对多等情况读者可以自行研究了。只给出相关部分,其他部分请参考前两篇文章频道 0 接收地址频道 1 接收地址接受端uint const ADDRESS0ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; /uint const ADDRESS1ADR_WIDTH= 0xc4,0xc3,0xc2,0xc1,0xc0; / uchar who=0xf

2、f;/*/*NRF24L01 初始化/*/void init_NRF24L01(void)us(100);CE=0; / chip enableCSN=1; / Spi disableSCK=0; / Spi clock line init high/SPI_Write_Buf(WRITE_REG + TX_ADDR,ADDRESS0, ADR_WIDTH); / 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0,ADDRESS0,ADR_WIDTH); / 频道 0 地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P1,ADDRESS

3、1,ADR_WIDTH); / 频道 1 地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x03);/ 频道 0、1 自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x03);/ 允许频道 0、 1SPI_RW_Reg(WRITE_REG + RF_CH, 0);/设置信道工作为 2.4GH Z,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /接0 收数据长度SPI_RW_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); /接1 收数据长度SPI

4、_RW_Reg(WRITE_REG + RF_SETUP, 0x07); /设置发射速率为 1MHZ 发射功率为最大值 0dB'*/* 函数: unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/* 功能:数据读取后放如 rx_buf 接收缓冲区中 /*/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) unsigned char revale=0; sta=SPI_Read(STATUS); / 读取状态寄存其来判断数据接收状况 if(RX_DR) / 判断是否接收到

5、数据CE = 0;SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);revale =1;who=sta&0x0e;who|=0xf0; / 通道 0: who=0xf0; 通道 1: who=0xf2 SPI_RW_Reg(WRITE_REG+STATUS,Oxff); / 接收到数据后 RX_DR,TX_DS,MAX_P都置高为 1,通过写 1 来清楚中断标志CSN=0;SPI_RW(FLUSH_RX);CSN=1;return revale;void main(void)uchar i;uchar RxBufTX_PLOAD_WIDTH

6、;init_NRF24L01() ;StartUART();ms(6000);while(1) / 如果接收到数据,发往 PCSetRX_Mode();if(nRF24L01_RxPacket(RxBuf)R_S_Byte(who);ms(10000);for(i=0;i<TX_PLOAD_WIDTH;i+)R_S_Byte(RxBufi);ms(10000); 发 送 1uint const ADDRESS0ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01;其余与双工通信相同 发 送 2uint const ADDRESS1ADR_WIDTH= 0xc4,0xc3

7、,0xc2,0xc1,0xc0; /频道 1 接收地址其余与双工通信相同以上就是简要的代码。也是重要的地方。如果发送端要发送数据的话, 可能在配置自动应答的接受地址时会遇到一些问题。 (因为是 以通道 0 作为应答通道, 而发送模式又必须使得接收发送地址一致, 这样给两台发送机发数 据就要对 0 实时配置地址)笔者尝试过配置, 没有成功, 只好不配置了,都是这样接收端无 法接收到自动应答的信号 24l01 双向通讯2010-11-19 21:28 一周的时间过去了,终于搞出来了双向通讯,中间出了点莫名奇妙的情况, 导致我迷惘了很久。上次发的头文件和 .c 文件有个模式设置的选项。在做双向通信的

8、时候发现 这个有点多余。所以就删掉了,内容也做了些小改动。所以就只发修改的部分24l01.h这个文件和之前的一样。只去掉/ 模式选择/#define RMODE#define TMODE这几行24l01.c修改了三个地方。分别是1、/*/*NRF24L01 初始化/* 这里不用设置什么模式,等需要接受或发送数据时指定模式/*/void init_NRF24L01(void)us(100);CE=0; / chip enableCSN=1; / Spi disableSCK=0; / Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADD

9、R, TX_ADDRESS, TX_ADR_WIDTH); /写/ 本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH写 / 接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);/ 频道 0 自动 ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); /允/许接收地址只有频道 0,如 果需要多频道可以参考 Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0);/ 设置信道工作为 2.4GHZ,收发必须一致SPI_RW_

10、Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDT设)置接收数据长度, 本次设置为 32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);/ 设置发射速率为 1MHZ 发射功率为最大值 0dB2、/* */* 函数: void SetRX_Mode(void)/* 功能:数据接收配置*/void SetRX_Mode(void)CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ 收发完成中断响应, 16 位 CRC ,主接收CE = 1;us(130);3、/*/* 函数: void nR

11、F24L01_TxPacket(unsigned char * tx_buf)/* 功能:发送 tx_buf 中数据 /*/void nRF24L01_TxPacket(unsigned char * tx_buf)CE=0; /StandBy I 模式SPI_Write_Buf(WRITE_REG + RX_ADDR_PO, TX_ADDRESS, TX_ADR_WIDTH 装/ 载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); / 装载数据 SPI_RW_Reg(WRITE_REG + CONFIG, OxOe); / IR

12、Q 收发完成中断响应, 16 位CRC主发送CE=1; /置高CE激发数据发送us(1O);以上就是全部的修改。这两个文件同样适用于单工通信。以下给出这次测试用的两个主函数。 为了方便与上次的文章对应。 这里还是以接 收,发送区分。 接收#include "nrf24lO1.h"#include "delay.h"uchar TxBufTX_PLOAD_WIDTH=0x55,0xaa;/* 串*void StartUART( void ) / 波特率 2400SCON = 0x50;TMOD= 0x20;TH1 =0xF3;TL1 =0xF3;PCON=

13、 0x00;TR1 =1;/*通过串口将接收到数据发送给PC端void R_S_Byte(uchar R_Byte)SBUF = R_Byte;while( TI = 0 ); /TI = 0;查询法/* 主函数*void main(void)uchar i;uchar RxBufTX_PLOAD_WIDTH;init_NRF24L01() ;StartUART(); ms(6000); while(1) / 如果接收到数据,发往 PC SetRX_Mode(); if(nRF24L01_RxPacket(RxBuf) for(i=0;i<TX_PLOAD_WIDTH;i+) R_S_B

14、yte(RxBufi);/ 发送 0x55, 0xaa 要求发送端发数据 nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,OXFF)加上这句后,会出现接收到几组数 据后停止了接收的现象,原因未知ms(13O);/ 这个延时很重要,延时过短,数据包丢失。/ 延时过长,减慢速度,甚至无法接收(实验时出现的问题,原因未知) RxBufO=O;RxBuf1=O;发送include "nrf24lO1.h"#include "delay.h"uchar TxBufTX_PLOAD_WIDTH=OxO1,Ox

15、O2;void main()char RxBufTX_PLOAD_WIDTH=O; init_NRF24LO1() ;nRF24LO1_TxPacket(TxBuf);ms(6OOO);while(1)SetRX_Mode();if(nRF24LO1_RxPacket(RxBuf)/ 将收到的数据发回接收端检验是否正确/ 如果设置的数据较长,应使用 for 循环 TxBufO=RxBufO;TxBuf1=RxBuf1;nRF24LO1_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,OXFF); ms(9O);/ 这个延时一样很重要RxBufO=O;Rx

16、Buf1=0;以上就是这周忙活的东西了,高手不要见笑。PS:原先想要使用自动重发功能的,结果发现自动重发的话,传输速率很慢,没 有延时的快。也可能是我自动重发的延时没设置好。另外最开始几天一直在做中断通信, 如果使用IRQ上中断来接受数据,可以明显 减轻MCI的负担。可是我测试了几天下来发现一个无语的结果。在中断里读出来 的STATUS的值是0x00,顿时心灰意冷。网上有其他人貌似做出来了,可惜我写 的跟他们一样也不行啊 ,不知道问题在哪。 但有一点是肯定的: 接收到数据 时必然引起中断。过几天继续贴出多机通信的代码。nrf24l01 的 51 驱动程序2010-11-13 18:58随着物联

17、网时代的到来,无线通信技术日趋重要。nrf24l01 是适合初学入门的无线模块。于是乎我就一头埋进去,苦干一周 有余。发现网上的程序都是抄来抄去的,不甚寒心。抄也就算了,光抄错的!后 来自己动手研究,完成了 SPI 接口的操作,继续攻克无线模块,最终无果,只好 再找代码。终于找到了一个可以的。本来想直接贴出来的, 但为了许多和我曾经一样迷茫的同胞可以顺利进入无 线领域。我特意修改代码,整理出 nrf24l01.h 与 nrf24l01.c ,一则便于模块化 管理,二则,便于使用,便于二次开发。同时,增加了许多注释。代码中应该还有许多不足的,甚至多余的东西,后续将会继续发表一篇关 于无线模块开发

18、的注意事项。/nrf24l01.h #ifndef NRF24L01_H #define NRF24L01_H #include <reg52.h> / 模式选择/#define RMODE#define TMODE端口typedef unsigned char uchar; typedef unsigned char uint;/*sbit CE = P19/3 sbit SCK = P1A1;/5 sbit MISO = P1A2;/7 sbit CSN = P1A5;/4 sbit MOSI = P1A6;/6 sbit IRQ = P1A7;/8地址、数据长度* #defi

19、ne TX_ADR_WIDTH 5 / 5 uints TX address width#define RX_ADR_WIDTH 5 / 5 uints RX address width#define TX_PLOAD_WIDTH 32 / 20 uints TX payload#define RX_PLOAD_WIDTH 32 / 20 uints TX payloadNRF24L01寄存器指令*#define READ_REG0x00 /#define WRITE_REG0x20 /#define RD_RX_PLOAD 0x61 / #define WR_TX_PLOAD 0xA0 /

20、#define FLUSH_TX0xE1 /#define FLUSH_RX0xE2 /#define REUSE_TX_PL 0xE3 / #define NOP0xFF /读寄存器指令 写寄存器指令 读取接收数据指令 写待发数据指令 冲洗发送 FIFO 指令 冲洗接收 FIFO 指令 定义重复装载数据指令 保留*SPI(nRF24L01)寄存器地址*#define CONFIG 0x00 / 响应方式#define EN_AA 0x01 / #define EN_RXADDR 0x02 / #define SETUP_AW 0x03 / #define SETUP_RETR 0x04 /

21、#define RF_CH 0x05 / #define RF_SETUP 0x06 / #define STATUS 0x07 / #define OBSERVE_TX 0x08 / #define CD0x09 /#define RX_ADDR_P00x0A /#define RX_ADDR_P10x0B /配置收发状态,CRC校验模式以及收发状态自动应答功能设置 可用信道设置 收发地址宽度设置 自动重发功能设置 工作频率设置 发射速率、功耗功能设置 状态寄存器 发送监测功能 地址检测 频道 0 接收数据地址 频道 1 接收数据地址#define RX_ADDR_P2 0x0C / #de

22、fine RX_ADDR_P3 0x0D / #define RX_ADDR_P4 0x0E / #define RX_ADDR_P5 0x0F / #define TX_ADDR 0x10 / #define RX_PW_P00x11 /#define RX_PW_P10x12 /#define RX_PW_P20x13 /#define RX_PW_P30x14 /#define RX_PW_P40x15 /#define RX_PW_P50x16 /#define FIFO_STATUS 0x17 /频道 2 接收数据地址 频道 3 接收数据地址 频道 4 接收数据地址 频道 5 接收数

23、据地址 发送地址寄存器 接收频道 0 接收数据长度 接收频道 0 接收数据长度 接收频道 0 接收数据长度 接收频道 0 接收数据长度 接收频道 0 接收数据长度 接收频道 0 接收数据长度栈入栈出状态寄存器设置*void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);

24、 uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf);/*#endif/nrf24l01.h 结束/nrf24l01.c #include "nrf24l01.h"#include "delay.h" uint bdata sta; / 状态标志sbit RX_DR =staA6;sbit

25、 TX_DS =staA5;sbit MAX_RT =staA4;uint const TX_ADDRESSTX_ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; / 地地址uint const RX_ADDRESSRX_ADR_WIDTH= 0x34,0x43,0x10,0x10,0x01; /收地址/* /*NRF24L01 初始化/*/void init_NRF24L01(void)us(100);CE=0; / chip enableCSN=1; / Spi disableSCK=0; / Spi clock line init highSPI_Write_Bu

26、f(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); /写/ 本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH写 / 接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);/ 频道 0 自动 ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); /允/许接收地址只有频道 0,如 果需要多频道可以参考 Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0);/ 设置信道工作为

27、2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDT设)置接收数据长度, 本次设置为 32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);/ 设置发射速率为 1MHZ 发射功率为最大值 0dB#ifdef RMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);/ IRQ 收发完成中断响应, 16位CRC,主接收#endif#ifdef TMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0E);/ IRQ 收发完成中断响应, 16位CRC,主

28、接收#endif/* */* 函数:uint SPI_RW(uint uchar)/*功能:NRF24L0的SPI写时序/* */uint SPI_RW(uint uchar)uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr+) / output 8-bit/ output 'uchar', MSB to MOSI / shift next bit into MSB./ Set SCK high./ capture current MISO bit/ .then set SCK low againMOSI = (uchar &

29、; 0x80); uchar = (uchar << 1);SCK = 1; uchar |= MISO;SCK = 0;/ return read uchar return(uchar);/*/* 函数: uchar SPI_Read(uchar reg)/*功能:NRF24L0的SPI时序/* */uchar SPI_Read(uchar reg)uchar reg_val;/ CSN low, initialize SPI communication. / Select register to read from.CSN = 0;SPI_RW(reg);/ CSN high,

30、 terminate SPI communication/ return register valuereg_val = SPI_RW(0); / .then read registervalue CSN = 1;return(reg_val);/* */*功能:NRF24L0读写寄存器函数/*/uint SPI_RW_Reg(uchar reg, uchar value)uint status;CSN = 0; status = SPI_RW(reg); SPI_RW(value);CSN = 1;/ CSN low, init SPI transaction / select regist

31、er/ .and write value to it./ return nRF24L01 status uchar/ CSN high again return(status);/*/* 函数: uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能:用于读数据,reg :为寄存器地址,pBuf:为待读出数据地址,uchars : 读出数据的个数/* */uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)uint status,uchar_ctr;CSN = 0;/ Se

32、t CSN low, init SPI tranactionstatus = SPI_RW(reg); / Select register to write to and read status uchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr+)pBufuchar_ctr = SPI_RW(0); /CSN = 1;return(status);/ return nRF24L01 status uchar/*/* 函数: uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功

33、能:用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars :写入 数据的个数/* */uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)uint status,uchar_ctr;CSN = 0; /SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr+) / SPI_RW(*pBuf+);CSN = 1; / 关闭 SPI return(status); /* */* 函数: void SetRX_Mode(void)/*

34、功能:数据接收配置*void SetRX_Mode(void)CE=0;#ifdef TMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ 收发完成中断响应, 16 位 CRC ,主接收#endifCE = 1;us(130); /* */* 函数: unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/* 功能:数据读取后放如 rx_buf 接收缓冲区中 /* */unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)unsigned ch

35、ar revale=0;sta=SPI_Read(STATUS); / 读取状态寄存其来判断数据接收状况 if(RX_DR) / 判断是否接收到数据CE = 0; /SPI 使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);/ read receive payload from RX_FIFO bufferrevale =1; / 读取数据完成标志SPI_RW_Reg(WRITE_REG+STATUS,sta); /接收到数据后 RX_DR,TX_DS,MAX_PT 都置高为 1,通过写 1 来清楚中断标志return revale; /* /

36、* 函数: void nRF24L01_TxPacket(unsigned char * tx_buf)/* 功能:发送 tx_buf 中数据 /*/void nRF24L01_TxPacket(unsigned char * tx_buf)CE=0; /StandBy I 模式SPI_Write_Buf(WRITE_REG + RX_ADDR_PO, TX_ADDRESS, TX_ADR_WIDTH 装/ 载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); / 装载数据 #ifdef RMODESPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); / IRQ 收发完成中断响应, 16 位CRC主发送#endifCE=1; /置高CE激发数据发送us(10);/nrf24l01.c 结束 文中用到的“ delay.h ”中一个us延时,一个ms延时,读者可以自己写。(由 于晶振不同,延时函数不同,这里就不列出了)这两个文件同时包含了收发模式。通过/ 模式选择#define RMODE/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论