Featured image of post 2.4G 无线通信

2.4G 无线通信

无线通讯

做通信时,可以去**安信可**的官网,它整理的很全


模块类型

  • WiFi

    • 速率高 高功耗
    • 可以使用2.4G 5G频段
    • 频率越高,波长越短 速度越快,穿透性差
  • 蓝牙

    • 经典蓝牙

    • BLE 低功耗蓝牙

    • 频段2.4G

    • 优点:连接—-匹配流完整

  • LoRa

    • 广域
    • 常用频段 500MHz
    • 范围广 穿透强
  • NB-LOT

    • 物联网模块
    • 速度慢 功耗低
  • 2.4G

    • 裸芯片 高性价比

选型

image-20260417013912826

采用的通信方式为SPI通信,这里复习SPI的知识,看之前的博客

通信协议总结_sbi协议-CSDN博客

原理图

image-20260417014551631

image-20260417011252534

1
2
3
4
5
CE		=>			PA11		CE也就是使能
CSN		=>			PB12		CSN是片选
SCK		=>			PB13		时钟
MOSI	=>			PB15		主发从收
MISO	=>			PB14		主收从发

image-20260417015604318

这里的通信芯片实际是使用SI24R1

中文规格书

芯片手册

以上是对应的数据手册

双端通信的要求:

  • 一般是使用相同的驱动文件
  • 选择相同的频道 0-125对应 2400-2525MHz
  • 空中速率相同 有250kbps 1Mbps 2Mbps
  • 地址宽度和地址内容相同、数据宽度相同

程序

首先配置

image-20260417015722253

image-20260417015826196

通信也是可以先看官方的DEMO

可以根据官方的程序进行修改

最重要的就是通过SPI读写一个字节的程序

使用HAL库的SPI 同步收发函数

发一个 → 收一个

1
2
3
4
5
6
static uint8_t SPI_RW(uint8_t byte)
{
    uint8_t rx_data;    // 用于存储接收数据的变量
		HAL_SPI_TransmitReceive(&hspi2, &byte, &rx_data, 1, 1000);
    return rx_data;
}

再就是往寄存器写数据、读数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/********************************************************
* 写寄存器的值
* 参数说明:
*   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: 要写入寄存器的数据缓冲区
*   size: 要写入的字节数
* 返回值:寄存器的状态
*********************************************************/
uint8_t Int_SI24R1_Write_Buf(uint8_t reg, const uint8_t *pBuf, uint8_t size)
{
  uint8_t status,byte_ctr;

  CSN_LOW;                                  			
  status = SPI_RW(reg);                          
  for(byte_ctr=0; byte_ctr<size; byte_ctr++){
  SPI_RW(*pBuf++);
  }     

  CSN_HIGH;                                      	

  return(status);       
}							  					   


/********************************************************
* 读寄存器的值 单字节
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_READ_REG + reg
* 返回值:寄存器的值
*********************************************************/
uint8_t Int_SI24R1_Read_Reg(uint8_t reg)
{
 	uint8_t value;

	CSN_LOW;    
	SPI_RW(reg);			
	value = SPI_RW(0);
	CSN_HIGH;              

	return(value);
}


/********************************************************
* 读寄存器的值 (多字节)
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_READ_REG + reg
*   pBuf: 用于存储读取数据的缓冲区
*   size: 要读取的字节数
* 返回值:寄存器的状态
*********************************************************/
uint8_t Int_SI24R1_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t size)
{
 	uint8_t status,byte_ctr;

	CSN_LOW;    
	SPI_RW(reg);			
	for(byte_ctr=0;byte_ctr<size;byte_ctr++)
	{
		pBuf[byte_ctr] = SPI_RW(0);
	}
	CSN_HIGH;              

	return (status);
}

SI24R1中重要有

  • 接收模式初始化

  • 发送模式初始化

  • 发送数据

  • 接收数据

    程序比着官方的DEMO修改,还可以查看最后的案例

image-20260417021819814

有关于宏定义的内容

寄存器的地址从00 - 1D

其他超了

的是就是SPI的指令

1
uint8_t TX_ADDRESS[TX_ADR_WIDTH] = {0x0A,0x01,0x07,0x0E,0x01};  // 默认发射地址
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/********************************************************
* SI24R1接收模式初始化
* 参数说明:无
* 返回值:无
*********************************************************/
void Int_SI24R1_RX_Mode(void)
{
	CE_LOW;
	Int_SI24R1_Write_Buf(SI24R1_WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); 		// 设置接收地址
	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, 40);                 				//选择射频通道40		
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  				//接收数据管道0数据字节数		
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_SETUP, 0x06);            				//数据传输速率1Mbps,发送功率4dBm		
	Int_SI24R1_Write_Reg( SI24R1_WRITE_REG+ CONFIG, 0x0f);              				//CRC使能 16位CRC,接收模式,电源开启 
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + STATUS, 0xff);  							//清除状态寄存器的中断标志
	CE_HIGH;                                            								
}						


/********************************************************
* SI24R1发送模式初始化
* 参数说明:无
* 返回值:无
*********************************************************/
void Int_SI24R1_TX_Mode(void)
{
	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);   
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_AA, 0x01);       											// 
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + EN_RXADDR, 0x01);   											// 
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + SETUP_RETR, 0x0a);  											//
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_CH, 40);         											// 
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + RF_SETUP, 0x06);    											// 
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG + CONFIG, 0x0e);      											
	CE_HIGH;																					
}
/********************************************************
* 读取接收数据	硬件直接接收数据保存到队列中
* 参数说明:
*   rxbuf: 用于存储接收数据的缓冲区
* 返回值:0:接收成功  1:接收失败
*********************************************************/
uint8_t Int_SI24R1_RxPacket(uint8_t *rxbuf)
{
	uint8_t state;
	// 读取状态寄存器的值 原封不懂写回状态寄存器	=》状态寄存器设置写1清除			
	state = Int_SI24R1_Read_Reg(STATUS);  			            //读取状态寄存器的值    	  
	Int_SI24R1_Write_Reg(SI24R1_WRITE_REG+STATUS,state);        //清除RX_DS中断标志位	

	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: 用于存储发送数据的缓冲区
* 返回值:0:发送成功  1:发送失败
*********************************************************/
uint8_t Int_SI24R1_TxPacket(uint8_t *txbuf)
{
	uint8_t state;
	//先进入配置模式,写入数据
	CE_LOW;															//CE拉低 使能SI24R1										  //CEͣʹSI24R1
  	Int_SI24R1_Write_Buf(WR_TX_PLOAD, txbuf, TX_PLOAD_WIDTH);	    //写数据到TX FIFO 32个字节
 	CE_HIGH;														//CE拉高 使能发送									  //CEøߣʹܷ	   
	
	//没有使用中断判断是否发送完成 =》使用轮询读取状态标志位
	//while(IRQ == 1);																				  //ȴ
	state = Int_SI24R1_Read_Reg(STATUS);   												  //读取状态寄存器
	while((state & (TX_DS | MAX_RT)) == 0)												//等待发送完成  发送成功或者达到最大重发次数
	{
		state = Int_SI24R1_Read_Reg(STATUS);   											  //读取状态寄存器
		vTaskDelay(10);
	}

	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 1; 
	}
	if(state & TX_DS)																	//发送成功
	{
		return 0;
	}
	return 1;																			//发送失败
}

最后的初始化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
char si24r1_buff[10];
/********************************************************
* 检查SI24R1是否正常工作
* 参数说明:
*   无
* 返回值:0:发送成功  1:发送失败
*********************************************************/
uint8_t Int_SI24R1c_Check(void){
	//先读取一次
	Int_SI24R1_Read_Buf(SI24R1_READ_REG + CONFIG, si24r1_buff, TX_ADR_WIDTH);

	//测试SPI通信能够正确读写寄存器
	//写入发送地址
	Int_SI24R1_Write_Buf(SI24R1_WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
	//读取发送地址
	Int_SI24R1_Read_Buf(SI24R1_READ_REG + TX_ADDR, si24r1_buff, TX_ADR_WIDTH);	
	
	for(uint8_t i = 0; i < TX_ADR_WIDTH; i++){
		if(si24r1_buff[i] != TX_ADDRESS[i]){
			return 1;	//通信失败
		}
	}
	return 0;	//通信成功
}

/********************************************************
* SI24R1初始化
* 参数说明:
*   无
* 返回值:无
*********************************************************/
void Int_SI24R1_Init(void){

	//上电后等待SI24R1稳定
	HAL_Delay(200);
	while(Int_SI24R1c_Check() == 1)	
	{
		HAL_Delay(10);
	}

	//设置默认的状态为接收模式 =》每次发送数据的时候 切换到发送状态
	Int_SI24R1_RX_Mode();
	debug_printf("SI24R1 Init Success!\r\n");
}

为什么先读取一次,就是清空FIFO缓冲区,防止旧数据干扰

Int_SI24R1.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef __Int_SI24R1__
#define __Int_SI24R1__

#include "spi.h"
#include "Com_debug.h"
#include "FreeRTOS.h"
#include "task.h"

//STM32CubeMX 定义引脚
//拉低片选
#define CSN_LOW    HAL_GPIO_WritePin(SPI2_CSN_GPIO_Port, SPI2_CSN_Pin, GPIO_PIN_RESET);
#define CSN_HIGH   HAL_GPIO_WritePin(SPI2_CSN_GPIO_Port, SPI2_CSN_Pin, GPIO_PIN_SET);

//拉高CE
#define CE_LOW     HAL_GPIO_WritePin(SPI2_CE_GPIO_Port, SPI2_CE_Pin, GPIO_PIN_RESET);
#define CE_HIGH    HAL_GPIO_WritePin(SPI2_CE_GPIO_Port, SPI2_CE_Pin, GPIO_PIN_SET);

#define TX_ADR_WIDTH    5    // 发射地址宽度 (bytes)
#define TX_PLOAD_WIDTH  32   // 发射载荷宽度 (bytes)

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

/********************************************************
* 写寄存器的值
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_WRITE_REG + reg
*   value: 要写入寄存器的值
* 返回值:寄存器的状态
*********************************************************/
uint8_t Int_SI24R1_Write_Reg(uint8_t reg, uint8_t value); 
/********************************************************
* 写寄存器的值 (多字节)
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_WRITE_REG + reg
*   pBuf: 要写入寄存器的数据缓冲区
*   bytes: 要写入的字节数
* 返回值:寄存器的状态
*********************************************************/
uint8_t Int_SI24R1_Write_Buf(uint8_t reg, const uint8_t *pBuf, uint8_t size);

/********************************************************
* 读寄存器的值
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_READ_REG + reg
* 返回值:寄存器的值
*********************************************************/
uint8_t Int_SI24R1_Read_Reg(uint8_t reg);
/********************************************************
* 读寄存器的值 (多字节)
* 参数说明:
*   reg: 寄存器地址   格式为 SI24R1_READ_REG + reg
*   pBuf: 用于存储读取数据的缓冲区
*   size: 要读取的字节数
* 返回值:寄存器的状态
*********************************************************/
uint8_t Int_SI24R1_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t size);
/********************************************************
* SI24R1接收模式初始化
* 参数说明:无
* 返回值:无
*********************************************************/
void Int_SI24R1_RX_Mode(void);
/********************************************************
* 读取接收数据	硬件直接接收数据保存到队列中
* 参数说明:
*   rxbuf: 用于存储接收数据的缓冲区
* 返回值:0:接收成功  1:接收失败
*********************************************************/
void Int_SI24R1_TX_Mode(void);
/********************************************************
* 读取接收数据	硬件直接接收数据保存到队列中
* 参数说明:
*   rxbuf: 用于存储接收数据的缓冲区
* 返回值:0:接收成功  1:接收失败
*********************************************************/
uint8_t Int_SI24R1_RxPacket(uint8_t *rxbuf);

/********************************************************
* 发送数据
* 参数说明:
*   txbuf: 用于存储发送数据的缓冲区
* 返回值:0:发送成功  1:发送失败
*********************************************************/
uint8_t Int_SI24R1_TxPacket(uint8_t *txbuf);


/********************************************************
* SI24R1初始化
* 参数说明:
*   无
* 返回值:无
*********************************************************/
void Int_SI24R1_Init(void);

//********************************************************************************************************************//
#endif
最后更新于 2026-04-18 01:45