news 2026/1/14 14:01:28

STM32F103C8T6 + SI24R1实现2.4G通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103C8T6 + SI24R1实现2.4G通信

原理图:

SPI时序

可以看的出来,SCK空闲时低电平,第一个跳变采样,高位先行,8Bit,HAL库可以这样配置

宏定义:

#define MY_RF_CH 69 #define RX_MODE 0 #define TX_MODE 1 #define SI24R1_CSN_LOW HAL_GPIO_WritePin(SI24R1_CSN_GPIO_Port, SI24R1_CSN_Pin, GPIO_PIN_RESET) #define SI24R1_CSN_HIGH HAL_GPIO_WritePin(SI24R1_CSN_GPIO_Port, SI24R1_CSN_Pin, GPIO_PIN_SET) #define SI24R1_CE_LOW HAL_GPIO_WritePin(SI24R1_CE_GPIO_Port, SI24R1_CE_Pin, GPIO_PIN_RESET) #define SI24R1_CE_HIGH HAL_GPIO_WritePin(SI24R1_CE_GPIO_Port, SI24R1_CE_Pin, GPIO_PIN_SET) // SI24R1 PIN DEFINITION #define MOSI P13 // Master Out, Slave In pin (output) #define MISO P10 // Master In, Slave Out pin (input) #define SCK P12 // Serial Clock pin, (output) #define CSN P15 // Slave Select pin, (output to CSN) #define CE P14 // Chip Enable pin signal (output) #define IRQ P11 // Interrupt signal, from nRF24L01 (input) #define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 #define TX_PLOAD_WIDTH 17 // 数据通道有效数据宽度 //********************************************************************************************************************// // SPI(SI24R1) commands #define SI24R1_READ_REG 0x00 // Define read command to register #define SI24R1_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(SI24R1) 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 RSSI 0x09 // 'Received Signal Strength Indecator' 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 //********************************************************************************************************************// // STATUS Register #define RX_DR 0x40 /**/ #define TX_DS 0x20 #define MAX_RT 0x10 //********************************************************************************************************************// // FUNCTION's PROTOTYPES // //********************************************************************************************************************// // SI24R1 API Functions void Int_SI24R1_Init(uint8_t mode); // SI24R1 Pin Init uint8_t Int_SI24R1_Write_Reg(uint8_t reg, uint8_t value); uint8_t Int_SI24R1_Write_Buf(uint8_t reg, const uint8_t *pBuf, uint8_t bytes); uint8_t Int_SI24R1_Read_Reg(uint8_t reg); uint8_t Int_SI24R1_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t bytes); void Int_SI24R1_RX_Mode(void); void Int_SI24R1_TX_Mode(void); uint8_t Int_SI24R1_RxPacket(uint8_t *rxbuf); uint8_t Int_SI24R1_TxPacket(uint8_t *txbuf);

读写寄存器:

static uint8_t SPI_RW(uint8_t byte) { uint8_t rx_byte = 0; HAL_SPI_TransmitReceive(&hspi1, &byte, &rx_byte, 1, UINT32_MAX); return rx_byte; } /******************************************************** 函数功能:写寄存器的值(单字节) 入口参数:reg:寄存器映射地址(格式:SI24R1_WRITE_REG|reg) value:寄存器的值 返回 值:状态寄存器的值 *********************************************************/ uint8_t Int_SI24R1_Write_Reg(uint8_t reg, uint8_t value) { uint8_t status; SI24R1_CSN_LOW; status = SPI_RW(reg); SPI_RW(value); SI24R1_CSN_HIGH; return (status); } /******************************************************** 函数功能:写寄存器的值(多字节) 入口参数:reg:寄存器映射地址(格式:SI24R1_WRITE_REG|reg) pBuf:写数据首地址 bytes:写数据字节数 返回 值:状态寄存器的值 *********************************************************/ uint8_t Int_SI24R1_Write_Buf(uint8_t reg, const uint8_t *pBuf, uint8_t bytes) { uint8_t status, byte_ctr; SI24R1_CSN_LOW; status = SPI_RW(reg); for (byte_ctr = 0; byte_ctr < bytes; byte_ctr++) SPI_RW(pBuf[byte_ctr]); SI24R1_CSN_HIGH; return (status); } /******************************************************** 函数功能:读取寄存器的值(单字节) 入口参数:reg:寄存器映射地址(格式:SI24R1_READ_REG|reg) 返回 值:寄存器值 *********************************************************/ uint8_t Int_SI24R1_Read_Reg(uint8_t reg) { uint8_t value; SI24R1_CSN_LOW; SPI_RW(reg); value = SPI_RW(0); SI24R1_CSN_HIGH; return (value); } /******************************************************** 函数功能:读取寄存器的值(多字节) 入口参数:reg:寄存器映射地址(SI24R1_READ_REG|reg) pBuf:接收缓冲区的首地址 bytes:读取字节数 返回 值:状态寄存器的值 *********************************************************/ uint8_t Int_SI24R1_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t bytes) { uint8_t status, byte_ctr; SI24R1_CSN_LOW; status = SPI_RW(reg); for (byte_ctr = 0; byte_ctr < bytes; byte_ctr++) pBuf[byte_ctr] = SPI_RW(0); // 读取数据,低字节在前 SI24R1_CSN_HIGH; return (status); }

SI24R1的SPI通信前三位是固定的,读是000,写是001,后五位是对应寄存器地址,所以写命令可以用0x20+寄存器地址进行

SI24R1接收模式初始化:

uint8_t TX_ADDRESS[TX_ADR_WIDTH] = {0x0A, 0x01, 0x07, 0x0E, 0x01}; // 定义一个静态发送地址

这里的静态地址,需要接收端和发送端相同

void Int_SI24R1_RX_Mode(void) { SI24R1_CE_LOW; Int_SI24R1_Write_Buf(SI24R1_WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_CH, MY_RF_CH); // 选择射频通道(信道)69 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_SETUP, 0x0f); // 数据传输率2Mbps,发射功率7dBm Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + STATUS, 0xff); // 清除所有的中断标志位 Int_SI24R1_Write_Reg(FLUSH_RX, 0xff); // 为了解决硬件BUG SI24R1_CE_HIGH; // 拉高CE启动接收设备 }

SI24R1发送模式初始化:

void Int_SI24R1_TX_Mode(void) { SI24R1_CE_LOW; Int_SI24R1_Write_Buf(SI24R1_WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址 Int_SI24R1_Write_Buf(SI24R1_WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_CH, MY_RF_CH); // 选择射频通道69 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_SETUP, 0x0f); // 数据传输率2Mbps,发射功率7dBm Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 // SI24R1_CE_HIGH; }

SI24R1初始化:

void Int_SI24R1_Init(uint8_t mode) { // 检查有没有上电成功(启动) while (1) { Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_CH, MY_RF_CH); uint8_t res = Int_SI24R1_Read_Reg(RF_CH); if (res == MY_RF_CH) { break; } } if (mode == RX_MODE) { Int_SI24R1_RX_Mode(); } else if (mode == TX_MODE) { Int_SI24R1_TX_Mode(); } }

先读取状态寄存器判断是否启动,通过传参配置SI24R1模式

读取接受数据:

/******************************************************** 函数功能:读取接收数据 入口参数:rxbuf:接收数据存放首地址 返回 值:0:接收到数据 1:没有接收到数据 *********************************************************/ uint8_t Int_SI24R1_RxPacket(uint8_t *rxbuf) { uint8_t state; state = Int_SI24R1_Read_Reg(STATUS); // 读取状态寄存器的值 Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + STATUS, state); // 清除RX_DR中断标志 if (state & RX_DR) // 接收到数据 { Int_SI24R1_Read_Buf(RD_RX_PLOAD, rxbuf, TX_PLOAD_WIDTH); // 读取数据 Int_SI24R1_Write_Reg(FLUSH_RX, 0xff); // 清除RX FIFO寄存器 return 0; } return 1; // 没收到任何数据 }

发送数据包:

/******************************************************** 函数功能:发送一个数据包 入口参数:txbuf:要发送的数据 返回 值:0x10:达到最大重发次数,发送失败 0x20:发送成功 0xff:发送失败 *********************************************************/ uint8_t Int_SI24R1_TxPacket(uint8_t *txbuf) { uint8_t state; SI24R1_CE_LOW; // CE拉低,使能SI24R1配置 Int_SI24R1_Write_Buf(WR_TX_PLOAD, txbuf, TX_PLOAD_WIDTH); // 写数据到TX FIFO,32个字节 SI24R1_CE_HIGH; // CE置高,使能发送 while (1) { // 读取状态寄存器的值 state = Int_SI24R1_Read_Reg(STATUS); Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + STATUS, state); // 清除TX_DS或MAX_RT中断标志 if (state & MAX_RT) // 达到最大重发次数 { Int_SI24R1_Write_Reg(FLUSH_TX, 0xff); // 清除TX FIFO寄存器 return MAX_RT; } if (state & TX_DS) // 发送完成 { return TX_DS; } }; // 等待发送完成 }

发送端配置:

uint8_t absda[17] = "HELLO WORLD!!!!!"; while (1) { Int_SI24R1_TxPacket(absda); }

接收端配置:

uint8_t rx_buf[32]; while(1){ uint8_t res = Int_SI24R1_RxPacket(rx_buf); if (res == 0){ printf("Comm_Task: %s\n", rx_buf); } }

最终效果:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/14 6:16:17

14、充分利用语言的完整工具集

充分利用语言的完整工具集 在配置管理中,我们常常需要高效地管理和分配资源。Puppet 提供了一系列强大的功能,让我们可以更灵活地处理各种资源。下面将详细介绍 Puppet 中的资源标签、资源导出与导入、资源参数覆盖以及资源默认值等重要特性。 资源标签的使用 Puppet 会隐…

作者头像 李华
网站建设 2025/12/14 0:56:13

AI算力:驱动智能时代多元计算与高效调度的基础

各行各业正被人工智能发展浪潮以前所未有的力道进行重塑&#xff0c;而且支撑其运作的底层基础是算力。换种通俗易懂的说法&#xff0c;AI算力是指用来执行人工智能算法&#xff0c;对海量数据予以处理以及解析所需要的计算能力。它不是一项简单的硬件指标&#xff0c;而是包含…

作者头像 李华
网站建设 2025/12/14 0:56:12

AI知识库的构建:从数据采集、处理到高效检索的全流程解析

AI知识库的搭建以及运用属于一项具备系统性的工程项目&#xff0c;它的关键之处在于怎样以高效且精准地把领域方面的知识给予人工智能系统&#xff0c;从而让其拥有专业领域范畴内的认知以及推理能力。这个进程一般被称作“知识库投喂”或者“知识灌注”&#xff0c;它并非仅仅…

作者头像 李华
网站建设 2026/1/12 0:08:26

Git工作流程指南: 基础 Git 操作

基础 Git 操作 仓库初始化 # 创建新的仓库 git init# 克隆已经存在的仓库 git clone <repository_URL>文件操作 # 将文件添加到暂存区&#xff08;Staging Area&#xff09; git add <file_name> # 添加单个文件 git add . …

作者头像 李华
网站建设 2025/12/14 0:51:58

Modelsim联合高云ip仿真流程

一、改变工作器件库打开modelsim&#xff0c;调整工作器件库&#xff1a;modelsim --> File --> Change Directory --> 选择modelsim的安装目录C:\modeltech64_10.7&#xff08;我装在C盘&#xff09;&#xff0c;点击选择文件夹&#xff0c;如下图。二、创建libirary…

作者头像 李华
网站建设 2025/12/14 0:51:26

69.学习复盘-21天核心知识点梳理与记忆技巧-附思维导图

69 学习复盘:21 天核心知识点梳理与记忆技巧 你好,欢迎来到第 69 讲,也是我们整个课程的倒数第三讲。 在过去的 20 多天里,我们一起经历了一段信息量巨大、充满挑战但也收获满满的 DDD 学习之旅。我们从最基础的概念,一路走到了复杂的企业级案例和面试技巧。 在即将结束…

作者头像 李华