nRF24L01--2.4G无线通信模块(1)(51单片机和51单片机通信)
作者:李剀
出处: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}}
}
上面的代码很详尽了,想要完整工程的可以下载----->>>完整代码工程文件(接收端+发射端)
凡事不要说“我不会”或“不可能”, 因为你根本还没有去做! 加油吧
nRF24L01--2.4G无线通信模块(1)(51单片机和51单片机通信)相关推荐
- 2.2 Arduino各类模块-3(NRF24L01 2.4G无线模块单向双向传输)
6.2.4G无线模块(NRF24L01) 说明: 使用1.9-3.6v供电,典型供电3.3v NRF24L01 2.4G无线模块我们分为两个部分,使用两个不同的库进行实现. NRF24L01硬件上具有 ...
- 无线通信模块行业介绍
无线通信模块可使功能单一的终端拥有数据传输的能力,无线通信模块是各类智能终端得以接入物联网的信息入口. 其是连接物联网感知层和网络层的关键环节, 所有物联网感知层终端产生的设备数据需要通过无线通信模块 ...
- 2.4G无线技术参数及行业分享
谈到2.4G很多人第一印象是Bluetooth.zigbee等目前主流的通信技术,殊不知除了这些还有另外一种适合工业.消费类,2.4G通讯技术频谱同样落在ISM频段内,其频率是2400MHZ-2525 ...
- 2.4G无线模块(NRF24L01)学习(1)——串口实现两个模块之间信息交互
先看模块,如下图: 一个模块的使用,必须先阅读产品文档,我为了学习这个模块,特地将资料文档下载下来,逐一阅读理解,这样以后才能灵活使用其模块. NRF24L01+模块的使用还是有一定的复杂度的,复杂度 ...
- NRF24L01 无线通信模块使用方法
原文出处:http://blog.csdn.net/mc_hust/article/details/39473913 昨天登录百度账号,无意间发现漏看了好多朋友的私信,其中不少是找我探讨关于NRF24 ...
- nRF24L01无线通信模块使用简介(接收端)
nRF24L01无线通信模块使用简介(STC51)接收端 书接上回,上篇博客给出了nRF24L01搭配C51单片机进行无线通信的发送端代码.这里给出接收端代码. 接收端 接收端的功能主要是接收发送端发 ...
- ec200s 方案 移远_移远 4G Cat 1 无线通信模块EC200S
EC200S 是移远通信最近推出的LTE Cat 1 无线通信模块,支持最大下行速率10Mbps 和最大上行速率5Mbps,具有超高的性价比:同时在封装上兼容移远通信多网络制式LTE Standard ...
- 433遥控器无线解码 1527中断方式解码 51单片机
433遥控器无线解码 1527中断方式解码 51单片机 这版为1527遥控器解码,是为了项目洗臀器做遥控器控制.1527遥控器原理如下. 码分别为:同步码 地址码20位 键码4位(也可以同步码16位 ...
- 2.4G无线芯片NRF24L01 驱动源码及详解
概述 NRF24L01/NRF24L01+ 是挪威NordicVLSI公司出品的2.4G射频收发器件,主打高速率,低功耗,应用简单功能.其性能卓越(我说的原厂真货),深受国内开发者欢迎.原厂芯片价格一 ...
最新文章
- 7 1学会使用 Node 编写简单的前端应用
- hexo + Github 搭建问题综述
- 组件化开发思想||全局组件注册语法||组件注册注意事项
- VC\JS Base64转码
- Windows XP \Windows 2003启动过程的学习及故障分析处理(四)
- nullnulle-人事管理系统-人事档案-变更管理-人员合同变更
- 根据年 -月查询这个月的第一天和最后一天
- Thinkphp编辑器扩展类kindeditor用法
- HTTP协议/RTSP协议/RTMP协议的区别
- 判断两个结构体是否相等
- 【转】C#实现SM2国密加密
- 【Android】命令行jarsigner签字和解决找不到证书链错误
- 页面加载被延迟 Firefox将禁用对DV和OV证书的OCSP检查
- import和class关键字的区别
- MySQL数据库如何管理与维护_MySQL安全管理、数据库维护及改善性能
- API RSA签名颁发证书
- MATLAB数学建模方法与实践(第3版)程序及数据
- 时速云:基于K8S的容器PaaS,将成为未来IT基础设施的重要组成部分
- 网页监控系统设计之使用mjpg-streamer
- Java中new一个对象的过程