NRF24L01编程心得123

第一次使用无线通信的芯片,第一次接触SPI总线时序,第一次遇到芯片有问题,很多的第一次,所以最后成功了我觉得很有意义,收获了很多,有必要用寥寥数字来记录一下。

最开始老板给的是一个NRF401的芯片,后来网上一查,这玩意早停产了,不过发现其操作和硬件接口非常简单,编程应该也非常简单,于是乎三下两下的接好电路,编好程序,上电一跑,晕了!完全没反应,一开始还怀疑自己的程序或者硬件电路哪里错了,DEBUG,查资料搞了好几天,最后确定自己没有搞错。

于是乎,又把401拿掉,直接用2根导线把两块板子的串行口接好,然后奇迹出现了,如同我设想的那样运行。

好吧,终于可以确定这2块不知放了多少年布满飞尘的401是坏的了。

然后上网继续寻找替代品,淘宝上一搜人气最高的是NRF24L01,本来还想买905的,不过哥相信群众,于是买了2块NRF24L01回来。

这个芯片的接口是SPI的接口,的确让我郁闷了一阵,以前从来没接触过这个玩意,而且一般的单片机哪有SPI接口,身边的一块ARM板倒是有不过只有一块啊,于是又硬着头皮去看如何用普通IO口模拟出SPI的时序来操作NRF24L01,等搞明白了芯片也寄到了,又是一阵捣鼓,接好线,相当多的线,编好程序,相对401来说很长的程序。

一上电,又晕了,还是没反应。

然后就是无止境的调试,修改程序,整整花了一周多时间后终于遇到了曙光啊!一个网上的高手帮我用他那边的示波器分析了一下我的程序波形,说没有问题啊,然后另一个高手告诉我应该怎样来一步一步地调试这些芯片,比如先给芯片寄存器写一个值然后马上读出来,看是否写操作正确,等等。

这个经验之谈真是犹如黑夜里的一盏明灯啊,让我豁然开朗,马上照高手指点的一搞,结果出来了。

2块NRF24L01的其中一块根本写不进去数据,完全是坏的,哎!人品啦!(我承认是我太傻太天真了,以为老板发货的时候都会先帮我检查一遍)马上和淘宝上的老板沟通了一下,让我把坏的寄过去他检查如果确实是他们的原因他们负责再给我寄一个过来,同时包邮费。

好吧,我又等,等了一周老板来电话了通知我确实是他们的问题给我寄了一块坏的芯片,并给我重新寄来了一块好的。

然后继续等啊等,又是一周,东西终于来了。

这次哥颤抖着以迅雷不及掩耳盗铃儿响叮当之势再一次接好线,下好以前写好的程序,谢天谢地谢亚龙啊,这次总算测试通过,两块芯片都是好的了。

今天自己又写了一个发送与接收单工通信的测试程序,跑了一下。

恩,效果不错,看到接收端不停得把收到的数据显示在电脑上时内牛满面啊!这其中也有个小插曲,一开始接收的数组被我定义在了code段,结果发送端都能正确收到接收的应答信号,但接收端就是不能把数据写进接收数组里面,程序编译也通过。

后来一想才明白CODE内的代码是下载到flash中的,是修改不了的。

最后改成data修饰,终于能正常运行了。

当初我曾请一个调出来的网友把他的程序借我参考下,但他说这是公司的商业机密,不能给,哎,为了以后的同仁少走弯路,我把我调好的测试程序放上来。

#include <reg52.h>#include <intrins.h>#define MODE 0 //MODE=1时为发送代码MODE=0时为接收代码typedef unsigned char uchar;//****************************************IO端口定义***************************************sbit MISO =P2^3;sbit MOSI =P2^2;sbit SCK =P2^1;sbit CE =P2^5;sbit CSN =P2^0;sbit IRQ =P3^2;sbit led = P1^2;//***************************************************************************** *************uchar bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;//*********************************************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 // 32 uints TX payload#define RX_PLOAD_WIDTH 32 // 32 uints TX payloaduchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};//本地地址pipe0uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};//接收地址pipe0uchar codeTx_Buf[TX_PLOAD_WIDTH]={0xff,0xee,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xb b,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x 33,0xee,0xff};//发送数据uchar Rx_Buf[RX_PLOAD_WIDTH];//接收数据//***************************************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 // 自动重发功能设置re_transmmit#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){unsigned int i,j;for(i=0;i<1000;i++)for(j=0;j<s;j++);}//短延时void delay_ms(unsigned int x){unsigned int i,j;i=0;for(i=0;i<x;i++){j=108;;while(j--);}}/************************************IO 口模拟SPI总线代码************************************************/uchar SPI_RW(uchar byte){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++){MOSI=(byte&0x80);byte=(byte<<1);SCK=1;byte|=MISO;//led=MISO;Delay(150);SCK=0;}return(byte);}uchar SPI_RW_Reg (uchar reg,uchar value) // 向寄存器REG写一个字节,同时返回状态字节{uchar status;CSN=0;status=SPI_RW(reg);SPI_RW(value);CSN=1;return(status);}uchar SPI_Read (uchar reg ){uchar reg_val;CSN=0;SPI_RW(reg);reg_val=SPI_RW(0);CSN=1;return(reg_val);}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes){uchar status,byte_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status bytefor(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)SPI_RW(*pBuf++);CSN = 1; // Set CSN high againreturn(status); // return nRF24L01 status byte}#if MODE // 条件编译/*******************************发*****送*****模*****式*****代*****码************************************/void TX_Mode(void){CE=0;SPI_RW_Reg(FLUSH_TX,0x00);SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);// Writes TX_Address to nRF24L01 ,设置发射管道0 的地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);// RX_Addr0 same as TX_Adr for Auto.Ack,设置接收管道0的地址,并且是一样SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto. Ack:Pipe0SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1aSPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Data rate:1Mbps, LNA:HCURRSPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);CE=1;delay_ms(100);}void Transmit(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_RW_Reg(FLUSH_TX,0x00);SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送delay_ms(150);}#else/*******************************接*****收*****模*****式*****代*****码*************************************/uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uchar 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_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/****************************************************************************** ************************//*函数: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,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志//Delay(100);}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/****************************************************************************** **********************//*函数:void RX_Mode(void)/*功能:数据接收配置/****************************************************************************************************/void RX_Mode(void){CE=0;SPI_RW_Reg(FLUSH_RX,0x00);//SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.AckSPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0//SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1aSPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURRSPI_RW_Reg(WRITE_REG + CONFIG, 0x0F);CE=1;delay_ms(130);}//************************************串口初始化*********************************************************void StartUART( void ){ //波特率9600SCON = 0x50;TMOD = 0x20;TH1 = 0xFD;TL1 = 0xFD;PCON = 0x00;TR1 = 1;}//************************************通过串口将接收到数据发送给PC端**************************************void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}#endif//************************************主函数************************************************************void main(){int i=0;CE=0;SCK=0;CSN=1;P1=0x00;#if MODE //发送模式代码TX_Mode();//SPI_RW_Reg(FLUSH_RX,0x00);while(1){Transmit(Tx_Buf);Delay(10);sta=SPI_Read(READ_REG + STA TUS);if(TX_DS){P1=sta; //8位LED显示当前STA TUS状态发送中断应使bit5 = 1 灯灭Delay(100);SPI_RW_Reg(WRITE_REG + STATUS,sta);}if(MAX_RT) //如果是发送超时{P1=0x0f; //发送超时时8位LED灯bit4 = 1 灯灭Delay(150);SPI_RW_Reg(WRITE_REG + STATUS,sta);}}#else //接收模式代码StartUART();RX_Mode();Delay(0);//防止编译警告while(1){if(nRF24L01_RxPacket(Rx_Buf)){for(i=0;i<TX_PLOAD_WIDTH;i++)R_S_Byte(Rx_Buf[i]);}}#endif}。

合集下载

24L01详细经验之谈

24L01详细经验之谈
无论何时收到确认,都会认为上一个数据包发送成功,这个数据包将被从发送缓冲区清除,并且把TX_DS IRQ置为高。
每次开始spi写,读回来的都是状态字。
射频收发工作在2.4~2.4835G
收发共用天线接口
GFSK调制
250k,1M,2M的空中速率
发射输出功率最高0dBm,即1mW
6路1对6星型网络(使用6个data pipe)
#define NOP 0xFF//保留
//*****************SPI(nRF24L01)寄存器地址****************************************************
#define CONFIG 0x00 //配置收发状态,CRC校验模式以及收发状态响应方式
/*reg:待写入的寄存器;value:待写入的值*/
ucharSPI_RW_Reg(uchar reg, uchar value)
{
ucharstatus;定义uchar变量status
CSN = 0;//片选非
status = SPI_RW(reg);//待写入的寄存器地址reg
SPI_RW(value);//写入值为value
自动应答的延时和重发次数是可编程的。
/********************************************************************************/
/*函数:void SetRX_Mode(void)
/*功能:数据接收配置
/********************************************************************************/

nrf24le1学习笔记

nrf24le1学习笔记

1、写卡时,需要将两根绿色的线进行短接,否则写卡失败!!!除此之外,当写卡烧录完写程序后,配置完读卡参数之后,需要重新上电,并且还需要重新关闭串口再打开串口。

否则不能写卡另外,注意卡片电池,如果电池电源太低,也不能写卡。

写卡器刚烧录完程序后,当配置完读卡器配置后,需要重新关闭和打开串口,再进行写卡器配置(或者软件重开),否则无法写卡。

2、所有的内存在没有写之前都是FF3、RC振荡器:在振荡电路中的频率选择部分可以只用电阻和电容构成。

这种只用电阻和电容构成的振荡器称为RC振荡器。

晶振:只要在晶体板极上施加交变电压,就会使晶片产生机械变形振动,此现象即所谓逆压电效应。

当外加电压频率等于晶体谐振器的固有频率时,就会发生压电谐振,从而导致机械变形的振幅突然增大。

4、温度系统:温度系数表征标称值受温度变化影响的程度,单位是ppm/°C。

如电阻的阻值,基准电压源的电压值等。

温度系数通常非常小,采用百万分比(ppm)表示更容易。

5、编程总结:1、nrf24le1芯片使用时,有一个寄存器,是用于控制端口操作的,如果关闭此端口则不能正确操作此端口。

OPMCON = 0x02;则表示关闭了端口,在使用端口时,应该重新打开端口。

如OPMCON = 0x00;2、nrf24le1芯片,当使用它与C8051F120进行SLAVE SPI通信时,如果已经完数据,而要从已写完的数据中,再读取出来,则需要一定的延时!3、两块单片机使用SPI通信时,如果配置的晶振频率过高,有可能使得程序在while循环等待过程中接收不到另一发起人单片机的程序,从而出现单片机死机的现象。

4、使用nrf24le1时,在使用二维数组,不能将二维数组的地址传递给一个数a,再把a传递给b而就直接交二维数组传递给b5、关于return和break:使用return时是跳出此子函数,回到调用该子函数的后面。

而使用break时是跳出该循环体。

6. 关于卡片睡眠醒来操作内存:当卡片醒来,若是要操作内存,则必须将系统时钟重新配置:CLKCTRL=0;delay_nms(30);(延时是为了等待时钟响应)。

一位从厌倦调试NRF24L01无线模块到成功的收发经验分享

一位从厌倦调试NRF24L01无线模块到成功的收发经验分享

一位从厌倦调试NRF24L01无线模块到成功的收发经验分享拿到这对小家伙的时候,距离现在已经有好几个月了吧。

直到大概一个月前,才将它们从抽屉里拿出来。

之所以一直搁置着,是因为想要靠自己来驱动它们。

厌倦了那种拿到模块到处找例程的感觉。

不过,这也让人吃尽了苦头。

熬了多少个夜晚,看了多少遍datasheet,甚至因为实在太困难了,所以索性再次搁在一边,拿了个较为简单的1302寻寻feel。

这一搁置,又过了一个多星期。

大学时间真的太紧张了,各种各样无聊的课占据了平日的大部分时间。

周末,才感觉是为自己活着的日子。

第三次&mdash;&mdash;真正的战役,持续时间并不算长,相对于前两次的铺垫来说。

熬了一个星期的夜,时间总是在不知不觉之间溜走,往往回过神来才发觉,大家都睡下了,已经三四点了。

不过喜欢这宁静的夜,也再一次深深的体会到,走这条路的人是没有夜晚的,因为深夜才是最高效的时间。

不过,这次的收尾工作却是在今天早上进行的。

前天晚上进行最终的测试,两台机都装的自己程序,结果接收机反馈回来乱码,经过昨天一整天的排查才知道是连续读数据函数不能表达。

修修改改忙了一整晚,到昨晚三四点还是没有突破,索性睡个觉。

今早九点,熟睡中一个激灵醒过来,打开电脑再看看,还是不行。

失望中倒头呼呼大睡,十一点再次醒来,牙都还没刷,问题就解决了。

虽然如此,但是心里还是带着小小的疑问,不明白究竟为什么。

这里实现的功能比较简单:通过PC串口给发送端写入要传送的数据(定长32字节),接收端将收到的数据反馈给PC。

由于只有一台电脑,所以只能够同时开两个串口调试窗来观察。

不过这里面的收获也挺多的,例如对C的指针有了较为直观、深刻的感受,再如数据交换函数的写法,还有就是包含串口通信在内所有程序都是参考数据手册写的。

nRF24L01实现一对多通信技术分析

nRF24L01实现一对多通信技术分析

// 写本地
_nop_(); _nop_(); _nop_(); SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); _nop_(); _nop_(); _nop_(); SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道 0 自动 ACK 应答允许 _nop_(); _nop_(); _nop_(); SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道 0,如果需要 多频道可以参考 Page21 _nop_(); _nop_(); _nop_(); SPI_RW_Reg(WRITE_REG + RF_CH, 0);
// 设置信道工作为 2.4GHZ,收发必须一致
_nop_(); _nop_(); _nop_(); SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度, 本次 设置为 32 字节 _nop_(); _nop_(); _nop_(); SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0F); 大值 0dB CE=1; }
发送主函数: void main(void) { init_NRF24L01(); P0=0x00; Delay(6000); nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(2000); SPI_RW_Reg(FLUSH_TX,0x00); SPI_RW_Reg(WRITE_REG+STATUS,0x7F);//关系着是否能顺利通信和接收端的数据通道 号能否正确读出。数据手册中有这么一句话:如果 MAX_RX 中断产生则必须清除后才能进 行通讯。 }

NRF24L01之我的学习体会

NRF24L01之我的学习体会

本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。

对部分函数的解释:uint SPI_RW(uint dat)最基本的函数,完成GPIO模拟SPI 的功能。

将输出字节(MOSI)从MSB 循环输出,同时将输入字节(MISO)从LSB 循环移入。

上升沿读入,下降沿输出。

(从SCK被初始化为低电平可以判断出)uchar SPI_Read(uchar reg); //从reg寄存器读一字节读取寄存器值的函数:基本思路就是通过READ_REG命令(也就是0x00+寄存器地址),把寄存器中的值读出来。

对于函数来说也就是把reg 寄存器的值读到reg_val 中去。

uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器寄存器访问函数:用来设置24L01 的寄存器的值。

基本思路就是通过WRITE_REG命令(也就是0x20+寄存器地址)把要设定的值写到相应的寄存器地址里面去,并读取返回值。

对于函数来说也就是把value值写到reg 寄存器中。

需要注意的是,访问NRF24L01 之前首先要enable 芯片(CSN=0;),访问完了以后再disable芯片(CSN=1;)。

uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);//从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址接收缓冲区访问函数:主要用来在接收时读取FIFO 缓冲区中的值。

基本思路就是通过READ_REG命令把数据从接收FIFO(RD_RX_PLOAD)中读出并存到数组里面去。

uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);//把pBuf缓存中的数据写入到nRF24L01通常用来写入发发射缓冲区访问函数:主要用来把数组里的数放到发射FIFO缓冲区中。

NRF24L01学习笔记

NRF24L01学习笔记

NRF24L01学习笔记按照如下方式在电路板上安排的管脚8 76 54 32 1各管脚如下定义:8.IRQ 7.MISO6.MOSI 5.SCK4.CSN 3.CE2.VCC 1.GND具体说明:3.CE 芯片的模式控制线。

在CSN 为低的情况下,CE 协同NRF24L01 的CONFIG 寄存器共同决定NRF24L01 的状态(参照NRF24L01 的状态机)。

4.CSN 为芯片的片选线CSN 为低电平芯片工作5.SCK 为芯片控制的时钟线(SPI时钟)6.MOSI 为芯片控制数据线(Master output slave input)主输出从输入7.MISO 芯片控制数据线(Master input slave output)master 硕士主人船长slave 从属奴隶主输入从输出8.IRQ 中断信号引脚。

中断时变为低电平,即NRF24L01内部发生中断时IRQ 引脚从高电平变为低电平。

引脚会在以下三种情况变低:Tx FIFO 发完并且收到ACK(使能ACK情况下)、Rx FIFO 收到数据、达到最大重发次数。

中断:nRF24L01 的中断引脚(IRQ)为低电平触发,当状态寄存器中TX_DS(数据发送完成中断位)、RX_DR(接收数据中断位)或MAX_RT(达到最多次重发中断位)为高时触发中断。

当MCU 给中断源写‘1’时,中断引脚被禁止。

可屏蔽中断可以被IRQ 中断屏蔽。

通过设置可屏蔽中断位为高,则中断响应被禁止。

默认状态下所有的中断源是被禁止的。

在写寄存器之前一定要进入待机模式或掉电模式NRF24L01有以下工作模式:其工作模式又CE和寄存器内部PWR_UP、PRIM_RX共同控制,见下表:5.1收发模式收发模式有Enhanced ShockBurstTM收发模式、ShockBurstTM收发模式和直接收发模式三种,收发模式由器件配置字决定,具体配置将在器件配置部分详细介绍。

5.1.1 Enhanced ShockBurstTM收发模式Enhanced ShockBurstTM收发模式下,使用片内的先入先出堆栈区,数据低速从微控制器送入,但高速(1Mbps)发射,这样可以尽量节能,因此,使用低速的微控制器也能得到很高的射频数据发射速率。

基于nRF24L01的无线信息传输设计

摘要当今,通过信息的采集、传输、处理和控制器作出相应的决策,进而实现对一定对象的监控和控制,是一个无论在民用、工业,还是军事领域,都被人们乐此不疲地研究着的热门技术。

而信息传输的可靠性无疑是控制器作出正确决策的重要前提。

无线传输以其成本廉价、占用空间小、环境适应性好、扩展性好和设备维护上更容易实现等优点正在逐步越来越受到人们的青睐。

RF24L01SE微功率无线通讯模块,采用Nordic公司的NRF24L01芯片,2.4G全球开发ISM频段免许可证使用,最高工作速率达2Mbps,125频道满足多点通信和跳频通信需要,体积小巧约31mm*17mm,尤其方便嵌入式开发与应用,高效GFSK调制,抗干扰能力强,特别适合无线音视频传输、工业控制领域等需要较大传输速率的无线通讯需求。

此外,采集到的信息和数据应能够使工作人员直观方便地读出,为此,配备质优价廉的显示设备成为必要。

常用的显示设备有LED点阵和LCD液晶显示,而LCD液晶显示由于具有低功耗、显示功能强大和编程简单而很好地符合了人们节约能源的要求,LCD1602和LCD12864是LCD系列中比较常见的模块化产品,它们含有齐全的字库,亦可根据自己的要求取模显示特殊的符号,这两种产品分别只引出16和20个插针,使用方便。

关键词:无线传输监控NRF24L01 工业控制LCD1602 LCD12864目录一.系统简介 (3)二.STC89C54RD+单片机 (3)三.4*4矩阵输入键盘 (4)四.无线nRF24L01模块 (4)1.模块性能及特点: (5)2. 工作方式: (5)2.1 收发模式 (5)2.2 空闲模式 (6)2.3 关机模式 (6)3.配置RF24L01模块 (7)四.LCD1602 (8)五.LCD12864(带字库) (8)六.系统原理图 (10)七.实物效果图 (11)八.部分程序代码 (12)九.课程设计心得体会 (20)十.参考文献 (20)一.系统简介本设计为两个STC89C54RD+单片机之间通过nRF24L01无线模块实现单工无线通信。

关于NRF24l01的调试

NRF24l01的调试过程与方法小结心得体会:最近老板给了几块nrf24l01模块我,初次上手难免走了许多的弯路,经过近一周的时间的不断调试,模块之间终于可以相互收发数据了。

这样下来终于松了一口气。

其间的各种辛苦与艰辛难于言表。

上网大致看了一下,网上基于51的调试比较多,但是我们实验室用的是DSP2812,由于nrf24l01是SPI接口,2812上刚好有SPI的接口,这样貌似给使用带来了方便,但是51之类的芯片虽然没有SPI口,但是例程也最多,关于他的讨论比较多。

最开始我的想法也比较混乱,想直接用SPI来调试,把底层函数稍微修改了一下,发现并没有结果,这个东西就像一个黑匣子一样,即看不见也摸不着,后来我慢慢改变了思路。

既然网上基于IO口模拟的SPI的例程最多,我决定另外走一条路,先用2812的IO 口模拟SPI再用自带的SPI口去调试。

这样一来我就有了两条可以走的路。

第一条:底层SPI时序用IO口模拟去写。

第二条:底层直接用2812的SPI去操作。

虽然这样一来,路好走了一点,有各类的程序可以参考,但是这样带来最大的一个问题,这也是后来我才发现的,nrf24l01的最大读写速率是有限制的,2812在150M运行时很显然是太大了一点,由于nrf24l01对时序的要求很高,端口的读写速率和时序都有严格的要求,所以我们才看到,在网上一般是15M左右的单片机来模拟IO口,没有谁用150M的DSP来模拟IO口的,当然既然确定了这样的方法后来也发现了问题,我还是继续走下去了。

很重要的一点是系统的时钟频率。

当然时序的要求也很高,这也就是为什么,网上说这个模块不好调试的原因,既然是调试,当然我们既然是调试,肯定有一个思路和方法。

那么方法是什么呢?开始的时候我是一股脑将发送和接收的程序都写进去,然后啥现象也没有,然后就傻眼了。

在网上看了看,于是有了一点思路。

方法是将发送和接收的调试分开来调试,以读取nrf24l01内部的寄存器为手段,先调试发送方,发送方调试没有问题以后,让发送方不断的发送数据,然后再来调试接收方,直到接收方也没有问题,再接着望下面去做。

nRF24L01学习经验

nRF24L01学习经验nRF24L01+nRF24L01+这个无线收发模块目前已经大致学习完毕,实现的功能以及各项参数:1~32字节数据的无线传输;5m的有效收发距离,1m的无遗漏收发距离;距离在5m内和5m外转变时,超出距离数据传输会自动中断,进入范围自动继续;实验中数据不丢失,无错误。

可用于短距离的数据传输和交互。

在通信模块的学习中,主要分为以下3个部分1、通过SPI配置nRF24L01+的寄存器因为nRF24L01+的寄存器配置只支持SPI总线,从无线板与MCU的连线情况看,单片机自带的SPI总线接口与无线板接口不匹配,所以要模拟一个SPI总线来进行控制,查找了一些SPI的总线描述,感觉SPI较I2C的时序更为简单,模拟SPI的过程中,遇到过一个问题,将所需要的函数全都写好,感觉时序也没有任何问题,可是寄存器就是写不进去,这个问题困扰了很久,感觉是时序的问题,但是函数中却找不出来,后来发现是模拟时钟的高低电平写反了。

Void SCK_H(void) {PORTB &= ~(1 << SCK);}Void SCK_L(void) {PORTB |= (1 << SCK);}这个问题导致时序错误而无法写入,而且纠错中不容易发现。

SPI的读写过程如下(读一个字节,写一个字节等就不贴出了):void write_reg(unsigned char address, unsigned char temp){unsigned char status = 0;PORTB &= ~BIT(CSN); //使能SPIstatus = spi_rw(address);//前8位写入地址跟读取状态寄存器write(temp);//写入一个字节PORTB |= BIT(CSN);}unsigned char read_reg(unsigned char address){unsigned char dat = 0;unsigned char status = 0;PORTB &= ~BIT(CSN); //使能SPIstatus = spi_rw(address);//前8位写入地址跟读取状态寄存器dat = read();//读取一个字节PORTB |= BIT(CSN);return dat;}SPI调通之后配置寄存器就只需要了解寄存器的作用就行了,24L01的寄存器也不算多,配置过程也就是理解寄存器作用的过程了。

nrf24l01调试方法及经验总结

NRF24L01 :在通信中的应用方法,经验总结(1)2011-07-31 13:15首先说一下:是一款新型单片射频收发器件,工作于 GHz~ GHz ISM频段。

内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合了增强型ShockBurst技术,其中输出功率和通信频道可通过程序进行配置。

nRF24L01功耗低,在以-6 dBm的功率发射时,工作电流也只有9 mA;接收时,工作电流只有 mA,多种低功率工作模式(掉电模式和空闲模式)使节能设计更方便。

是想将这个IC调通,首先要多读一下技术文档:下载技术文档以下C51驱动的源代码库()此库文件适合发送端使用,在接收端会有所不同,请看第 2 部分的分析在使用过程中,需要引用SCK = 1; uchar |=MISO; then set SCK lowagain } return(uchar); . SPI_RW(reg);reg_val = SPI_RW(0); then read registervalue CSN =1; and write value to it.. CSN =1; // CSN highagain return(status); // return nRF24L01 statusuchar } /****************************************************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*************************************************************************************** *************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) { uintstatus,uchar_ctr; CSN = 0; // Set CSN low, init SPI tranaction status = SPI_RW(reg); // Select register to write to and read statusuchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++) pBuf[uchar_ctr] =SPI_RW(0); // CSN =1; return(status);// return nRF24L01 statusuchar } /******************************************************************************* ************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:reg为寄存器地址,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) /*功能:数据接收配置/*************************************************************************************** *************/ 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接收缓冲区中/*************************************************************************************** ***************/ uchar nRF24L01_RxPacket(unsigned char* rx_buf) { unsigned char revale=0; sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{ Display8bit(3,0,sta); //看一下接收机状态判断一下,IC的工作状态,在正常使用过程中,这句需要去掉 CE =0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer revale =1; //读取数据完成标志} SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志returnrevale; } /***************************************************************************** ****************************** /*函数: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,主发送SPI_RW_Reg(WRITE_REG+STATUS,0X7E); CE=1; //置高CE,激发数据发送inerDelay_us(100); }NRF24L01 :在通信中的应用方法,经验总结(3)2011-07-31 13:42再接着往下说调试过程:一般拿到IC后最大的困难就是无法知道自己 IC 是否已经工作了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档