




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
最近百度上一些朋友都在为nRF24L01头疼,我这段时间又比较忙不能花太多时间一个一个去帮忙调试,干脆今天抽点儿时间写个应用笔记,希望能给大家提供一些方法和帮助。有问题可以跟帖留言,我看到会尽量帮大家。nRF24L01是Nordic公司生产的一个单芯片射频收发器件,是目前应用比较广泛的一款无线通讯芯片,具体手册资料网上大把,我就不再重复它的特性什么的了,直接说说它的调试方法,供大家参考。24L01是收发双方都需要编程的器件,这就对调试方法产生了一定的要求,如果两块一起调,那么通讯不成功,根本不知道是发的问题还是收的问题,不隐晦的说,我当时也是没理清调试思路才浪费了大半天时间看着模块干瞪眼。正确的方法应该是先调试发送方,能保证发送正确,再去调接收,这样就可以有针对性的解决问题。至于怎么去调发送方,先说下发送方的工作流程:配置寄存器使芯片工作于发送模式后拉高CE端至少10us读状态寄存器STATUS判断是否是发送完成标志位置位清标志清数据缓冲网上的程序我也看过,大多都是成品,发送方发送-等应答-(自动重发)-触发中断。可是这样的流程就已经把接收方给牵涉进来了,就是说一定要接收方正确收到数据并且回送应答信号之后发送方才能触发中断,结束一次完整的发送。可是这跟我们的初衷不相符,我们想单独调试发送,完全抛开接收,这样就要去配置一些参数来取消自动应答,取消自动重发,让发送方达到发出数据就算成功的目的。SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); / 失能通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x00); / 失能接收通道0SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00); / 失能自动重发(注:以下贴出的寄存器描述由于中文资料上有一个错误,故贴出原版英文资料)有了以上这三个配置,发送方的流程就变成了发送-触发中断。这样就抛开了接收方,可以专心去调试发送,可是怎么样才知道发送是否成功呢,要用到另外两个寄存器,STATUS和FIFO_STATUS。这样就很清晰了,我们可以通过读取STATUS的值来判断是哪个事件触发了中断,寄存器4、5、6位分别对应自动重发完成中断,数据发送完成中断,数据接收完成中断。也就是说,在之前的配置下,如果数据成功发送,那么STATUS的值应该为0x2e。这样就可以作为一个检测标准,另外一个标准可以看FIFO_STATUS寄存器,第5位的描述:发送缓冲器满标志,1为满,0为有可用空间;第4位的描述:发送缓冲器空标志,1为空,0为有数据;同样可以看到接收缓冲器的对应标志。这样在数据发送成功后,发送寄存器当然应该是空的,接收缓冲因为在之前已经失能,所以也应该是空,也就是说成功发送之后的FIFO_STATUS寄存器值应该是0x11。有了这两个检测标准,我们即使不用接收方也可以确定发送方是否成功发送。当发送方调试成功之后,在程序里让它一直发送,然后我们就可以去调试接收方,思路是一样的,同样说下接收方工作流程先。配置寄存器使芯片工作于接收模式后拉高CE端至少130us读状态寄存器STATUS判断是否是接收完成标志位置位清标志读取数据缓冲区的数据清数据缓冲然后在初始化配置寄存器的时候要和发送方保持一致,比较重要的是要失能自动应答,使能通道0接收:SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); / 失能通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 接收要使能接收通道0这样就可以了,接收方就可以进入接收模式去接收数据了,这次的调试就会灵活一些,因为是接收数据,可以在接收方添加一个显示设备把数据直观的显示出来,去对照看是否正确,当然还可以使用和发送方一样的方法:观察STATUS和FIFO_STATUS的值,对照寄存器描述,接收正确时STATUS的值应该是0x40,对于FIFO_STATUS的情况就多了些,因为数据宽度的不同也会造成寄存器的值不一样,24L01最大支持32字节宽度,就是说一次通讯最多可以传输32个字节的数据,在这种情况下,接收成功读数据之前寄存器值应该为0x12,读数据之后就会变成0x11;如果数据宽度定义的小于32字节,那么接收成功读数据之前寄存器值应该为0x10,读数据之后就会变成0x11。这个看起来挺复杂,其实很清晰,大家可以试着分析下,对照数据手册分析每个位的状态就可以得到结果。好了,到这里对nRF24L01的调试基本上就算通了,但是要明白这些只是调试方法,最终的产品如果不加上应答和重发的话那么数据的稳定性是很难保证的,所以在基本的通讯建立之后就要把发送的配置改为:SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); / 使能接收通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 使能接收通道0SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); / 自动重发10次,间隔500us接收方的配置也要更改:SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); / 失能通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 接收要使能接收通道0这样发送和接收就进入了一个标准状态,发送-等应答-(自动重发)-触发中断;接收-应答-触发中断,一切按部就班,程序里加上自己的应用部分就能实现很多功能了,呵呵,这个帖子就先到这,明白芯片工作原理之后写程序就有目的性了,下一篇再说说程序中查询法和中断法以及具体的程序实例。写了一个多小时了,得忙会儿工作,别被老板逮着了,哈哈。祝大家成功NRF24L01发送端程序调试成功 复制地址 日志地址: 请用Ctrl+C复制后贴给好友。翰林文圣_2.4G 2011年03月10日 22:13 阅读(7) 评论(0) 分类:单片机资料 举报 字体:中 o 小o 中o 大 在网友(李渊)的鼎力相助下,今天总算把困扰我好久的无线模块调试成功了,并且其中学到了很多学不到的东西感觉专业人士就是不一样,ARM嵌入不是一般人能做的!感谢感谢,不然不知道需要在黑暗中摸索多久。下面献上热乎乎的程序!因为网上根本没有单独发送并且已经调试好的程序,独家首发_好兴奋!#include #include typedef unsigned char uchar;typedef unsigned char uint;/*IO端口定义*sbit MISO=P10;sbit MOSI=P11;sbitSCK =P12;sbitCE =P13;sbitCSN =P14;sbitIRQ =P15;/*NRF24L01*#define 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 payloaduint const TX_ADDRESSTX_ADR_WIDTH= 0x01,0x01,0x01,0x01,0x01;/本地地址uint const RX_ADDRESSRX_ADR_WIDTH= 0x10,0x10,0x10,0x10,0x10;/接收地址 /*NRF24L01寄存器指令*#define READ_REG 0x00 / 读寄存器指令#define WRITE_REG 0x20 / 写寄存器指令#define RD_RX_PLOAD 0x61 / 读取接收数据指令#define WR_TX_PLOAD 0xA0 / 写待发数据指令#define FLUSH_TX 0xE1 / 冲洗发送 FIFO指令#define FLUSH_RX 0xE2 / 冲洗接收 FIFO指令#define REUSE_TX_PL 0xE3 / 定义重复装载数据指令#define NOP 0xFF / 保留/*SPI(nRF24L01)寄存器地址*#define CONFIG 0x00 / 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 / 自动应答功能设置#define EN_RXADDR 0x02 / 可用信道设置#define SETUP_AW 0x03 / 收发地址宽度设置#define SETUP_RETR 0x04 / 自动重发功能设置#define RF_CH 0x05 / 工作频率设置#define RF_SETUP 0x06 / 发射速率、功耗功能设置#define STATUS 0x07 / 状态寄存器#define OBSERVE_TX 0x08 / 发送监测功能#define CD 0x09 / 地址检测 #define RX_ADDR_P0 0x0A / 频道0接收数据地址#define RX_ADDR_P1 0x0B / 频道1接收数据地址#define RX_ADDR_P2 0x0C / 频道2接收数据地址#define RX_ADDR_P3 0x0D / 频道3接收数据地址#define RX_ADDR_P4 0x0E / 频道4接收数据地址#define RX_ADDR_P5 0x0F / 频道5接收数据地址#define TX_ADDR 0x10 / 发送地址寄存器#define RX_PW_P0 0x11 / 接收频道0接收数据长度#define RX_PW_P1 0x12 / 接收频道0接收数据长度#define RX_PW_P2 0x13 / 接收频道0接收数据长度#define RX_PW_P3 0x14 / 接收频道0接收数据长度#define RX_PW_P4 0x15 / 接收频道0接收数据长度#define RX_PW_P5 0x16 / 接收频道0接收数据长度#define FIFO_STATUS 0x17 / FIFO栈入栈出状态寄存器设置/*void Delay(unsigned int s);void inerDelay_us(unsigned char n);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);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);/*长延时*void Delay(unsigned int s)unsigned int i;for(i=0; is; i+);for(i=0; i0;n-)_nop_();/*/*NRF24L01初始化/*/void init_NRF24L01(void) inerDelay_us(100);CE=0; / chip enableCSN=1; / Spi disable SCK=0; / Spi clock line init highIRQ=1;SPI_Write_Buf(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, 0x00); / 频道0自动ACK应答禁止SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); / 允许接收地址只有频道0,如果需要多频道可以参考Page21 如果 SPI_RW_Reg(WRITE_REG + RF_CH, 0); / 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); /设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); /设置发射速率为2MHZ,发射功率为最大值0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); / IRQ收发完成中断响应,16位CRC,发射模式/ps:波特率用设置么?IRQ用拉高么?不响应中断?/*/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/*/uint SPI_RW(uint uuchar)uint bit_ctr; for(bit_ctr=0;bit_ctr8;bit_ctr+) / output 8-bit MOSI = (uuchar & 0x80); / output uchar, MSB to MOSIuuchar = (uuchar 1); / shift next bit into MSB.SCK = 1; / Set SCK high.uuchar |= MISO; / capture current MISO bitSCK = 0; / .then set SCK low again return(uuchar); / return read uchar/*/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序/*/uchar SPI_Read(uchar reg)uchar reg_val;CSN = 0; / CSN low, initialize SPI communication.SPI_RW(reg); / Select register to read from.reg_val = SPI_RW(0); / .then read registervalueCSN = 1; / CSN high, terminate SPI communicationreturn(reg_val); / return register value/*/*功能:NRF24L01读写寄存器函数/*/uint SPI_RW_Reg(uchar reg, uchar value)uint status;CSN = 0; / CSN low, init SPI transactionstatus = SPI_RW(reg); / select registerSPI_RW(value); / .and write value to it.CSN = 1; / CSN high againreturn(status); / return nRF24L01 status uchar/*/*函数: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; / Set CSN low, init SPI tranactionstatus = SPI_RW(reg); / Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctruchars;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)/*功能: 用于写数据:为寄存器地址,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_ctruchars; uchar_ctr+) /SPI_RW(*pBuf+);CSN = 1; /关闭SPIreturn(status); / /*/*函数:void SetRX_Mode(void)/*功能:数据接收配置 /*/*void SetRX_Mode(void)CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); / IRQ收发完成中断响应,16位CRC,主接收CE = 1; inerDelay_us(130);*/*/*函数: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)/ 判断是否接收到数据 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;*/*/*函数: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_P0, TX_ADDRESS, TX_ADR_WIDTH); / 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); / 装载数据/SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); / IRQ收发完成中断响应,16位CRC,主发送CE=1; /置高CE,激发数据发送inerDelay_us(50);/*主函数*void main()/unsigned char TxBuf20=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20; /test/unsigned char TxBuf20=0; unsigned char TxBuf20=1;init_NRF24L01();nRF24L01_TxPacket(TxBuf);while(1)nRF24L01_TxPacket(TxBuf);P0=SPI_Read(STATUS);SPI_RW_Reg(WRITE_REG+STATUS,0XFF); /清状态寄存器Delay(2100);/感觉不加延时或是改小些都无所谓,根据实际情况来。 明天最好能调试出接收端程序哈哈 调试ing 经过一周的努力终于把发射和接受都搞定了,估计在多弄一天我就得崩溃了,先是硬件出问题,引脚弄反了,查出之后又开始调试软件,结果一个接着一个的查寄存器,看手册,这期间耗费了大量的心血,多亏认识了一个网友(李渊),在他的指点下才渐渐了解这个芯片的工作原理,传输机制,一天半就成功传送数据。在调试时注意ACK自动应答和电平CE的延长时间,试着查看STATUS的寄存器状态!终于可以安心的做毕业设计了哈哈(o)/#include #include typedef unsigned char uchar;typedef unsigned char uint;/*IO端口定义*sbit MISO=P10;sbit MOSI=P11;sbitSCK =P12;sbitCE =P13;sbitCSN =P14;sbitIRQ =P15;/*NRF24L01*#define 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 payloaduint const TX_ADDRESSTX_ADR_WIDTH= 0x10,0x10,0x10,0x10,0x10;/本地地址uint const RX_ADDRESSRX_ADR_WIDTH= 0x01,0x01,0x01,0x01,0x01;/接收地址/*NRF24L01寄存器指令*#define READ_REG 0x00 / 读寄存器指令#define WRITE_REG 0x20 / 写寄存器指令#define RD_RX_PLOAD 0x61 / 读取接收数据指令#define WR_TX_PLOAD 0xA0 / 写待发数据指令#define FLUSH_TX 0xE1 / 冲洗发送 FIFO指令#define FLUSH_RX 0xE2 / 冲洗接收 FIFO指令#define REUSE_TX_PL 0xE3 / 定义重复装载数据指令#define NOP 0xFF / 保留/*SPI(nRF24L01)寄存器地址*#define CONFIG 0x00 / 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 / 自动应答功能设置#define EN_RXADDR 0x02 / 可用信道设置#define SETUP_AW 0x03 / 收发地址宽度设置#define SETUP_RETR 0x04 / 自动重发功能设置#define RF_CH 0x05 / 工作频率设置#define RF_SETUP 0x06 / 发射速率、功耗功能设置#define STATUS 0x07 / 状态寄存器#define OBSERVE_TX 0x08 / 发送监测功能#define CD 0x09 / 地址检测 #define RX_ADDR_P0 0x0A / 频道0接收数据地址#define RX_ADDR_P1 0x0B / 频道1接收数据地址#define RX_ADDR_P2 0x0C / 频道2接收数据地址#define RX_ADDR_P3 0x0D / 频道3接收数据地址#define RX_ADDR_P4 0x0E / 频道4接收数据地址#define RX_ADDR_P5 0x0F / 频道5接收数据地址#define TX_ADDR 0x10 / 发送地址寄存器#define RX_PW_P0 0x11 / 接收频道0接收数据长度#define RX_PW_P1 0x12 / 接收频道0接收数据长度#define RX_PW_P2 0x13 / 接收频道0接收数据长度#define RX_PW_P3 0x14 / 接收频道0接收数据长度#define RX_PW_P4 0x15 / 接收频道0接收数据长度#define RX_PW_P5 0x16 / 接收频道0接收数据长度#define FIFO_STATUS 0x17 / FIFO栈入栈出状态寄存器设置/*void Delay(unsigned int s);void inerDelay_us(unsigned char n);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);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);/*长延时*void Delay(unsigned int s)unsigned int i;for(i=0; is; i+);for(i=0; i0;n-)_nop_();/*/*NRF24L01初始化/*/void init_NRF24L01(void) inerDelay_us(100);CE=0; / chip enableCSN=1; / Spi disable SCK=0; / Spi clock line init highSPI_Write_Buf(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,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); / 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 民生银行潍坊市昌邑市2025秋招群面模拟题及高分话术
- 兴业银行芜湖市鸠江区2025秋招面试典型题目及参考答案
- 民生银行天津市宁河区2025秋招面试典型题目及参考答案
- 广发银行重庆市渝北区2025秋招笔试专业知识题专练及答案
- 光大银行深圳市罗湖区2025秋招群面模拟题及高分话术
- 中信银行烟台市芝罘区2025秋招结构化面试15问及话术
- 广发银行长沙市浏阳市2025秋招笔试英语题专练及答案
- 光大银行银川市兴庆区2025秋招笔试英文行测高频题含答案
- 浦发银行株洲市荷塘区2025秋招英文面试题库及高分回答
- 广宁安全培训课件
- 勇气与成长写物作文10篇范文
- 反洗钱可疑交易识别课件
- 2025年中国银行招聘考试模拟试题及答案集
- BIM 建模基础与应用教学教案
- 真人秀节目策划与执行方案
- 2025至2030年中国工艺美术品行业市场前景预测及投资战略研究报告
- 人工智能技术及应用 第2版 课件全套 程显毅 第1-7章 人工智能时代 -人工智能应用
- 国庆中秋课件
- 艾滋病合并马尔菲青霉菌感染
- 乡镇卫生院检验检查分级管理制度
- 科技金融管理课件下载
评论
0/150
提交评论