nRF24L01--2.4G无线通信模块(1)(51单片机和51单片机通信)

article/2025/9/21 0:46:04

作者:李剀

出处:https://www.cnblogs.com/kevin-nancy/

或者
https://blog.csdn.net/Kevin_8_Lee/article/details/95667604

欢迎转载,但也请保留上面这段声明。谢谢!(上面两个都是我的博客,只是在不同平台,大家可以点击链接看一下我的博客哦~~~)

写在前面:这一篇先介绍一下两个51单片机之间通过nRF24L01模块通信的过程,下一篇我会写 51单片机STM32F407 单片机通信过程。

关于nRF24L01这个模块,网上可以说是资料非常多了,我参考的是云佳科技的pdf以及官方的datasheet英文数据手册。 另外,关于这个模块的介绍以及能够用来做什么也不过多的废话,数据手册及说明书都有。

51单片机我使用的是买来的开发板,核心是STC89C52,大家不必担心平台不同,都是使用软件模拟spi,引脚怎么定义都可以,也可以选择跟我使用的不一样的引脚,都Ok的。


一、硬件介绍


1、 nRF24L01模块接口电路见下图

在这里插入图片描述
单片机是作为主机的,即Master nRF24L01作为从机,即Slave;

这样大家应该会很好理解MOSI和MISO了,,在我的另一篇博客也有SPI介绍,STM32F407使用MFRC522射频卡调试及程序移植成功,
这个我是在STM32上调试的,可以参考一下里面对spi MOSI和MISO的解释


1 GND ------>> 接地(与单片机共地)

2 VCC ------>> 1.9~3.6V (推荐3.3V)

3 CE ------>> RX 或 TX模式选择 高电平>10us则为发送模式 持续高电平为接收模式
设为低电平是待机模式

4 CSN ------>> SPI片选信号 低电平使能,默认状态应该设置为高,以免发生错误的数据传输

5 SCK ------>> SPI时钟信号

6 MOSI ------>> 从SPI数据输入脚 (这里解释一下MOSI对应的单片机引脚输出信号, 即单片机输出数据给nRF24L01)

7 MISO ------>> 从SPI数据输出脚 (MISO对应单片机引脚设置为输入, 即数据从nRF24L01出来送进单片机 )

注:对于51单片机,无需设置单片机引脚的输入输出,但是STM32单片机需要设置

8 IRQ ------>> 可屏蔽中断脚 中断 低电平使能


** PS:**

1) VCC电压供电范围要求1.9~3.6V之间,由于51单片机大多是5V,所以自己的开发板上没有无线模块接口的要注意,把VCC另外接到这个范围的电压上,电压过高会烧坏模块。。 推荐 3.3V 其他引脚无电压要求

2) 用普通单片机IO口模拟SPI协议即可控制该模块,我一般都是用模拟SPI,可移植性高

该模块使用的芯片方框图如下

在这里插入图片描述

2、 单片机2.4G模块引脚接口
在这里插入图片描述
3、 单片机按键引脚图

在这里插入图片描述
4、 硬件连接实物图(我用的两个相同的51单片机,所以引脚都一样,只是程序里面接收模式和发送模式略微不同)
在这里插入图片描述
在这里插入图片描述


二、软件部分


对于某个模块写程序是一定要参照datasheet的时序图, 这样才可以保证不出错。

下面是我从 nRF24L01 datasheet上截的SPI 时序图
在这里插入图片描述

变量设置及宏定义 接收端和发射端一样

// 宏定义
#define     uchar       unsigned char 
#define     uint        unsigned int #define     TX_ADR_WIDTH    5  // 5字节宽度的发送/接收地址
#define     TX_PLOAD_WIDTH  4  // 数据通道有效数据宽度// LED灯及按键位定义
sbit LED = P1^0;
sbit KEY1 = P3^0;
sbit KEY2 = P3^1;
sbit BEEP = P2^3;uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址uchar RX_BUF[TX_PLOAD_WIDTH];
uchar TX_BUF[TX_PLOAD_WIDTH];
uchar flag;
uchar DATA = 0x01;
uchar bdata sta;
sbit  RX_DR     = sta^6;
sbit  TX_DS     = sta^5;
sbit  MAX_RT    = sta^4;// NRF24L01 模块引脚位定义
sbit CE  =  P1^2;
sbit CSN =  P1^3;
sbit SCK =  P1^7;
sbit MOSI= P1^5;
sbit MISO= P1^6;
sbit IRQ = P1^4;

寄存器设置

/*  SPI(nRF24L01) 指令设置指令格式<命令字  : 由高位到低位(每字节)><数据字节: 低字节到高字节,每一字节高位在前>*/
#define READ_REG    0x00  // Define read command to register
#define WRITE_REG   0x20  // Define write command to register
#define RD_RX_PLOAD 0x61  // Define RX payload register address
#define WR_TX_PLOAD 0xA0  // Define TX payload register address
#define FLUSH_TX    0xE1  // 清除 TX FIFO寄存器  应用于发射模式下
#define FLUSH_RX    0xE2  // 清除 RX FIFO寄存器  应用于接收模式下。
#define REUSE_TX_PL 0xE3  // 重新使用上一包有效数据。 当CE=1,数据包被不断重新发射 发射过程中必须禁止数据包重利用功能
#define NOP         0xFF  // 空操作。可以用来读状态寄存器/*  SPI(nRF24L01) registers(addresses)*/
#define CONFIG      0x00  // 'Config' register address
#define EN_AA       0x01  // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR   0x02  // 'Enabled RX addresses' register address
#define SETUP_AW    0x03  // 'Setup address width' register address
#define SETUP_RETR  0x04  // 'Setup Auto. Retrans' register address
#define RF_CH       0x05  // 'RF channel' register address
#define RF_SETUP    0x06  // 'RF setup' register address
#define STATUS      0x07  // 'Status' register address
#define OBSERVE_TX  0x08  // 'Observe TX' register address
#define CD          0x09  // 'Carrier Detect' register address
#define RX_ADDR_P0  0x0A  // 'RX address pipe0' register address
#define RX_ADDR_P1  0x0B  // 'RX address pipe1' register address
#define RX_ADDR_P2  0x0C  // 'RX address pipe2' register address
#define RX_ADDR_P3  0x0D  // 'RX address pipe3' register address
#define RX_ADDR_P4  0x0E  // 'RX address pipe4' register address
#define RX_ADDR_P5  0x0F  // 'RX address pipe5' register address
#define TX_ADDR     0x10  // 'TX address' register address
#define RX_PW_P0    0x11  // 'RX payload width, pipe0' register address
#define RX_PW_P1    0x12  // 'RX payload width, pipe1' register address
#define RX_PW_P2    0x13  // 'RX payload width, pipe2' register address
#define RX_PW_P3    0x14  // 'RX payload width, pipe3' register address
#define RX_PW_P4    0x15  // 'RX payload width, pipe4' register address
#define RX_PW_P5    0x16  // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17  // 'FIFO Status Register' register address

1 简介一下 Enhanced ShockBurstTM发射流程


A. 把接收机的地址和要发送的数据按时序送入NRF24L01;

B. 配置CONFIG寄存器,使之进入发送模式。

C. 微控制器把CE置高(至少10us),激发NRF24L01进行Enhanced ShockBurstTM发射;

D. N24L01的Enhanced ShockBurstTM发射

 (1)  给射频前端供电;(2) 射频数据打包(加字头、CRC校验码); (3) 高速发射数据包; (4) 发射完成,NRF24L01进入空闲状态。

********** ** 发射端代码 ** *********
1) 首先初始化IO口

// 初始化IO
void init_io(void)
{CE  = 0;        // 待机CSN = 1;        // SPI禁止SCK = 0;        // SPI时钟置低IRQ = 1;        // 中断复位LED = 1;        // 关闭指示灯
}

2) 通过SPI对24L01进行读写的函数 返回读取的字节

uchar SPI_RW(uchar byte)
{uchar   bit_ctr;// output 8-bitsfor (bit_ctr = 0; bit_ctr < 8; bit_ctr++){MOSI = (byte & 0x80);   // output ‘byte’  MSB to MOSIbyte = (byte << 1);     // shift next bit into MSB..SCK = 1;                // Set SCK high.. 24L01 read 1-bit from MOSI and output 1-bit to MISO byte |= MISO;           // capture current MISO bit SCK = 0;                // ..then set SCK low again}return (byte);  // return read byte
}

3)

通过SPI协议向寄存器reg 写入数据value

uchar SPI_RW_Reg(uchar reg, uchar value)
{uchar status;CSN = 0;                // CSN low, init SPI transaction, start transmitting datastatus = SPI_RW(reg);   // select register and return status byteSPI_RW(value);          // ..and write value to it..CSN = 1;                // CSN high again, transmission endreturn(status);         // return nRF24L01 status byte
}

4) 从寄存器reg中读数据 返回读取的数据

uchar SPI_Read(uchar reg)
{uchar reg_val;CSN = 0;                    // CSN置低,开始传输数据SPI_RW(reg);                // 选择寄存器reg_val = SPI_RW(0);        // 然后从该寄存器读数据CSN = 1;                    // CSN拉高,结束数据传输return(reg_val);            // 返回寄存器数据}

5) 从reg寄存器读 bytes 个字节

uchar SPI_Read_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 read & return status bytefor (byte_ctr = 0; byte_ctr < bytes; byte_ctr++)pBuf[byte_ctr] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1;                    // set CSN high, stop transactionreturn(status);             // return nRF24L01 status byte
}

6) 往reg寄存器写入 bytes 个字节

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 & return status bytefor (byte_ctr = 0; byte_ctr < bytes; byte_ctr++) SPI_RW(*pBuf++);    // 逐个字节写入nRF24L01CSN = 1;                // Set CSN high again 结束数据传输return(status);         // 返回状态寄存器
}

7) 设置nRF24L01为接收模式的函数,等待接收发送设备的数据包

void RX_Mode(void)
{CE = 0;SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);  // 接收设备接收通道0使用和发送设备相同的发送地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);               // 使能接收通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);           // 使能接收通道0SPI_RW_Reg(WRITE_REG + RF_CH, 40);                 // 选择射频通道0x40SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);            // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);              // CRC使能,16位CRC校验,上电,接收模式delay_ms(150);CE = 1;                                            // 拉高CE启动接收设备
}

8) 设置nRF24L01为发送模式

void TX_Mode(uchar *BUF)
{CE = 0;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);  // 为了应答接收设备,接收通道0地址和发送地址相同SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH);                  // 写数据包到TX FIFOSPI_RW_Reg(WRITE_REG + EN_AA, 0x01);       // 使能接收通道0自动应答SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);   // 使能接收通道0SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a);  // 自动重发延时等待250us+86us,自动重发10次SPI_RW_Reg(WRITE_REG + RF_CH, 40);         // 选择射频通道0x40SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);    // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);      // CRC使能,16位CRC校验,上电delay_ms(150);CE = 1;
}

9) 检查接收设备有无接收到数据包

uchar Check_ACK(bit clear)
{delay_ms(200);while(IRQ);             // 等待数据接收完成sta = SPI_RW(NOP);      // 返回状态寄存器if(TX_DS){LED0 = ~LED0;delay_ms(200);LED0 = ~LED0;delay_ms(200);LED0 = ~LED0;delay_ms(200); }if(MAX_RT)if(clear)                         // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发SPI_RW(FLUSH_TX);SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志IRQ = 1;if(TX_DS)return(0x00);elsereturn(0xff);
}

10) 按键扫描

// 按键扫描
void CheckButtons()
{if(KEY1 == 0){delay_ms(10);if(KEY1 == 0){while(!KEY1);TX_BUF[0] = 1;          // 数据送到缓存TX_Mode(TX_BUF);        // 把nRF24L01设置为发送模式并发送数据Check_ACK(0);           // 等待发送完毕,清除TX FIFOdelay_ms(250);delay_ms(250);}}if(KEY2 == 0){delay_ms(10);if(KEY2 == 0){while(!KEY2);TX_BUF[0] = 2;          	// 数据送到缓存TX_Mode(TX_BUF);            // 把nRF24L01设置为发送模式并发送数据 Check_ACK(0);               // 等待发送完毕,清除TX FIFOdelay_ms(250);delay_ms(250);}}
}

11) 主函数

void main(void)
{init_io();                      // 初始化IOwhile(1){CheckButtons();           // 按键扫描}
}

2 Enhanced ShockBurstTM接收流程

A. 配置本机地址和要接收的数据包大小;

B. 配置CONFIG寄存器,使之进入接收模式,把CE置高。

C. 130us后,NRF24L01进入监视状态,等待数据包的到来;

D. 当接收到正确的数据包(正确的地址和CRC校验码),NRF2401自动把字

头、地址和CRC校验位移去;

E. NRF24L01通过把STATUS寄存器的RX_DR置位( STATUS一般引起微

控制器中断 )通知微控制器;

F. 微控制器把数据从 NewMsg_RF2401 读出;

G. 所有数据读取完毕后,可以清除STATUS寄存器。NRF2401可以进入

四种主要的模式之一。

接收端代码和发射端是一样的

注意发射端地址和接收端地址一致即可

接收端主函数

void main(void)
{init_io();                      // 初始化IORX_Mode();						// 设置为接收模式while(1){sta = SPI_Read(STATUS);      // 读状态寄存器//delay_ms(200);if(RX_DR)                    // 判断是否接受到数据{SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH);  // 从RX FIFO读出数据flag = 1;}SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除RX_DS中断标志if(flag)                   // 接受完成{if(RX_BUF[0] == 1)// KEY1按下  则蜂鸣器 响1下{BEEP = 0;delay_ms(500);BEEP = 1;delay_ms(500);}if(RX_BUF[0] == 2)	// KEY2按下   蜂鸣器响3下{BEEP = 0;delay_ms(500);BEEP = 1;delay_ms(500);BEEP = 0;delay_ms(500);BEEP = 1;delay_ms(500);BEEP = 0;delay_ms(500);BEEP = 1;delay_ms(500);}flag = 0;               // 清标志delay_ms(250);delay_ms(250);LED = 1;                // 关闭LED}}
}

上面的代码很详尽了,想要完整工程的可以下载----->>>完整代码工程文件(接收端+发射端)

凡事不要说“我不会”或“不可能”, 因为你根本还没有去做! 加油吧

http://chatgpt.dhexx.cn/article/nE9Gn0YI.shtml

相关文章

STM32控制NRF24L01无线模块进行通信

一.NRF2401无线模块 1.模块介绍 功能介绍 (1)2.4Ghz 全球开放ISM 频段免许可证使 2) 最高工作速率2Mbps&#xff0c;高效GFSK调制&#xff0c;抗干扰能力强&#xff0c;特别适合工业控制场合 (3)126 频道&#xff0c;满足多点通信和跳频通信需要 (4) 内置硬件CRC 检错和点对…

NRF24L012.4G模块

文章目录 datasheet1. 相关案例&#xff1a;2. nRF24L01通信的常识1. 发送模式。1.5 补充spi一点知识1. SPI读写时序2. 工作模式2.1 收发模式Enhanced ShockBurstTM收发模式Enhanced ShockBurstTM发送流程&#xff1a;Enhanced ShockBurstTM接收流程&#xff1a; 3. SPI指令 3.…

STM32驱动NRF24L01无线模块

目录 一、模块简介二、工作模式三、主要命令四、配置寄存器五、状态寄存器六、接收模式七、发送模式八、STM32使用NRF24L01模块 一、模块简介 NRF24L01是NORDIC公司生产的一款无线通信芯片&#xff0c;采用FSK调制&#xff0c;内部集成NORDIC自己的Enhanced Short Burst 协议&…

nRF24L01无线模块笔记

nRF24L01模块 官网链接: https://www.nordicsemi.com/Products/nRF24-series 常见的无线收发模块, 工作在2.4GHz频段, 适合近距离遥控和数据传输. nRF24L01是一个能兼顾距离和数据速率的无线模块, 在空旷环境下&#xff0c;2M速率15米, 1M速率30米, 250K速率能达到50米. 和蓝牙…

NRF24L01+模块:一对一双向通信,成功!

查找了很多资料&#xff0c;好多都是复制粘贴转发&#xff0c;或者安装英文手册直译的&#xff08;比如我自己上篇笔记&#xff0c;&#xff0c;&#xff09;&#xff0c;看完还是一脸懵逼&#xff0c;没几个可行的&#xff0c;推荐几个比较实在的资料&#xff1a;手册我也不是…

NRF24L01 无线通信模块使用方法

原文出处&#xff1a;http://blog.csdn.net/mc_hust/article/details/39473913 昨天登录百度账号&#xff0c;无意间发现漏看了好多朋友的私信&#xff0c;其中不少是找我探讨关于NRF2401模块的。从12年到14年的信件都有&#xff08;平时很少注意系统提示信息。。。&#xff0…

STM32 + 无线通信模块 NRF24L01 数据收发

NRF24L01的模块资料&#xff0c;网上已很详尽了&#xff0c;在这不再重复描述知识点了。 这篇文章的目的&#xff0c;旨在把主要知识点胶接起来&#xff0c;梳理成一套完整的步骤&#xff0c;使器件快速上手汇入工作使用。 将按操作顺序&#xff0c;拆分成7个步骤&#xff0c;…

NRF24L01 无线模块

NRF24L01 简介 NRF24L01 可以实现点对点或者是1&#xff08;收&#xff09;对6&#xff08;发&#xff09;的无线通信。NRF24L01 采样SPI通信&#xff0c;很方便连接MCU NRF24L01 无线模块&#xff0c;采用的芯片是 NRF24L01&#xff0c;该芯片的主要特点如下&#xff1a; 1&a…

NRF2401模块

一、模块介绍 (1) 2.4Ghz 全球开放 ISM 频段免许可证使用 (2) 最高工作速率 2Mbps&#xff0c;高效 GFSK 调制&#xff0c;抗干扰能力强&#xff0c;特别适合工业控制场合 (3) 126 频道&#xff0c;满足多点通信和跳频通信需要 (4) 内置硬件 CRC 检错和点对多点通信地址控制…

Nrf24l01无线模块

Nrf24l01无线模块 一&#xff0c;模块介绍 二&#xff0c;接口电路&#xff0c; 模块连接注意点&#xff1a; (1) VCC 脚接电压范围为 1.9V~3.6V 之间&#xff0c;不能在这个区间之外&#xff0c;超 过 3.6V 将会烧毁模块。推荐电压 3.3V 左右。 (2) 除电源 VCC 和接地端&…

51驱动NRF24L01通信,NRF24L01与TTL转NRF24L01模块通信

51驱动NRF24L01通信&#xff0c;NRF24L01与TTL转NRF24L01模块通信 NRF24L01一、简介二、引脚功能描述 程序设计一、对 24L01 的程序编程的基本思路如下&#xff1a;二、Tx 与 Rx 的配置过程1、Tx 模式初始化过程&#xff1a;2、Rx 模式初始化过程&#xff1a; 三、基本程序函数…

详解NRF24L01无线收发模块

近日有粉丝朋友留言&#xff0c;希望介绍一下nRF24L01这款无线收发芯片&#xff0c;正巧前不久的电赛有些涉及&#xff0c;因此将自己的一些经验写在这里&#xff0c;希望能有所收获。 前面我们介绍过单片机的几种通信协议&#xff0c;并且初步了解如何操作寄存器进而控制芯片的…

nRF24L01芯片(模块)介绍

nRF24L01芯片&#xff08;模块&#xff09;简介 nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。无线收发器包括&#xff1a;频率发生器、增强型“SchockBurst”模式控制器、功率放大器、晶体振荡器、调制器和解调器。 输出功率频道选择和协议的…

2.4G通信

文章目录 2.4G无线通信实验一、模块简介二、Enhanced ShockBurstTM模式介绍三. 编程1.初始化IO口2.Enhanced ShockBurstTM发送流程3.Enhanced ShockBurstTM发送模式初始化4.Enhanced ShockBurstTM接收流程5.Enhanced ShockBurstTM接收模式初始化6.读函数7.写函数8.主函数 总结 …

无线收发模块——NRF24L01

1、什么是nRF24L01 nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。有着极低的电流消耗。 nRF24L01与5V单片机的连接通过SPI接口进行通讯&#xff0c;输出功率频道选择和协议的设置可以通过SPI 接口进行设置&#xff0c;几乎可以连接到各种单片…

分布式集群脑裂问题

Zookeeper集群"脑裂"问题 - 运维总结 在分布式集群的脑裂问题中&#xff0c;zookeeper脑裂是一个经典的例子。 在zookeeper集群中&#xff0c;有一个leader和多个follower&#xff08;observer不参与选举&#xff0c;可以忽略&#xff09;&#xff0c;leader通过周…

分布式脑裂问题

"脑裂"定义 脑裂(split-brain)就是“大脑分裂”&#xff0c;也就是本来一个“大脑”被拆分了两个或多个“大脑”&#xff0c;我们都知道&#xff0c;如果一个人有多个大脑&#xff0c;并且相互独立的话&#xff0c;那么会导致人体“手舞足蹈”&#xff0c;“不听使唤…

Redis常见问题——脑裂问题

文章目录 背景一、脑裂问题产生二、选举完成三、总结四、解决方法 背景 脑裂问题&#xff1a;有三台服务器一台主服务器&#xff0c;两台从服务器&#xff0c;还有一个哨兵&#xff08;哨兵就相当于一个代码段&#xff0c;不参与实际业务&#xff09; 一、脑裂问题产生 解释一…

Redis脑裂现象

Redis脑裂现象 什么是Redis的脑裂现象 当Redis主从集群环境出现两个主节点为客户端提供服务&#xff0c;这时客户端请求命令可能会发生数据丢失的情况。 脑裂出现的场景 场景一 主从哨兵集群中如果当发生主从集群切换时&#xff0c;那么一定是超过预设quorum数量的哨兵和主…

redis集群(主从)脑裂及解决方案

什么是redis的集群脑裂&#xff1f; redis的集群脑裂是指因为网络问题&#xff0c;导致redis master节点跟redis slave节点和sentinel集群处于不同的网络分区&#xff0c;此时因为sentinel集群无法感知到master的存在&#xff0c;所以将slave节点提升为master节点。此时存在两个…