nRF24L01无线通信模块使用手册
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
nRF24L01无线通信模块使用手册
一、模块简介
该射频模块集成了NORDIC公司生产的无线射频芯片nRF24L01:
1.支持2.4GHz的全球开放ISM频段,最大发射功率为0dBm
2.2Mbps,传输速率高
3.功耗低,等待模式时电流消耗仅22uA
4.多频点(125个),满足多点通信及跳频通信需求
5.在空旷场地,有效通信距离:25m(外置天线)、10m(PCB天线)
6.工作原理简介:
发射数据时,首先将nRF24L01配置为发射模式,接着把地址TX_ADDR和数据TX_PLD 按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号。
如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从发送堆栈中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC_T)达到上限,MAX_RT置高,TX_PLD不会被清除;MAX_RT或TX_DS置高时,使IRQ变低,以便通知MCU。
最后发射成功时,若CE为低,则nRF24L01进入待机模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入待机模式2。
接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。
当接收方检测到有效的地址和CRC时,就将数据包存储在接收堆栈中,同时中断标志位RX_DR置高,IRQ变低,以便通知MCU去取数据。
若此时自动应答开启,接收方则同时进入发射状态回传应答信号。
最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。
三、模块引脚说明
1 / 19
7 NC 空 8 CSN 芯片片选信号 I 9 CE 工作模式选择
I 10
+5V
电源
四、模块与AT89S52单片机接口电路
注:上图为示意连接,可根据自己实际需求进行更改;使用AT89S52MCU 模块时,请将Nrf24L01通讯模块每个端口(MOSI 、SCK 、CSN 和CE )接4.7K 的排阻上拉到VCC 增强其驱动能力(如下图:)。
若使用其它单片机与Nrf24L01通讯模块相连时请串联2K 电阻。
VCC P1.0 P1.1
P1.2 P1.3 P1.4 P3.2 GND
AT89S52MCU 模块 +5V CE CSN SCK MOSI MISO IRQ GND
Nrf24L01通讯模块
3 / 19
五、工作模式控制
注1:进入此模式后,只要CSN 置高,在FIFO 中的数据就会立即发射出去,直到所有数据数据发射完毕,之后进入待机模式II 。
注2:正常的发射模式,CE 端的高电平应至少保持10us 。
24L01将发射一个数据包,之后进入待机模式I 。
六、数据和控制接口 通过以下六个引脚,可实现模块的所有功能: ①IRQ (低电平有效,中断输出)
②CE (高电平有效,发射或接收模式控制) ③CSN (SPI
信号) ④SCK (SPI 信号) ⑤MOSI (SPI 信号) ⑥MISO (SPI 信号) 通过SPI 接口,可激活在数据寄存器FIFO 中的数据;或者通过SPI 命令(1个字节长度)访问寄存器。
在待机或掉电模式下,单片机通过SPI 接口配置模块;在发射或接收模式下,单片机通过SPI 接口接收或发射数据。
1.SPI 指令 所有的SPI 指令均在当CSN 由低到高开始跳变时执行;从MOSI 写命令的同时,MISO 实时返回24L01的状态值;SPI 指令由命令字节和数据字节两部分组成。
SPI 命令字节表
FLUSH_TX 1110 0001 0 在发射模式下,清空TX FIFO寄存器。
FLUSH_RX 1110 0010 0 在接收模式下,清空RX FIFO寄存器。
在
传输应答信号时不应执行此操作,否则不
能传输完整的应答信号。
REUSE_TX_PL 1110 0011 0 应用于发射端。
重新使用上一次发射的有
效数据,当CE=1时,数据将不断重新发
射。
在发射数据包过程中,应禁止数据包
重用功能。
NOP 1111 1111 0 空操作。
可用于读状态寄存器。
2.SPI时序
SPI读写时序见下面两图。
在写寄存器之前,一定要进入待机模式或掉电模式。
其中,——SPI指令位;Sn——状态寄存器位;Dn——数据位(低字节在前,高字节在后;每个字节中高位在前)
SPI读时序
SPI写时序
地址
(十六进制)
寄存器位复位值类型说明
00 CONFIG 配置寄存器
Reserved 7 0 R/W 默认为0
MASK_RX_DR 6 0 R/W 可屏蔽中断RX_RD
1:中断产生时对IRQ没影响0:RX_RD中断产生时,IRQ 引脚为低
MASK_TX_DS 5 0 R/W 可屏蔽中断TX_RD
1:中断产生时对IRQ没影响0:TX_RD中断产生时,IRQ 引脚为低
5 / 19
7 / 19
八、模块编程控制
1.ShockBurst TM发射模式
9 / 19
①设置PRIM_RX为低。
②通过SPI接口,将接收节点地址(TX_ADDR)和有效数据(TX_PLD)写入模块,写TX_PLD 时,CSN必须一直置低。
③置CE为高,启动发射。
CE高电平持续时间至少为10us。
④ShockBurst TM发射模式:
系统上电
启动内部16MHz时钟
数据打包
数据发射
⑤若启动了自动应答模式(ENAA_P0=1),则模块立即进入接收模式(NO_ACK已设置)。
如果接收到应答信号,则表示发射成功,TX_DS置高且TX FIFO中的有效数据被移出;如果没有接收到应答信号,则自动重发(自动重发已设置);如果自动重发次数超过最大值(ARC),MAX_RT置高,在TX FIFO中的数据不被移出。
当MAX_RT和TX_DS置高时,IRQ激活。
只有重新写状态寄存器(STATUS)才能关闭IRQ。
如果重发次数达到最大后,仍没有接收到应答信号,在MAX_RT中断清除之前,不会再发射数据。
PLOS_T计数器会增加,每当有一个MAX_RT中断产生。
⑥如果CE置低,则系统进行待机模式I,否则发送TX FIFO寄存器中的下一个数据包。
当TX FIFO中的数据发射完,CE仍为高时,系统进入待机模式II。
⑦在待机模式II下,CE置低,则进入待机模式I。
2.ShockBurst TM接收模式
①设置PRIM_RX为高,配置接收数据通道(EN_RXADDR)、自动应答寄存器(EN_AA)和有效数据宽度寄存器(RX_PW_PX)。
②置CE为高,启动接收模式。
③130us后,模块检测空XX号,
④接收到有效的数据包后(地址匹配、CRC检验正确),数据储存在RX FIFO中,RX_DR 置高。
⑤如果启动了自动应答功能,则发送应答信号。
⑥MCU置CE为低,进入先机模式I。
⑦MCU可通过SPI接口将数据读出
⑧模块准备好进入发射模式或接收模式或待机模式。
11 / 19
九、RF通道频率
RF通道频率指的是nRF24L01所使用的中心频率,该频率X围从2.400GHz到2.525GHz,以1MHz区分一个频点,故有125个频点可使用。
由参数RF_CH确定,公式为:F0 = 2400 + RF_CH(MHz)
十、示例程序
接收模块与发射模块大部分程序代码相同,如下:
1.SPI命令和寄存器配置头文件API.h(根据第六、七两点编写)
#ifndef _BYTE_DEF_
#define _BYTE_DEF_
typedef unsigned char BYTE;
#endif
// SPI命令
#define READ_REG 0x00 //读第0个寄存器
#define WRITE_REG 0x20 //写第0个寄存器
#define RD_RX_PLOAD 0x61 //在接收模式下使用,读有效数据
#define WR_TX_PLOAD 0xA0 //在发送模式下使用,写有效数据
#define FLUSH_TX 0xE1 //在发送模式下使用,清TX FIFO寄存器
#define FLUSH_RX 0xE2 //在接收模式下使用,清RX FIFO寄存器
#define REUSE_TX_PL 0xE3 //发送方使用,重复发送最后的数据
#define NOP 0xFF //空操作,用于读状态寄存器STATUS的值
// nRF24L01寄存器地址
#define CONFIG 0x00 //配置寄存器,8bit
#define EN_AA 0x01 //自动应答设置寄存器,8bit
#define EN_RXADDR 0x02 //接收地址设置寄存器,8bit
#define SETUP_AW 0x03 //地址宽度设置寄存器,8bit
#define SETUP_RETR 0x04 //自动重复发送设置寄存器,8bit
#define RF_CH 0x05 //RF通道寄存器,8bit
#define RF_SETUP 0x06 //RF设置寄存器,8bit
#define STATUS 0x07 //状态寄存器,8bit
#define OBSERVE_TX 0x08 //发送观测寄存器,8bit
#define CD 0x09 //载波检测寄存器,8bit,
#define RX_ADDR_P0 0x0A //接收地址数据通道0,40bit
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10 //发送地址.发送方使用,40bit
#define RX_PW_P0 0x11 //通道0接收的有效数据字节长度(1-32字节),8bit
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
13 / 19
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17 //FIFO状态寄存器,8bit
2.SPI操作头文件(与单片机的接口设置在此头文件中)
#defineuchar unsigned char
#define TX_ADR_WIDTH 5 //地址长度为5个字节
#defineTX_PLOAD_WIDTH 20 //数据长度为20个字节
uchar const TX_ADDRESS[TX_ADR_WIDTH] = {0xE7,0xE7,0xE7,0xE7,0xE7};
char rx_buf[TX_PLOAD_WIDTH]; //接收缓冲区
ucharflag; //标志位
int test[12];
#define CE P0_0 //芯片使能:Chip Enable
#define CSN P0_1 //片选信号:Chip Select Not
#define SCK P1_2 //串行时钟信号:Serial Clock
#defineMOSI P0_3 //主发从收:Master In Slave Out
#define MISO P0_4 //主收从发:Master Out Slave In
#defineIRQ P3_2 //中断查询:Interrupt Request
uchar bdata sta;
sbit RX_DR = sta^6;
sbit TX_DS = sta^5;
sbit MAX_RT = sta^4;
uchar SPI_RW(uchar byte)//写一个字节到nRF24L01,并返回此时nRF24L01的状态及数据
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) //先写字节的高位,再写低位
{
MOSI = (byte & 0x80); //MOSI取byte最高位
byte = (byte << 1); //byte左移一位
SCK = 1; //SCK从高到低时开始写入
byte |= MISO;
//获取MISO位.从MOSI写命令的同时,MISO返回nRF24L01的状态及数据SCK = 0;
}
return(byte);
}
uchar SPI_RW_Reg(BYTE reg, BYTE value)//将字节value写入寄存器reg
{
uchar status;
CSN = 0; //CSN为0时,才能进行SPI读写
status = SPI_RW(reg); //选择寄存器reg
SPI_RW(value); //写字节value到该寄存器
CSN = 1; //终止SPI读写
return(status);
}
BYTE SPI_Read(BYTE reg)//读寄存器reg状态字
{
BYTE reg_val;
CSN = 0; //CSN为0时,才能进行SPI读写
SPI_RW(reg); //选择寄存器reg
reg_val = SPI_RW(0); //写0,什么操作也不进行,仅仅为了读寄存器状态
CSN = 1; //终止SPI读写
return(reg_val);
}
uchar SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
//从寄存器reg读出数据,典型应用是读RX数据或RX/TXF地址{
uchar status,byte_ctr;
CSN = 0; //CSN为0时,才能进行SPI读写
status = SPI_RW(reg); //选择寄存器reg并返回其状态字
for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); //从寄存器读数据
CSN = 1; //终止SPI读写
return(status); //返回状态值
}
uchar SPI_Write_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)//将数据写入寄存器,如TX数据,RX/TX地址等. {
uchar status,byte_ctr;
CSN = 0; //CSN为0时,才能进行SPI读写
status = SPI_RW(reg); //选择寄存器reg并返回其状态字
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)
SPI_RW(*pBuf++); //写数据到寄存器
CSN = 1; //终止SPI读写
return(status); //返回状态值
}
//接收模式初始化:设置RX地址,RX数据宽度,RF通道,速率,低噪声放大器增益
//设置完之后,将CE置高,准备好接收数据
void RX_Mode(void)
{
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
// 写TX_Address 到nRF24L01 SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 自动重发延时:500us + 86us;重发次数:10次
15 / 19
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
//将地址TX_ADDRESS写入寄存器0的数据通道0
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //ENAA_P0=1,数据通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //ERX_P0=1,使能
SPI_RW_Reg(WRITE_REG + RF_CH, 40); //40个通信频段
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);
//数据通道0的RX数据长度为TX_PLOAD_WIDTH,要与发送的一致SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0F);
//速率为2Mbps,发送功率为0dBm,低噪声放大器增益为1 SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);
//PRIM_RX=1,接收方;PWR_UP=1;CRC检验字为2字节;
}
//发送模式初始化:设置发送地址,设置发送的数据,设置接收方地址,RF通道,速率等,与接收类似
void TX_Mode(void)
{
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
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 + EN_AA, 0x01);
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);
SPI_RW_Reg(WRITE_REG + RF_CH, 40);
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f);
}
void show_status(void) //显示状态寄存器的值
{
test[0] = SPI_Read(EN_AA); //0x01
test[1] = SPI_Read(EN_RXADDR); //0x01
test[2] = SPI_Read(SETUP_AW); //0x03,5个字节
test[3] = SPI_Read(SETUP_RETR); //0x1a
test[4] = SPI_Read(RF_CH); //0x28
test[5] = SPI_Read(RF_SETUP); //0x0f
test[6] = SPI_Read(RX_ADDR_P2);
test[7] = SPI_Read(RX_ADDR_P3);
test[8] = SPI_Read(RX_ADDR_P4);
test[9] = SPI_Read(RX_ADDR_P5);
test[10] = SPI_Read(RX_PW_P0); //0x14
test[11] = SPI_Read(STA TUS);
}
void init_io(void)
{
CE = 0; //待机
CSN = 1; //SPI禁止读写
SCK = 0;
}
void Inituart(void)//设置串口工作模式
{
TMOD |= 0x20; //定时器1工作在方式2,8位自动重装模式
TL1 = 0xfd; //波特率为9600
TH1 = 0xfd;
SCON = 0x50; //模式1,8位数据
TR1 = 1; //启动定时器1
TI=1;
}
void init_int0(void)//外部中断设置
{
EA=1; //允许全局中断
ES=1; //开串行口中断
EX0=1; //允许外部中断0
}
void delay_ms(unsigned int x) //毫秒级延时
{
unsigned int i,j;
i=0;
for(i=0;i<x;i++)
{
j=108;
while(j--);
}
}
3.发送模块主函数(向接收模块发射数据“abcdefg”,中断方式)void main(void)
{
int i;
init_io(); //IO端口设置
Inituart(); //串口设置
init_int0(); //外部中断0设置
for(i=0;i<7;i++) //待发的数据tx_buf,发送的数据为”abcdefg”七个字母tx_buf[i] = 'a'+i;
17 / 19
while(1)
{
CE = 0; //Standby-1模式
TX_Mode(); //发送设置
CE = 1; //启动发送模式
delay_ms(20);
CE = 0; //Standby-1模式
delay_ms(1000);
}
}
//中断函数
//如果RX_DR=1,则读取数据,之后清除标志位;
//如果TX_DS或MAX_RT为1,则仅清除中断标志位
void ISR_int0(void) interrupt 0
{
sta=SPI_Read(STATUS); //读状态寄存器STATUS
if(RX_DR) //如接收到数据,则中断
{
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);//读取接收的数据
flag=1; //标志位置高
}
if(MAX_RT) //重发中断达到最大数
SPI_RW_Reg(FLUSH_TX,0); //清除TX FIFO寄存器
SPI_RW_Reg(WRITE_REG+STATUS,sta);//清除RX_DR,TX_DS和MAX_RT中断标志位
}
4.接收模块主函数(接收并在串口输出,同时输出状态寄存器的值,使用查询方式)void main(void)
{
int i;
init_io(); //IO端口设置
Inituart(); //串口设置
init_int0(); //外部中断0设置
CE=0; //Standby-1模式
RX_Mode(); //设置接收模式
CE = 1; //准备接收数据
while(1)
{
sta=SPI_Read(STATUS);
if(RX_DR) //接收到数据
{
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);//读取接收的数据
for(i=0;i<7;i++)
printf("%c ",rx_buf[i]); //通过串口发送接收到的数据
printf("\n");
show_status(); //输出状态寄存器的值,可不用此操作
for(i=0;i<12;i++)
printf("%x ",test[i]);
printf("\n");
delay_ms(10);
}
if(MAX_RT) //重发中断达到最大数
SPI_RW_Reg(FLUSH_TX,0); //清除TX FIFO寄存器
SPI_RW_Reg(WRITE_REG+STATUS,sta); //清除RX_DR,TX_DS和MAX_RT中断标志位}
}
19 / 19。