51单片机使用NRF24L01进行2.4G无线通信

本文并不打算详细介绍NRF24L01的各个功能寄存器及指令的详细用法,因为网上都可以搜到很多非常详细的教程文档,这里只是介绍一些基本概念、用法以及代码的解释,旨在帮助新手能够快速上手调通快速使用。

基础概念

该模块使用的是SPI协议,SPI协议的具体内容可以参考我的上一篇博文(https://www.chengpei.top/archives/spi-xie-yi-jian-jie),当然不太了解SPI协议的具体内容也没关系,后面的实现代码里已经封装了现成的SPI协议收发数据逻辑。SPI协议只是定义了mcu和NRF24L01模块之间的通信方法,模块的具体使用方法还得看它本身定义的指令以及寄存器的配置。

指令

指令是定义的一些模块可以执行的动作,比如:读寄存器、写寄存器、写数据到空中等等

所有的指令在源码头文件中有定义:

// SPI(nRF24L01) commands
#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  // Define flush TX register command
#define FLUSH_RX    0xE2  // Define flush RX register command
#define REUSE_TX_PL 0xE3  // Define reuse TX payload register command
#define NOP         0xFF  // Define No Operation, might be used to read status register

寄存器

相当于模块中的配置项,可以通过发送指令及内容修改读取模块中的寄存器值,来完成对模块的功能配置

所有的寄存器地址在源码头文件中有定义:

// 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

引脚定义

模块有8个引脚,定义如下:
CSN:芯片的片选线,CSN 为低电平芯片工作。

SCK:芯片控制的时钟线(SPI 时钟)

MISO:芯片控制数据线(Master input slave output)

MOSI:芯片控制数据线(Master output slave input)

IRQ:中断信号。无线通信过程中 MCU 主要是通过 IRQ 与 NRF24L01 进行通信。

CE: 芯片的模式控制线。 在 CSN 为低的情况下,CE 协同 NRF24L01 的 CONFIG 寄存器共同决定 NRF24L01 的状态(参照 NRF24L01 的状态机)

VCC:供电

GND:接地

前4个引脚是SPI协议的引脚,测试代码是基于51单片机的硬件连接方式

// Define SPI pins
sbit CE   = P1^3;  // Chip Enable pin signal (output)
sbit CSN  = P1^4;  // Slave Select pin, (output to CSN, nRF24L01)
sbit IRQ  = P3^3;  // Interrupt signal, from nRF24L01 (input)
sbit MISO = P1^6;  // Master In, Slave Out pin (input)
sbit MOSI = P1^5;  // Serial Clock pin, (output)
sbit SCK  = P1^7;  // Master Out, Slave In pin (output)

关键函数

SPI读写函数

该函数使用代码模拟的SPI通信协议,传入一个字节,函数会将该字节循环输出到MOSI,并且从MISO读取一个字节返回

uchar SPI_RW(uchar byte)
{uchar i;for(i=0; i<8; i++)          // 循环8次{MOSI = (byte & 0x80);   // byte最高位输出到MOSIbyte <<= 1;             // 低一位移位到最高位SCK = 1;                // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据byte |= MISO;          // 读MISO到byte最低位SCK = 0;               // SCK置低}return(byte);               // 返回读出的一字节
}

写寄存器

该函数是给指定寄存器写入数据,第一个参数是写指令+寄存器地址,第二个参数是一个字节的值

uchar SPI_RW_Reg(uchar reg, uchar value)
{uchar status;CSN = 0;                   // CSN置低,开始传输数据status = SPI_RW(reg);      // 选择寄存器,同时返回状态字SPI_RW(value);             // 然后写数据到该寄存器CSN = 1;                   // CSN拉高,结束数据传输return(status);            // 返回状态寄存器
}

写多个字节到寄存器

其实就是写寄存器函数的多字节版本,通过调用循环调用SPI_RW实现多字节的写入,第一个参数是写指令+寄存器地址,第二个参数是字节数组,第三个参数是写入长度

uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
{uchar status, i;CSN = 0;                    // CSN置低,开始传输数据status = SPI_RW(reg);       // 选择寄存器,同时返回状态字for(i=0; i<bytes; i++)SPI_RW(pBuf[i]);        // 逐个字节写入nRF24L01CSN = 1;                    // CSN拉高,结束数据传输return(status);             // 返回状态寄存器
}

设置为接收模式

该函数是设置模块为接收模式

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);                 // NRF24L01使用文档.pdf选择射频通道0x40SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f);            // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);              // CRC使能,16位CRC校验,上电,接收模式CE = 1;                                            // 拉高CE启动接收设备
}

设置发送模式

该函数设置模块为发送模式,并且发送数据

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, 0x1a);  // 自动重发延时等待250us+86us,自动重发10次SPI_RW_Reg(WRITE_REG + RF_CH, 40);         // 选择射频通道0x40SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f);    // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);      // CRC使能,16位CRC校验,上电CE = 1;
}

设置接收/发送模式的流程也可以参考下模块的使用文档的七八两页,文档可以去我的博客页下载:https://www.chengpei.top/archives/51-nrf24l01

完整的示例代码主要逻辑是初始化,设置为接收模式,循环读状态寄存器判断是否可读,读出数据到读缓冲区,如果按钮P3^5被按下,则设置发送模式发送0x31,然后切回接收模式,如果你有两套51单片机加NRF24L01可以烧录进去进行读写测试

完整代码:https://github.com/chengpei/2.4g-51-test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/59638.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用在汽车PKE无钥匙进入系统的高度集成SOC芯片:CSM2433

CSM2433是一款集成2.4GHz频段发射器、125KHz接收器和8位RISC&#xff08;精简指令集&#xff09;MCU的SOC芯片&#xff0c;用在汽车PKE无钥匙进入系统里。 什么是汽车PKE无钥匙进入系统&#xff1f; 无钥匙进入系统具有无钥匙进入并且启动的功能&#xff0c;英文名称是PKE&…

机器学习基础05

目录 1.随机森林 1.1随机森林的介绍 1.2算法原理 1.3API 2.线性回归 2.1回归的含义 2.2线性回归 2.3损失函数 2.4多参数回归 2.5最小二乘法MSE 2.6API 1.随机森林 集成学习的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。 集成…

数据库范式、MySQL 架构、算法与树的深入解析

一、数据库范式 在数据库设计中&#xff0c;范式是一系列规则&#xff0c;用于确保数据的组织和存储具有良好的结构、完整性以及最小化的数据冗余。如果不遵循范式设计&#xff0c;数据可能会以平铺式罗列&#xff0c;仅使用冒号、分号等简单分隔。这种方式存在诸多弊端&#…

SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间

SQL面试题——奔驰SQL面试题 我们的表大致如下 CREATE TABLE signal_log( vin STRING COMMENTvehicle frame id, signal_name STRING COMMENTfunction name, signal_value STRING COMMENT signal value , ts BIGINT COMMENTevent timestamp, dt STRING COMMENTformat yyyy-mm…

Hadoop生态圈框架部署(六)- HBase完全分布式部署

文章目录 前言一、Hbase完全分布式部署&#xff08;手动部署&#xff09;1. 下载Hbase2. 上传安装包3. 解压HBase安装包4. 配置HBase配置文件4.1 修改hbase-env.sh配置文件4.2 修改hbase-site.xml配置文件4.3 修改regionservers配置文件4.4 删除hbase中slf4j-reload4j-1.7.33.j…

YOLOv11改进,YOLOv11添加GnConv递归门控卷积,二次创新C3k2结构

摘要 视觉 Transformer 在多种任务中取得了显著的成功,这得益于基于点积自注意力的新空间建模机制。视觉 Transformer 中的关键因素——即输入自适应、长距离和高阶空间交互——也可以通过卷积框架高效实现。作者提出了递归门控卷积(Recursive Gated Convolution,简称 gnCo…

Queuing 表(buffer表)的优化实践 | OceanBase 性能优化实践

案例问题描述 该案例来自一个金融行业客户的问题&#xff1a;他们发现某个应用对一个数据量相对较小的表&#xff08;仅包含数千条记录&#xff09;访问时&#xff0c;频繁遇到性能下降的情况。为解决此问题&#xff0c;客户向我们求助进行分析。我们发现这张表有频繁的批量插…

CentOS 8 安装 chronyd 服务

操作场景 目前原生 CentOS 8 不支持安装 ntp 服务&#xff0c;因此会发生时间不准的问题&#xff0c;需使用 chronyd 来调整时间服务。CentOS 8以及 TencentOS 3.1及以上版本的实例都使用 chronyd 服务实现时钟同步。本文介绍了如何在 CentOS 8 操作系统的腾讯云服务器上安装并…

AI大模型(二):AI编程实践

一、软件安装 1. 安装 Visual Studio Code VSCode官方下载&#xff1a;Visual Studio Code - Code Editing. Redefined 根据自己的电脑系统选择相应的版本下载 安装完成&#xff01; 2. 安装Tongyi Lingma 打开VSCode&#xff0c;点击左侧菜单栏【extensions】&#xff0c;…

Win10/11 安装使用 Neo4j Community Edition

如果你下载的是 Neo4j Community Edition 的压缩包&#xff0c;意味着你需要手动解压并配置 Neo4j。以下是详细的使用步骤&#xff1a; 0. 下载压缩包 访问Neo4j官网&#xff0c;找到 Community Edition 版本并选择 4.x 或者 5.x 下载&#xff1a;https://neo4j.com/deployme…

使用json配置动态区间及动态执行公式

背景 有时候可能线上一直需要调整公式或者区间以及参数等等&#xff0c;如果使用代码方式&#xff0c;将会变得比较麻烦&#xff0c;可以在redis或者数据库配置一份动态配置&#xff0c;让代码进行解析并执行&#xff0c;可以对公式以及参数等进行动态调节 需求 x 是估值&…

腾讯地图GL JS点标识监听:无dragend事件的经纬度获取方案

引入腾讯地图SDK <!--腾讯地图 API--><script charset"utf-8" src"https://map.qq.com/api/gljs?librariestools&v1.exp&key***"></script>构建地图容器 <div class"layui-card"><div class"layui-car…

Tiktok对接和内容发布申请流程

这段时间在搞AI生成视频&#xff0c;希望用户能一键发布到Tiktok&#xff0c;因此研究了一下Tiktok的开发者申请流程&#xff0c;发现好复杂&#xff0c;同时也发现Tiktok的开发也跟我一样&#xff0c;挺草台班子的 0、流程简述 废话不多说&#xff0c;Tiktok的开发者申请和…

企业生产环境-麒麟V10(ARM架构)操作系统部署kafka高可用集群

前言&#xff1a;Apache Kafka是一个分布式流处理平台&#xff0c;由LinkedIn开发并捐赠给Apache软件基金会。它主要用于构建实时数据流管道和流应用。Kafka具有高吞吐量、可扩展性和容错性的特点&#xff0c;适用于处理大量数据。 以下是Kafka的一些核心概念和特性&#xff1…

xcode-select: error: tool ‘xcodebuild‘ requires Xcode, but active developer

打开 .sh 文件所在的终端窗口&#xff0c;执行终端命令&#xff1a;sh 文件名.sh&#xff0c;出现如下错误&#xff1a; 解决办法&#xff1a;

CC6学习记录

&#x1f338; cc6 cc6和cc1的国外链其实后半条链子是一样的&#xff0c;但是cc6的不局限于jdk的版本和commons-collections的版本。 回忆一下cc1的后半条链子&#xff1a; LazyMap.get()->InvokerTransformer.transform() 这里我们就结合了URLDNS链的思路&#xff0c;在…

嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波

引言&#xff1a;本内容主要用作于学习巩固嵌入式硬件内容知识&#xff0c;用于想提升下述能力&#xff0c;针对学习STM32与DAC0832产生波形以及波形转换&#xff0c;对于硬件的降压和对于前面硬件篇的实际运用&#xff0c;针对仿真的使用&#xff0c;具体如下&#xff1a; 设…

网络安全练习之 ctfshow_web

文章目录 VIP题目限免&#xff08;即&#xff1a;信息泄露题&#xff09;源码泄露前台JS绕过协议头信息泄露robots后台泄露phps源码泄露源码压缩包泄露版本控制泄露源码(git)版本控制泄露源码2(svn)vim临时文件泄露cookie泄露域名txt记录泄露敏感信息公布内部技术文档泄露编辑器…

ReactPress与WordPress:一场内容管理系统的较量

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress WordPress官网&#xff1a;https://wordpress.org/ ReactPress与WordPress&#xff1a;一场内容管理系统的较量 在当今数字化时代&#xff0c;内容管理系统&#xff08;CMS&#xff09;已成为…

IDEA调整警告级别【IntelliJ IDEA 2024.2.0.1】

文章目录 目前现状鼠标悬停&#xff0c;选择配置筛选 > 取消选择OK效果 目前现状 需要把提示改成只要显示error的5个 鼠标悬停&#xff0c;选择配置 筛选 > 取消选择 OK 效果