嵌入式设计应用
nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型“SchockBurst”模式控制器、功率放大器、晶体振荡器、调制器和解调器。
小体积,QFN20 4x4mm封装
宽电压工作范围,1.9V~3.6V,输入引脚可承受5V电压输入
工作温度范围,-40℃~+80℃
工作频率范围,2.400GHz~2.525GHz
发射功率可选择为0dBm、-6dBm、-12dBm和-18dBm
数据传输速率支持1Mbps、2Mbps
低功耗设计,接收时工作电流12.3mA,0dBm功率发射时11.3mA,掉电模式时仅为900nA
126个通讯通道,6个数据通道,满足多点通讯和调频需要
增强型“ShockBurst”工作模式,硬件的CRC校验和点对多点的地址控制
数据包每次可传输1~32Byte的数据
4线SPI通讯端口,通讯速率最高可达8Mbps,适合与各种MCU连接,编程简单
可通过软件设置工作频率、通讯地址、传输速率和数据包长度
MCU可通过IRQ引脚块判断是否完成数据接收和数据发送
nRF24L01原理图
1、NRF24L01
2、NRF24L01 管脚功能
nRF24L01与5V单片机的连接(只适用于高阻口)
3、51单片机的I/O口输出为5V,而NRF24L01的电源输入为1.9—3.6V,如果直接接入单片机的电源会烧坏模块,因而要对单片机的电源接口进行压降,这里我选用二极管进行压降,二极管型号为IN4001. 这一步完成之后就可以把引脚用杜邦线连接到单片机的I/O口,定义管脚就可以开始编程了。
4、要用NRF24L01进行通信首先知道它的发送和接收流程
发送流程:
① MCU通过SPI对NRF24L01进行基本配置,,配置自动应答通道使能,设置自动重发次数不为0(在此设置可以重发数据包)设置为发送模式,还有其他配置等等
② MCU把要发送的数据和接收数据设备的地址通过SPI写入NRF24L01
③ CE引脚置高,启动发送
④ 此时有两种情况:
1.在有限时间内收到应答信号,则TX_DS置高(发送数据成功标志位),并引发IRQ中断(引脚IRQ置低),并清除TX BUf(此为发送缓冲寄存器,自行写代码清除),IRQ中断需要写状态寄存器进行复位(因为此处IRQ由TX_DS引发,将TX_DS复位即可使IRQ复位)
2.重发数据次数超过设定值,则MAX_RT置高(达到最多重发次数标志位),并引发IRQ中断(引脚IRQ置低),不清除TX BUf,IRQ中断需要写状态寄存器进行复位(因为此处IRQ由MAX_RT引发,将MAX_RT复位即可使IRQ复位)
⑤ 接收到应答信号产生中断或者达到最大重发次数产生中断后,NRF24L01继续发下一包数据。
⑥ 当TX BUf为空时,进入待机模式二(当CE为高,TX BUf为空时,进入待机模式二;NRF24L01的工作模式图表在最后,工作模式不需过多理会,只要在适当时候拉高CE进行发送即可,配置NRF24L01时CE置低)
接收流程:
① 与发送模式一样,一开始MCU通过SPI对NRF24L01进行基本配置,设置数据通道自动应答使能(在EN_AA寄存器进行设置,即收到数据后,向主机发送应答信号)还有进行接收数据通道使能(在EN_RXADDR寄存器配置,即选择六个接收通道的某一通道来接收数据,设置为接收模式,还有其他等配置。
② 拉高CE引脚(CE置高),启动接收状态
③ 接收到一个有效数据包后,数据存储在RX BUf,并产生RX_DR中断(RX_DR为接收数据成功标志位,接收成功置1),中断和发送模式一样,同样需要复位。
④ 接收设备自动向发送设备发送确认信号(无需自己写代码)
⑤ 设置CE引脚为低,NRF24L01进入待机模式一
⑥ MCU通过SPI读取NRF24L01收到的数据
总结为:
发送过程:
a. MCU通过SPI对NRF24L01进行基本配置,配置好NRF24L01
b. MCU将要发送的数据与接收数据设备的地址写入NRF24L01
c. CE引脚置高,启动发送
接收过程:
a. MCU通过SPI对NRF24L01进行基本配置,配置好NRF24L01
b. CE引脚置高,启动接收
c. MCU对 NRF24L01进行数据读取
5、我们在使用NRF24L01的时候有一个头文件,是关于NRF24L01的寄存器定义和相关函数的编写,这个文档网上有很多,我们只需要按照它的发送和接受流程调用相关函数配置寄存器就可以了。
//===================================================================================
// 主 程 序 开 始
//===================================================================================
void main(void)
{
uchar i = 0;
uchar j = 0;
uchar a,b;
unsigned char TxBuf[12] ={2,3,1,4,0,3,1,3,0,2,1,1};
unsigned char RxBuf[12] ;
LCD_init();
init_NRF24L01();
SPI_Read_Buf(RX_ADDR_P0,RxBuf,5);
Delay(100);
SetRX_Mode();
lcd2004_pos(0,4);
dat(‘T’); dat(‘X’);
dat(‘ ’);
dat(‘ ’);
dat(‘T’);
dat(‘E’);
dat(‘X’);
dat(‘T’);
dat(‘。’);
dat(‘。’);
dat(‘。’);
status = SPI_Read(STATUS);
a=status / 10;
b=status % 10;
lcd2004_pos(1,0);
dat(‘S’);
dat(‘T’);
dat(‘A’);
dat(‘:’);
dat(0x30+a);
dat(0x30+b);
fifo = SPI_Read(FIFO_STATUS);
a=fifo / 10;
b=fifo % 10;
lcd2004_pos(1,8);
dat(‘F’); dat(‘I’);
dat(‘F’);
dat(‘O’);
dat(‘:’);
dat(0x30+a);
dat(0x30+b);
while(1)
{
//===================================================================================
// 发 送 程 序
//===================================================================================
SPI_RW_Reg(WRITE_REG+STATUS,0xFF);
SPI_Write_Buf(WR_TX_PLOAD,TxBuf,TX_PLOAD_WIDTH);
nRF24L01_TxPacket(TxBuf);
status = SPI_Read(STATUS);
a=status / 10;
b=status % 10;
lcd2004_pos(1,0);
dat(‘S’);
dat(‘T’);
dat(‘A’);
dat(‘:’);
dat(0x30+a);
dat(0x30+b);
fifo = SPI_Read(FIFO_STATUS);
a=fifo / 10;
b=fifo % 10;
lcd2004_pos(1,8);
dat(‘F’);
dat(‘I’);
dat(‘F’);
dat(‘O’);
dat(‘:’);
dat(0x30+a);
dat(0x30+b);
SPI_RW_Reg(WRITE_REG+STATUS,0xFF);
//==================================================================================
// 接 收 程 序
//==================================================================================
lcd2004_pos(0,0);
dat(‘R’);dat(‘X’);dat(‘。’);dat(‘。’);dat(‘。’);
j = SPI_Read(CD);
lcd2004_pos(0,6);
dat(‘C’);
dat(‘D’);
dat(‘:’);
lcd2004_pos(0,10);
dat(0x30+j);
Delay(1000);
if(nRF24L01_RxPacket(RxBuf)==1)
{
lcd2004_pos(1,0);
for(i=0;i《12;i++)
{
dat(0X30+RxBuf[i]);
}
}
这里只是程序的一部分,用到了1602液晶显示。程序中通过读取寄存器STATUS、FIFO来判断发射部分的状态,如果发射成功,则寄存器的数值就会发生改变。
同理,在接收端,我也读取了寄存器CD的值。意思大概就是如果接收端收到载波,则寄存器的值就会变成1,如果没有检测到任何的载波信号,那么寄存器的值就为0。
通过检测寄存器的状态就可以判断两个模块是否正常工作。举个例子,如果发射端的两个寄存器的值正常改变,那么说明发生端是正常工作的。再到接收端观察,如果CD的值始终为0,那么说明接受端的模块出现问题。就这样可以缩小排错的范围。
正常情况下来说,如果发射和接收都正常的话,通过函数nRF24L01_RxPacket(RxBuf)就可以读取接收端缓冲区的值,这个数组值的大小与你发送的数组大小一样。
全部0条评论
快来发表一下你的评论吧 !