NRF24L01模块STM32通信-通信初始化
目录
前言
一、IO口初始化
二、模拟SPI的基础代码
1.一些代码的宏定义
2.起始信号
3.CS,SCK,MOSI操作
4.MISO,IRQ操作
三.中间层代码
1.字节的输入和读取
2.写操作
3.读操作
四.应用层代码
1.24L01的检测
2.在main函数进行简单验证
3.24L01宏定义的代码
总结
前言
环境:
芯片:STM32F103C8T6
Keil:V5.24.2.0
模块:NRF24L01
一、IO口初始化
根据:NRF24L01模块STM32通信-调试前言-CSDN博客
需要初始6个IO:4个输出,2个输入
我初始对应的IO口如下;
//输出
CSN ->PA3
CE ->PA4
MOSI ->PA7
SCK ->PA5
//输入
IRQ ->PB1
MISO ->PA6
IO口初始化,包含了OLED和其他的初始化代码.
void Gpio_Init(void)
{
/* 输出
CSN ->PA3//
CE ->PA4
MOSI ->PA7
SCK ->PA5 输入
IRQ ->PB1
MISO ->PA6
*/
//outputRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);//inputGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);}
二、模拟SPI的基础代码
1.一些代码的宏定义
#define SPI_CS_PROT GPIOA //CS接线引脚通道, CSN
#define SPI_CS_PIN GPIO_Pin_3#define SPI_DO_PROT GPIOA //D0接线引脚通道, MOSI
#define SPI_DO_PIN GPIO_Pin_7#define SPI_SLK_PROT GPIOA //CL接线引脚通道, SCK
#define SPI_SLK_PIN GPIO_Pin_5#define SPI_DI_PROT GPIOA //DI接线引脚通道, MISO
#define SPI_DI_PIN GPIO_Pin_6#define SPI_IRQ_PROT GPIOB //DI接线引脚通道, MISO
#define SPI_IRQ_PIN GPIO_Pin_1#define MYSPI_W_CS(x) GPIO_WriteBit(SPI_CS_PROT,SPI_CS_PIN,(BitAction)(x))//对CS线进行操作
#define MYSPI_W_DI(x) GPIO_WriteBit(SPI_DI_PROT,SPI_DI_PIN,(BitAction)(x))//对DI线进行操作
#define MYSPI_W_DO(x) GPIO_WriteBit(SPI_DO_PROT,SPI_DO_PIN,(BitAction)(x))//对DO线进行操作
#define MYSPI_W_SLK(x) GPIO_WriteBit(SPI_SLK_PROT,SPI_SLK_PIN,(BitAction)(x))//对SLK线进行操作
#define NRF24L01_CE(x) GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(x))//对CE线进行操作
2.起始信号
void MySPI_Start(void)
{MYSPI_W_CS(0); //拉低为开始信号
}void MySPI_Stop(void)
{MYSPI_W_CS(1); //拉高为结束信号
}
3.CS,SCK,MOSI操作
void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, SPI_CS_PIN, (BitAction)BitValue);
}void MySPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, SPI_SLK_PIN, (BitAction)BitValue);
}void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, SPI_DO_PIN, (BitAction)BitValue);
}
4.MISO,IRQ操作
uint8_t MySPI_Read_MISO(void)
{return GPIO_ReadInputDataBit(SPI_DI_PROT, SPI_DI_PIN);
}uint8_t MySPI_Read_IRQ(void)
{return GPIO_ReadInputDataBit(SPI_IRQ_PROT, SPI_IRQ_PIN);
}
三.中间层代码
1.字节的输入和读取
uint8_t MySPI_SwapByte(uint8_t ByteSend) //字节读取和交换
{uint8_t i,ByteReceive = 0x00;for(i = 0;i < 8;i ++){MySPI_W_MOSI(ByteSend & (0x80 >> i));MySPI_W_SCK(1);if (MySPI_Read_MISO() == 1){ByteReceive |= (0x80 >> i);}MySPI_W_SCK(0);}return ByteReceive;
}
关于这段代码更详细的解说可以观看江科大的视频SPI部分.
2.写操作
uint8_t NRF24l01_write_buf(uint8_t reg, uint8_t *pbuf, uint8_t len)
{uint8_t status, i;MySPI_Start(); /* 使能SPI传输 */status = MySPI_SwapByte(reg); /* 发送寄存器值(位置),并读取状态值 */for (i = 0; i < len; i++){MySPI_SwapByte(*pbuf++); /* 写入数据 */}MySPI_Stop(); /* 关闭SPI传输 */ return status; /* 返回读到的状态值 */}
3.读操作
uint8_t NRF24l01_read_buf(uint8_t reg, uint8_t *pbuf, uint8_t len)
{uint8_t status, i; MySPI_Start(); /* 使能SPI传输 */status = MySPI_SwapByte(reg); /* 发送寄存器值(位置),并读取状态值 */for (i = 0; i < len; i++){pbuf[i] = MySPI_SwapByte(0X55); /* 读出数据 */ } return status; /* 返回读到的状态值 */
}
四.应用层代码
1.24L01的检测
/*** @brief 检测24L01是否存在* @param 无* @retval 0, 成功; 1, 失败;*/
uint8_t NRF24l01_check(void)
{uint8_t buf[5] = {0XA5, 0XA5, 0XA5, 0XA5, 0XA5};uint8_t i;NRF24l01_write_buf(NRF_WRITE_REG + TX_ADDR, buf, 5); /* 写入5个字节的地址. */NRF24l01_read_buf(TX_ADDR, buf, 5); /* 读出写入的地址 */for (i = 0; i < 5; i++){if (buf[i] != 0XA5) break;}if (i != 5) return 1; /* 检测24L01错误 */return 0; /* 检测到24L01 */
}
关于其中的一些宏定义,代码放在本文末.
2.在main函数进行简单验证
void MY24L01_Init(void)//对模块和通信线的前期操作
{NRF24L01_CE(0);
MYSPI_W_CS(1);
MYSPI_W_SLK(0);}while(1)
{while (NRF24l01_check()) /* 检查NRF24L01是否在线 */{OLED_ShowString(16, 18, "NRF24l01 NGNGNG", OLED_6X8);OLED_Update();}OLED_ShowString(32, 18, "GOOD", OLED_6X8);OLED_Update();
}
可以使用OLED进行显示,当然因为结果只有0或1,所以也可以采用其他方式进行验证,如LED的亮灭
如果代码正确则可以进行后面的代码书写.
3.24L01宏定义的代码
/******************************************************************************************/
/* NRF24L01寄存器操作命令 */
#define NRF_READ_REG 0x00 /* 读配置寄存器,低5位为寄存器地址 */
#define NRF_WRITE_REG 0x20 /* 写配置寄存器,低5位为寄存器地址 */
#define RD_RX_PLOAD 0x61 /* 读RX有效数据,1~32字节 */
#define WR_TX_PLOAD 0xA0 /* 写TX有效数据,1~32字节 */
#define FLUSH_TX 0xE1 /* 清除TX FIFO寄存器.发射模式下用 */
#define FLUSH_RX 0xE2 /* 清除RX FIFO寄存器.接收模式下用 */
#define REUSE_TX_PL 0xE3 /* 重新使用上一包数据,CE为高,数据包被不断发送. */
#define NOP 0xFF /* 空操作,可以用来读状态寄存器 *//* SPI(NRF24L01)寄存器地址 */
#define CONFIG 0x00 /* 配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能; *//* bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能 */
#define EN_AA 0x01 /* 使能自动应答功能 bit0~5,对应通道0~5 */
#define EN_RXADDR 0x02 /* 接收地址允许,bit0~5,对应通道0~5 */
#define SETUP_AW 0x03 /* 设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节; */
#define SETUP_RETR 0x04 /* 建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us */
#define RF_CH 0x05 /* RF通道,bit6:0,工作通道频率; */
#define RF_SETUP 0x06 /* RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益 */
#define STATUS 0x07 /* 状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发 *//* bit5:数据发送完成中断;bit6:接收数据中断; */
#define MAX_TX 0x10 /* 达到最大发送次数中断 */
#define TX_OK 0x20 /* TX发送完成中断 */
#define RX_OK 0x40 /* 接收到数据中断 */#define OBSERVE_TX 0x08 /* 发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器 */
#define CD 0x09 /* 载波检测寄存器,bit0,载波检测; */
#define RX_ADDR_P0 0x0A /* 数据通道0接收地址,最大长度5个字节,低字节在前 */
#define RX_ADDR_P1 0x0B /* 数据通道1接收地址,最大长度5个字节,低字节在前 */
#define RX_ADDR_P2 0x0C /* 数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; */
#define RX_ADDR_P3 0x0D /* 数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; */
#define RX_ADDR_P4 0x0E /* 数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; */
#define RX_ADDR_P5 0x0F /* 数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; */
#define TX_ADDR 0x10 /* 发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等 */
#define RX_PW_P0 0x11 /* 接收数据通道0有效数据宽度(1~32字节),设置为0则非法 */
#define RX_PW_P1 0x12 /* 接收数据通道1有效数据宽度(1~32字节),设置为0则非法 */
#define RX_PW_P2 0x13 /* 接收数据通道2有效数据宽度(1~32字节),设置为0则非法 */
#define RX_PW_P3 0x14 /* 接收数据通道3有效数据宽度(1~32字节),设置为0则非法 */
#define RX_PW_P4 0x15 /* 接收数据通道4有效数据宽度(1~32字节),设置为0则非法 */
#define RX_PW_P5 0x16 /* 接收数据通道5有效数据宽度(1~32字节),设置为0则非法 */
#define NRF_FIFO_STATUS 0x17 /* FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留 *//* bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环; *//******************************************************************************************/
总结
本文代码并未涉及很多的交互动作,只是验证基础代码和IO口的连接正确.操作相对简单,方便及时对代码进行验证,查缺补漏,方便后面代码的调试
相关文章:
NRF24L01模块STM32通信-通信初始化
目录 前言 一、IO口初始化 二、模拟SPI的基础代码 1.一些代码的宏定义 2.起始信号 3.CS,SCK,MOSI操作 4.MISO,IRQ操作 三.中间层代码 1.字节的输入和读取 2.写操作 3.读操作 四.应用层代码 1.24L01的检测 2.在main函数进行简单验证 3.24L01宏定义的代码 总结 前…...

高比例压缩:Linux 中的压缩命令与技巧
文章目录 高比例压缩:Linux 中的压缩命令与技巧1. 压缩格式的选择2. gzip 命令示例:压缩文件示例:解压文件 3. bzip2 命令示例:压缩文件示例:解压文件 4. xz 命令示例:压缩文件示例:解压文件 5.…...

LabVIEW软件Bug的定义与修改
在LabVIEW软件开发过程中,bug(程序错误或缺陷)指的是程序中导致不符合预期行为的任何问题。Bug可能是由于编码错误、逻辑漏洞、硬件兼容性问题、系统资源限制等因素引起的。它可能会导致程序崩溃、功能无法正常执行或输出结果不符合预期。理解…...

基于Springboot + vue实现的办公用品管理系统
🥂(❁◡❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞 💖📕🎉🔥 支持我:点赞👍收藏⭐️留言📝欢迎留言讨论 🔥🔥&…...

B+树的原理及实现
文章目录 B树的原理及实现一、引言二、B树的特性1、结构特点2、节点类型3、阶数 三、B树的Java实现1、节点实现2、B树操作2.1、搜索2.2、插入2.3、删除2.4、遍历 3、B树的Java实现示例 四、总结 B树的原理及实现 一、引言 B树是一种基于B树的树形数据结构,它在数据…...

(四)结合代码初步理解帧缓存(Frame Buffer)概念
帧缓存(Framebuffer)是图形渲染管线中的一个非常重要的概念,它用于存储渲染过程中产生的像素数据,并最终输出到显示器上。简单来说,帧缓存就是计算机图形中的“临时画布”,它储存渲染操作生成的图像数据&am…...
python注意事项:range遍历越索引现象、列表边遍历边修改出现的问题
文章目录 前言一、range遍历越索引现象QS1:遍历range(2,2)会发生什么?不会报错,但是也不会遍历到任何内容QS1:遍历range(3,2)会发生什么?不会报错,但是也不会遍历到任何内容 二、列表边遍历边修改注意事项(Java的List系…...
【C++】模板与泛型编程(三):重载与模板
16.3 重载与模板 函数模板可以被另一个模板或一个普通分模板函数重载。与往常一样,名字相同的函数必须具有不同数量或类型的参数(这样才可以完成重载)。 如果设计模板,则函数的匹配规则与普通函数的重载有所不同,具体…...

JavaScript字符串拓展:实用方法与示例全解析
一、引言:为什么要学习 JS 字符串拓展 在前端开发的世界里,JavaScript 如同基石般支撑着网页的交互与动态呈现。而字符串作为我们日常操作中最频繁接触的数据类型之一,其原生方法在面对复杂多变的业务需求时,有时难免显得捉襟见肘…...

基于html5实现音乐录音播放动画源码
源码介绍 基于html5实现音乐录音播放动画源码是一款类似Shazam的UI,点击按钮后,会变成为一个监听按钮。旁边会有音符飞入这个监听按钮,最后转换成一个音乐播放器。 效果预览 源码获取 基于html5实现音乐录音播放动画源码...

初学stm32 --- ADC模拟/数字转换器工作原理
目录 常见的ADC类型 并联比较型工作示意图 逐次逼近型工作示意图 ADC的特性参数 STM32各系列ADC的主要特性 ADC框图简介 参考电压/模拟部分电压 输入通道( F1为例) 转换序列(F1为例) 规则组和注入组执行优先级对比 规则…...
导航技术的分类
导航技术可以根据不同的分类标准进行划分,以下是从不同角度对导航技术的分类: 一、按导航信息获取原理分类 无线电导航:利用无线电波的传播特性来测定运动体的位置、速度等导航参数。常见的无线电导航系统包括罗兰-C、奥米加、台卡等。卫星…...
C++语言的函数实现
C语言中的函数实现详解 C是一种强大的编程语言,广泛应用于系统软件、游戏开发、实时物理模拟等多个领域。在C中,函数是组织和重用代码的重要工具。本文将深入探讨C中的函数实现,包括函数的定义、调用、重载、递归、作用域、内联函数和模板函…...

每日一题-两个链表的第一个公共结点
文章目录 两个链表的第一个公共结点问题描述示例说明示例 1示例 2 方法及实现方法描述代码实现 复杂度分析示例运行过程示例 1示例 2 总结备注 两个链表的第一个公共结点 问题描述 给定两个无环的单向链表,找到它们的第一个公共节点。如果没有公共节点,…...

细说STM32F407单片机以轮询方式读写外部SRAM的方法
目录 一、实例的功能 二、工程配置 1、KEYLED 2、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator 3、FSMC (1) 模式设置 (2) Bank 1子区3参数设置 1) NOR/PSRAM control组,子区控制参数 2) NOR/PSRAM timi…...

【3】安装cyclictest和iperf
cyclictest 安装比较简单,我是直接使用命令行: apt-get install rt-tests 随后,运行 sudo cyclictest 但是这个程序会一直运行,直到你手动中断程序,而且每秒生成一行输出也很烦人,所以可以选择把结果…...
C语言将点分十进制的IP字符串转成4个整数
最近在做lldp的snmp返回值时需要做这样的转换处理:C语言将点分十进制的IP字符串转成4个整数。 这里用两种方式: sscanf格式化处理用 inet_aton函数将ip字符串转成32位的整形,然后再根据bit转成对应的4个整数。 man命令可以确认下sscanf和i…...
go语言学习 笔记 1(变量,语法,数据类型)
1,包管理 一个文件夹可以称为一个包 在一个包里面可以创建多个文件 包中可以创建包 同一个包内的同一级的包的名字要相同 如:包a中的包b.包b中的包得是同一个package,a中和包b同级的包名字也得是一个名字 必须要有一个main包,入口,就像是c必须有一个main函数 如果没有mai…...

无网络时自动切换备用网络环境
目录 背景目标为什么需要做自动网络切换网络切换手段 网络环境实现思路和代码部署脚本开机自动执行附录连接两个网络时的路由问题 背景 目标 学校实验室有两个网络环境,我电脑使用网线连接稳定但低速的网络A,使用WiFi连接高速但不稳定的网络B。因此&am…...

电脑32位和64位之区别(Difference between 32-Bit and 64 Bit Computers)
电脑32位和64位之区别 很多小伙伴还不知道电脑32位和64位是什么意思,今天小编就来普及一下。 32位和64位是指电脑处理器(CPU)和操作系统的架构,决定了电脑如何处理数据、存储信息、运行程序等。 32位和64位是指电脑系统中每个处…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
Windows 下端口占用排查与释放全攻略
Windows 下端口占用排查与释放全攻略 在开发和运维过程中,经常会遇到端口被占用的问题(如 8080、3306 等常用端口)。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口,帮助你高效解决此类问题。 一、准…...

react更新页面数据,操作页面,双向数据绑定
// 路由不是组件的直接跳转use client,useEffect,useRouter,需3个结合, use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...

在MobaXterm 打开图形工具firefox
目录 1.安装 X 服务器软件 2.服务器端配置 3.客户端配置 4.安装并打开 Firefox 1.安装 X 服务器软件 Centos系统 # CentOS/RHEL 7 及之前(YUM) sudo yum install xorg-x11-server-Xorg xorg-x11-xinit xorg-x11-utils mesa-libEGL mesa-libGL mesa-…...
Ansible+Zabbix-agent2快速实现对多主机监控
ansible Ansible 是一款开源的自动化工具,用于配置管理(Configuration Management)、应用部署(Application Deployment)、任务自动化(Task Automation)和编排(Orchestration…...