
开源协议
:CC BY-NC 3.0
(未经作者授权,禁止转载)描述
2.4G无线射频模块
一、工程介绍
1.概述
本工程基于py32f403单片机(开发库类似stm32的Hal库,可直接换成同pin数的stm32()),射频可选用用si24r1/nrf24l01芯片或者xl2400p。板载ch340可串口直接连接PC,或者按图示方式焊接电阻可切换为usb虚拟串口。本项目主要实现点对点通信、点对点透传功能时分复用实现伪双工通信(代码整理中)。
2.基本参数
工作于2.4G频段
基于国产芯片SI24R1,兼容NRF24L01+, 低成本高性能。
主控芯片py32f403C1DT6 硬件性价比极高。
使用usb串口(usb虚拟串口)、6p串口和主机通信
支持对两个或是组网模式下多个模块的参数进行任意单独配置,上电默认透传模式,后续会更新一对多组网。
lcd显示数据包接收状态。
3.射频芯片介绍
> nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型“SchockBurst”模式控制器、功率放大器、晶体振荡器、调制器和解调器。
> XL2400P芯片是一款单片无线收发芯片,工作在2.400至2.483GHz的世界通用ISM频段。该芯片集成了多种功能模块,。1包括射频收发机、频率发生器、晶体振荡器和调制解调器,同时支持一对多组网以及带ACK的通信模式。XL2400P芯片能够在1.7至3.6V的工作电压下稳定运行,并适应-40至+125℃的极端温度范围。其发射输出功率、工作频道和通信数据率均可根据需求进行配置。
二、软件设计
2.1 si24r1/nrf24l01+驱动编写
1.手册说明
SPI时序
> 芯片采用标准的四线SPI接口,实测最高读写速度大于10Mb/S。外部微控制器可以通过SPI接口对芯片进行配置,包括读写功能寄存器、读写FIFO、读芯片状态、清除中断等。
Shutdown 工作模式(掉电模式)
> 在Shutdown 工作模式下,Si24R1所有收发功能模块关闭,芯片停止工作,消耗电
流最小,但所有内部寄存器值和FIFO值保持不变,仍可通过SPI实现对寄存器的读写。
设置CONFIG寄存器的PWR_UP位的值为0,芯片立即返回到Shutdown工作模式。
Standby 工作模式(待机模式)
> 在Standby 工作模式,只有晶体振荡器电路工作,保证了芯片在消耗较少电流的同
时能够快速启动。设置CONFIG寄存器下的PWR_UP位的值为1,芯片待时钟稳定后
进入Standby 模式。芯片的时钟稳定时间一般为1.5~2ms,与晶振的性能有关。当引脚
CE=1 时,芯片将由Standby 模式进入到 Idle-TX 或 RX 模式,当 CE=0 时,芯片将由
Idle-TX、TX 或 RX模式返回到Standby模式。
Idle-TX 工作模式(发送空闲模式)
> 在Idle-TX 工作模式下,晶体振荡器电路及时钟电路工作。相比于Standby模式,
芯片消耗更多的电流。当发送端TX FIFO寄存器为空,并且引脚CE=1时,芯片进入到
Idle-TX 模式。在该模式下,如果有新的数据包被送到TX FIFO中,芯片内部的电路将
立即启动,切换到TX模式将数据包发送。
在Standby 和 Idle-TX 工作模式下,所有内部寄存器值和 FIFO 值保持不变,仍可
通过SPI实现对寄存器的读写。
TX 工作模式
> 当需要发送数据时,需要切换到TX工作模式。芯片进入到TX工作模式的条件为:TX FIFO 中有数据, CONFIG寄存器的PWR_UP位的值为1,PRIM_RX位的值为0,同时要求引脚CE上有一个至少持续10us的高脉冲。Idle-TX模式切换到TX模式的时间为 120us~130us 之间,但不会超过 130us。单包数据发送完成后,如果 CE=1, 则由TX FIFO的状态来决定芯片所处的工作模式,当TX FIFO还有数据,芯片继续保持在TX工作模式,并发送下一包数据;当TX FIFO没有数据,芯片返回Idle-TX模式;如果CE=0,立即返回Standby模式。数据发射完成后,芯片产生数据发射完成中断。
RX 工作模式
> 当需要接收数据时,需要切换到RX工作模式。芯片进入到RX工作模式的条件为:设置寄存器CONFIG的PWR_UP位的值为1,PRIM_RX位的值为1,并且引脚CE=1。芯片由Standby 模式切换到RX模式的时间为120~130us。当接收到数据包的地址与芯片的地址相同,并且CRC检查正确时,数据会自动存入RX FIFO,并产生数据接收中断。芯片最多可以同时存三个有效数据包,当FIFO已满,接收到的数据包被自动丢掉。
代码示例
/*!
* @brief 设置为关断模式
* @param 无
* @return 无
* @note 该模式下,Si24R1所有收发功能模块关闭,芯片停止工作,消耗电流最小
*/
void SI24R1_SetShutdown(void)
{
uint8_t controlreg = SI24R1_Read_Reg(CONFIG);
SI24R1_Write_Reg(CONFIG, controlreg & (~(1 << PWR_UP)));
}
/*!
* @brief 设置为待机模式
* @param 无
* @return 无
* @note 该模式下,只有晶体振荡器电路工作,保证了芯片在消耗较少电流的同时能够快速启动。
*/
void ST24R1_SetStandby(void)
{
uint8_t controlreg = SI24R1_Read_Reg(CONFIG);
SI24R1_Write_Reg(CONFIG, controlreg | (1 << PWR_UP));
}
/*!
* @brief 设置nRF24L01+为TX/RX模式
* @param mode: 模式 (TX/RX)
* @return 无
* @note TX工作模式的条件为:
* TX FIFO 中有数据, CONFIG寄存器的PWR_UP位的值为1,PRIM_RX位的值为0,
* 同时要求引脚CE上有一个至少持续10us的高脉冲。当发送端TX FIFO寄存器为空,
* 并且引脚CE=1时,芯片进入到Idle-TX 模式。在该模式下,如果有新的数据包被
* 送到TX FIFO中,芯片内部的电路将立即启动,切换到TX模式将数据包发送。
* RX工作模式的条件为:
* 设置寄存器CONFIG的PWR_UP位的值为1,PRIM_RX位的值为1,并且引脚CE=1。
*/
void SI24R1_SetMode(SI24R1_MODE mode)
{
uint8_t mask = SI24R1_Read_Reg(CONFIG);
if (mode == TX_MODE)
{
mask &= ~(1 << PRIM_RX);
}
else if (mode == RX_MODE)
{
mask |= (1 << PRIM_RX);
}
SI24R1_Write_Reg(CONFIG, mask);
}
2.芯片通信模式
ACK 模式
> 当用W_TX_PAYLOAD命令对发送端TX FIFO写数据时,将数据打包后,数据包中
包控制字段NO_ACK 标志位复位。接收端接收到一帧有效数据后, 产生RX_DR中断
后,会自动发送一帧ACK信号,发送端接收到ACK信号,则自动清除TX FIFO数据
并产生TX_DS发射中断,表明此次通信成功。
接收端在发送ACK信号时,取接收管道地址作为目标地址来发送ACK信号,所以发
送端需要设置接收管道0地址与自身发送地址相同,以便接收ACK信号。
如果发送端在ARD时间内没有接收到ACK信号,则重新发送上一帧数据。当重发次
数达到最大,仍没有收到确认信号时,发送端产生MAX_RT中断。MAX_RT中断在清
除之前不能进行下一步的数据发送。所有中断通过对状态寄存器进行写操作来清除。
PLOS_CNT 寄存器在每产生一个MAX_RT中断后加1,用来记录当前频段下,丢失的
数据包的数量。ARC_CNT寄存器记录当前数据重发的次数,在发送一包新数据时使其
复位。最大重发次数与ARD时间通过SETUP_RETR 寄存器来进行配置。接收端开启
自动回复ACK信号由EN_AA寄存器来控制。
ACK PAYLOAD通信模式(伪双工)
> 接收端在回复 ACK 信号时,可以同时发送带有负载数据的 ACK 信号
(ACKPAYLOAD)。开启这一功能需要配置 FETURE 寄存器中的 EN_ACK_PAY 位,
并且双方必须开启动态负载长度。
接收端先用 W_ACK_PAYLOAD 对 TX FIFO 写入对应接收数据管道的
ACKPAYLOAD,当这一管道接收到一帧新的有效数据,产生RX_DR中断,并自动回
复ACK,并自动将ACKPAYLOAD其打包,发送给发送端;发送端收到带有负载数据
的ACK信号后,同时产生TX_DS和RX_DR中断。当接收端再次接收到发送端发送的
一包有效数据后,表示发送端已经收到ACKPAYLOAD,清除TX FIFO中数据,同时
产生 RX_DR 与 TX_DS 中断。如果收到的数据为上一包数据的重发,则重新将此
ACKPAYLOAD 打包,并作为ACK信号发送出去。图4-5发送端第一次发送后没有收
到带有ACKPAYLOD的ACK信号,进行重发,接收端再次将此ACKPAYLOAD打包,
接收端收到后,进行下一帧数据发送。
NO ACK模式(快速发送)
> 用 W_TX_PAYLOAD_NOACK 命令对发送方写 TX PAYLOAD 时,数据包中
NO_ACK 标志位置位,发送端发送完一包数据后,立即产生 TX_DS 中断,并且开始
准备发送下一包数据。接收端接收到数据后判断NO_ACK标志置位,且数据有效,则
产生RX_DR 中断,此时一帧数据通信完成,不再回复 ACK 信号。
W_TX_PAYLOAD_NOACK命令通过FETURE寄存器中的EN_DYN_ACK来使能。
3.si24r1.h
驱动接口函数宏定义,修改该宏定义以适配不同引脚或是单片机平台。
uint8_t SPI3_ReadWriteByte(uint8_t data)为spi读写操作函数需要自行实现。
//接口函数
#define L01_CSN_LOW() HAL_GPIO_WritePin(RF_CSN_GPIO_Port, RF_CSN_Pin,GPIO_PIN_RESET) // CSN 置低
#define L01_CSN_HIGH() HAL_GPIO_WritePin(RF_CSN_GPIO_Port, RF_CSN_Pin,GPIO_PIN_SET) // CSN 置高
#define L01_CE_LOW() HAL_GPIO_WritePin(RF_CE_GPIO_Port, RF_CE_Pin,GPIO_PIN_RESET) // CE 置低
#define L01_CE_HIGH() HAL_GPIO_WritePin(RF_CE_GPIO_Port, RF_CE_Pin,GPIO_PIN_SET) // CE 置高
#define GET_L01_IRQ() HAL_GPIO_ReadPin(RF_IRQ_GPIO_Port, RF_IRQ_Pin) // 获取中断引脚状态
#define SPI_ExchangeByte(data) SPI3_ReadWriteByte(data) //spi读写操作
#define RF_Delay(Delay) HAL_Delay(Delay)//延迟ms
寄存器定义
/****************************************************************************************************************************/
#define MODEL_RX 1 //普通接收
#define MODEL_TX 2 //普通发射
#define MODEL_RX2 3 //接收模式2,用于双向传输
#define MODEL_TX2 4 //发送模式2,用于双向传输
#define TX_ADR_WIDTH 5 //5字节的地址宽度
#define RX_ADR_WIDTH 5 //5字节的地址宽度
#define TX_PLOAD_WIDTH 32 //32字节的用户数据宽度
#define RX_PLOAD_WIDTH 32 //32字节的用户数据宽度
/** SI24R1定义 */
/*************************************************寄存器操作命令**************************************************************/
#define SPI_READ_REG 0x00 //读配置寄存器,低5位为寄存器地址
#define SPI_WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址
#define R_RX_PL_WID 0x60 //读取收到的数据字节数
#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节
#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字节
#define WR_TX_PLOAD_NACK 0xB0 //写TX入不带 ACK 的发送有效载荷
#define FLUSH_TX 0xE1 //清除TX FIFO寄存器,发射模式下使用
#define FLUSH_RX 0xE2 //清除RX FIFO寄存器,接收模式下使用
#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送
#define W_ACK_PLOAD 0xA8 //接收方,将数据通过ACK形式发送,最多允许3帧存放在FIFO中
#define NOP 0xFF //空操作,可以用来读状态寄存器
/*************************************************寄存器地址**************************************************************/
#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 //设置地址宽度(所有数据通道) bit0~1: 00,3字节 01,4字节, 02,5字节
#define SETUP_RETR 0x04 //建立自动重发;bit0~3:自动重发计数器;bit4~7:自动重发延时 250*x+86us
#define RF_CH 0x05 //RF通道,bit0~6工作通道频率
#define RF_SETUP 0x06 //RF寄存器,bit3:传输速率( 0:1M 1:2M);bit1~2:发射功率;bit0:噪声放大器增益
//状态
#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit1~3:接收数据通道号(最大: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,不循环
#define DYNPD 0x1C //动态数据包长度寄存器;bit0~5:对应通道0~5的动态数据包长度使能
#define FEATRUE 0x1D //动态特征寄存器;bit1:使能ACK负载(带负载数据的ACK包);bit1:使能动态负载长度
/*************************************************位定义**************************************************************/
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW_RERSERVED 0x0
#define AW_3BYTES 0x1
#define AW_4BYTES 0x2
#define AW_5BYTES 0x3
#define ARD_250US (0x00<<4)
#define ARD_500US (0x01<<4)
#define ARD_750US (0x02<<4)
#define ARD_1000US (0x03<<4)
#define ARD_2000US (0x07<<4)
#define ARD_4000US (0x0F<<4)
#define ARC_DISABLE 0x00
#define ARC_15 0x0F
#define CONT_WAVE 7
#define RF_DR_LOW 5
#define PLL_LOCK 4
#define RF_DR_HIGH 3
//bit2-bit1:
#define PWR_F12DB (0x00<<1)
#define PWR_F6DB (0x01<<1)
#define PWR_F4DB (0x02<<1)
#define PWR_0DB (0x03<<1)
#define PWR_1DB (0x04<<1)
#define PWR_3DB (0x05<<1)
#define PWR_4DB (0x06<<1)
#define PWR_7DB (0x07<<1)
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
//for bit3-bit1,
#define TX_FULL_0 0
#define RPD 0
#define TX_REUSE 6
#define TX_FULL_1 5
#define TX_EMPTY 4
//bit3-bit2, reserved, only '00'
#define RX_FULL 1
#define RX_EMPTY 0
#define DPL_P5 5
#define DPL_P4 4
#define DPL_P3 3
#define DPL_P2 2
#define DPL_P1 1
#define DPL_P0 0
#define EN_DPL 2
#define EN_ACK_PAY 1
#define EN_DYN_ACK 0
#define IRQ_ALL ( (1<
设计图

BOM


评论