【无线芯片解读】2.4G专题:Si24R1

简介

Si24R1芯片工作在2.4GHz ISM频段,集成嵌入式ARQ基带协议引擎。
工作频率范围:2400MHz~2525MHz
信道数:126
带宽:1MHz
调制与解调技术:GFSK/FSK
数据速率:2Mbps/1Mbps/250Kbps
最高发射功率:7dBm
接收灵敏度:< -83dBm @2Mbps
发射电流:<12mA @0dBm,2Mbps
接收电流:<15mA @0dBm,2Mbps
通信接口:SPI ,@10MHz
电压范围:1.9-3.6V
RSSI值:1bit输出,-60dBm
关断功耗:<0.7uA
待机功耗:<15uA
快速启动时间:<130us
外接晶体:16MHz ±60ppm
硬件框架:
在这里插入图片描述
PA:无线信号从芯片发射端的功率放大器
Power Management:电源管理
LNA:无线信号从芯片接收端的低噪声放大器, 噪声系数很低的放大器
RF PLL:射频锁相环,利用相位同步产生的电压,去调谐压控振荡器以产生目标频率的负反馈控制系统。
GFSK/FSK Modulator:调制器
GFSK/FSK Demodulator:解调器
ARQ Engine:ARQ协议引擎
TX FIFO:发射队列
RX FIFO:接收队列
SPI:串行接口
Regs Map:寄存器表图

应用范围

无线遥控,无线鼠标,无线键盘,无线电子标签,遥控无人机,遥控玩具等。

芯片引脚定义

在这里插入图片描述

端口号端口名称功能描述
1CE芯片开启信号,激活TX或RX
2CSNSPI片选信号
3SCKSPI时钟信号
4MOSISPI输入信号
5MISOSPI输出信号
6IRQ可屏蔽中断信号,低电平有效
7,15,18VCC电源
8,14,17,20VSS
9XO晶体输出引脚
10XI晶体输入引脚
11VDD_PA给内置PA供电的电源输出引脚
12RFP天线接口1
13RFN天线接口2
16IREF基准电流
19VDD_D内部数字电路电源,需接去耦电容

工作模式:

在这里插入图片描述SI24R1芯片供电电压至少大于1.9V,典型值3.3V,需延时100ms让芯片稳定工作。
关断模式:CONFIG寄存器的PWR_UP位清0,该模式下所有寄存器值与FIFO值保持不变,功耗<0.7uA。也可以通过SPI实现寄存器的读写。芯片的时钟稳定时间一般在1.5~2ms。
待机模式:CE脚拉低,CONFIG寄存器的PWR_UP位置1,该模式下时钟保持工作,功耗<15uA,切换收发时间小于130us。也可以通过SPI实现寄存器的读写。
发射空闲模式:CE脚拉高,CONFIG寄存器的PRIM_RX位清0,不发包(TX FIFO无数据)。也可以通过SPI实现寄存器的读写。
发射模式:CE脚拉高,CONFIG寄存器的PRIM_RX位清0,发包(TX FIFO有数据)。数据发射完成,会产生发射完成中断。
接收模式:CE脚拉高,CONFIG寄存器的PRIM_RX位置1。该模式收包通过数据包的地址和芯片地址比对,CRC检查,然后收到的数据自动存入RX FIFO,并产生数据接收中断。

数据包处理协议

ARQ包格式:

在这里插入图片描述

前导码字段:用于接收同步,发射时芯片自动附上,接收时芯片自动去掉(对用户不可见)
地址字段:作为接收数据方地址,与芯片的地址寄存器中地址相同时才会接收。
包控制字段:长度为9bit,
在这里插入图片描述
数据包长度指定数据包的长度可为0-32Byte;PID是发射方告知接收方发的包是新包还是重发的包;NO_ACK是发射方告知接收方是否回ACK确认信号。
负载数据字段:发射数据内容,最大32Byte。
CRC字段:包的CRC值,支持8bit和16bit两种,通过CONFIG寄存器中的CRCO位配置。

通信模式:

(TX)发射模式:自动将ARQ格式的数据包打包,输出信号进行调制由天线发射。
(RX)发射模式:不断侦测解调信号中的有效地址,一旦检测到地址与接收地址相同时,开始接收数据。接收到的负载数据存放在RX FIFO中,并由芯片的IRQ引脚产生中断通知MCU。MCU通过SPI接口随时访问RX FIFO寄存器,读取数据。
ACK模式:回复ACK信号
NO_ACK模式:不回复ACK信号
动态负载长度模式:字符长度可调的数据发送和接收,发射段即对TX FIFO(最大32字节)写入数据,然后拉搞CE启动传输,并打包传输。接收端需检查接收长度并按照接收长度读取数据。这里要DYNPD、FEATURE配置这两个寄存器。
静态负载长度模式:固定32字节长度的数据发送和接收,传输不够灵活。
多管道通信模式:支持多发一收(最多6发1收),接收方的接收管道地址设置与对应的发射管道地址设置相同。

SPI数据与控制接口:

芯片采用标准的四线SPI接口,读写速度最大支持10Mb/s。
SPI常见操作命令:
在这里插入图片描述

主要寄存器操作:

CONFIG:配置寄存器值0x00
收发配置在第0位: 0:发射模式 1:接收模式
开关机配置在第1位: 0:关断模式 1:开启模式

EN_AA:使能自动确认寄存器

SETUP_RETR:自动重发配置寄存器值0x04
高4位(7:4):自动重发延时配置 0x00-0xFF(250~4000us,250的倍数)
低4位(3:0):最大重发次数配置
0x00:关闭重发次数
0x01、0x02、0x04、…0xff:开启(1~15)重发次数。

RF_CH:射频信道寄存器值0x05
信道配置 0x00-0x7D (2400MHz~2525MHz)

RF_SETUP:射频配置寄存器
低3位(2:0):设置发射功率 0x00~0x07,共8个等级
第3位和第5位:设置数据速率

STATUS:状态寄存器

DYNPD:配置使能动态负载长度
0x01 使能通道1的动态负载长度

FEATURE:配置使能动态负载
0x04 使能动态负载长度特性

典型芯片电路图:

Si24R1芯片外围电路包含外接16MHz晶振时钟电路,RF射频π型匹配电路,电源滤波电路。
在这里插入图片描述

驱动程序应用:

si24r1.c文件内容:

#include "SI24R1.h"
#include "delay.h"
u8 TX_ADDRESS[TX_ADR_WIDTH] = {0x0A,0x01,0x07,0x0E,0x01};    

/*SPI读写字节函数*/
static u8 SPI_RW(u8 byte)
{
	u8 bit_ctr;
	for(bit_ctr=0; bit_ctr<8; bit_ctr++) //轮询8位
	{
		if(byte & 0x80) MOSI = 1; //判断如果最高位是高电平,输出高电平
		else MOSI = 0;			//反之输出低电平												 
		byte = (byte << 1); //左移                    
		SCK = 1;            //SCK为高                           
		byte |= MISO;       //字节值按位或(相加)                     
		SCK = 0;            //SCK为低                   
	}
	return(byte);    //返回字节和                          
}

/*SPI IO初始化函数*/
void SI24R1_Init(void)
{
	SCK = 0; //SCK(SPI)时钟引脚拉低 													
	CSN = 1;	//CSN片选引脚拉高		
	CE 	= 0; //CE脚拉低,待机准备状态				
	IRQ = 1; //中断引脚拉高,低电平有效
}
/*SPI写寄存器函数*/
u8 SI24R1_Write_Reg(u8 reg, u8 value)
{
	u8 status;
	CSN = 0; //CSN片选引脚拉低                
	status = SPI_RW(reg);	//返回写的寄存器值			
	SPI_RW(value);//写值
	CSN = 1; //CSN片选引脚拉高
	return(status);
}
/*SPI写数据函数*/
u8 SI24R1_Write_Buf(u8 reg, const u8 *pBuf, u8 bytes)
{
	u8 status,byte_ctr;
  CSN = 0;  //CSN片选引脚拉低                                    			
  status = SPI_RW(reg);//返回写的寄存器值                          
  for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) //数据遍历写入   
    SPI_RW(*pBuf++);
  CSN = 1;  //CSN片选引脚拉高                                 	
  return(status);       
}							  					   
/*SPI读寄存器函数*/
u8 SI24R1_Read_Reg(u8 reg)
{
 	u8 value;
	CSN = 0;    
	SPI_RW(reg);	
	value = SPI_RW(0);//读寄存器值	
	CSN = 1;              
	return(value);
}
/*SPI读数据函数*/
u8 SI24R1_Read_Buf(u8 reg, u8 *pBuf, u8 bytes)
{
	u8 status,byte_ctr;
  CSN = 0;                                        
  status = SPI_RW(reg);                           
  for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
    pBuf[byte_ctr] = SPI_RW(0); //读数据内容                  
  CSN = 1;                                        
  return(status);    
}
/*设置接收模式*/
void SI24R1_RX_Mode(void)
{
	CE = 0;
	SI24R1_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);	
	SI24R1_Write_Reg(WRITE_REG + EN_AA, 0x01);               						
	SI24R1_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);           						
	SI24R1_Write_Reg(WRITE_REG + RF_CH, 40);                 						
	SI24R1_Write_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  						
	SI24R1_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);            						
	SI24R1_Write_Reg(WRITE_REG + CONFIG, 0x0f);              					
	SI24R1_Write_Reg(WRITE_REG + STATUS, 0xff);  												
	CE = 1;                                            							
}						
/*设置发射模式*/
void SI24R1_TX_Mode(void)
{
	CE = 0;
	SI24R1_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    ·
	SI24R1_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);  
	SI24R1_Write_Reg(WRITE_REG + EN_AA, 0x01);       											
	SI24R1_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);   											
	SI24R1_Write_Reg(WRITE_REG + SETUP_RETR, 0x0a);  											
	SI24R1_Write_Reg(WRITE_REG + RF_CH, 40);         											
	SI24R1_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);    											
	SI24R1_Write_Reg(WRITE_REG + CONFIG, 0x0e);      											
}
/*收包函数*/
u8 SI24R1_RxPacket(u8 *rxbuf)
{
	u8 state;
	state = SI24R1_Read_Reg(STATUS);  			                    	  
	SI24R1_Write_Reg(WRITE_REG+STATUS,state);              
	if(state & RX_DR)								                          
	{
		SI24R1_Read_Buf(RD_RX_PLOAD,rxbuf,TX_PLOAD_WIDTH);     
		SI24R1_Write_Reg(FLUSH_RX,0xff);					              
		return 0; 
	}	   
	return 1;                                                   
}

/*发包函数*/
u8 SI24R1_TxPacket(u8 *txbuf)
{
	u8 state;
	CE=0;																										  
    SI24R1_Write_Buf(WR_TX_PLOAD, txbuf, TX_PLOAD_WIDTH);	    
 	CE=1;																										  
	while(IRQ == 1);																				  
	state = SI24R1_Read_Reg(STATUS);  											   	   
	SI24R1_Write_Reg(WRITE_REG+STATUS, state); 								
	if(state&MAX_RT)																			    
	{
		SI24R1_Write_Reg(FLUSH_TX,0xff);										    
		return MAX_RT; 
	}
	if(state&TX_DS)																			      
	{
		return TX_DS;
	}
	return 0xFF;																						  
}

si24r1.h头文件内容:

#include "config.h"
//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 32  				// Êý¾ÝͨµÀÓÐЧÊý¾Ý¿í¶È

//********************************************************************************************************************//
// SPI(SI24R1) 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(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
#define DYNPD           0x1C
#define FEATURE         0x1D
//********************************************************************************************************************//
// STATUS Register 
#define RX_DR						0x40  /**/
#define TX_DS						0x20
#define MAX_RT					  0x10

//********************************************************************************************************************//
//                                        FUNCTION's PROTOTYPES                                                       //
//********************************************************************************************************************//
//SI24R1 API Functions
void SI24R1_Init(void); //SI24R1 Pin Init
u8 SI24R1_Write_Reg(u8 reg, u8 value); 
u8 SI24R1_Write_Buf(u8 reg, const u8 *pBuf, u8 bytes);
u8 SI24R1_Read_Reg(u8 reg);
u8 SI24R1_Read_Buf(u8 reg, u8 *pBuf, u8 bytes);

void SI24R1_RX_Mode(void);
void SI24R1_TX_Mode(void);
u8 SI24R1_RxPacket(u8 *rxbuf);
u8 SI24R1_TxPacket(u8 *txbuf);
#endif

main.c文件内容:

#include "SI24R1.h"
#include "delay.h"
#include "string.h"
#define LED3		P16
#define LED4		P35
#define KEY1		P12
#define KEY2		P14
unsigned char tx_data[32]={0};
unsigned char rx_data[32]={0};
#define FOSC    22118400L
#define BAUD    115200//9600
#define UART_RX_FIFO 32
unsigned char UART_RX_Data[UART_RX_FIFO];
/*串口函数初始化*/
void uart_init(void)
{
	SCON = 0x50;
	T2L = (65536 - (FOSC/4/BAUD));
	T2H = (65536 - (FOSC/4/BAUD)) >> 8;
	AUXR = 0x14;
	AUXR |= 0x01;
	ES = 1;
	EA = 1;
}
/*串口发送字符函数*/
void SendData(unsigned char Data)
{ 
	SBUF = Data;
	while(TI == 0);
	TI = 0;
}
/*串口发送字符串函数*/
void SendString(char *s)
{
	while(*s)
	{
		SendData(*s++);
	}
}
/*串口接收字符函数*/
void RecvData(unsigned char Data)
{ 
	unsigned int i;
	for(i=0;i<UART_RX_FIFO;i++)
	{
	 UART_RX_Data[i] = Data;
	}
	while(RI == 0);
	RI = 0;
}
/*设置串口响应中断*/
void UART_i() interrupt 4
{
	if(RI)
	{
		 RI = 0;
		 RecvData(SBUF);
	}
	if(TI)
	{
		 TI = 0;
	}
}

void main(void)
{
  unsigned char udata=0,rssi;
  uart_init(); //串口初始化
  SI24R1_Init();//2.4G SPI初始化
  #if 0
  SI24R1_TX_Mode(); //设置发射模式
  #else
  SI24R1_RX_Mode(); //设置接收模式
  #endif
	while(1)
	{
	 #if 0
	 udata = SI24R1_TxPacket(tx_data);//发包
	 #else
	 udata = SI24R1_RxPacket(rx_data);//收包
	 rssi=SI24R1_Read_Reg(RSSI); //获取接收信号强度
	 if(rssi == 0)
	 {
	  SendString("<-60dBm\r\n");
	 }
	 else
	 {
	  SendString(">-60dBm\r\n");
	 }
	 #endif
	 delay_ms(50);	 // Broadcasting interval
	 if(udata == 0xff)
	 {
		 LED4=0;//SendString("send fail\r\n");
		 LED3=0;
		 SendString("send or recv fail\r\n");
	 }
	 else
	 {
		 LED4=1;//SendString("send ok\r\n");
		 LED3=1;
		 SendString("send or recv ok\r\n");
	 }
	}
}

认证指南:

随着国家强制对无线产品的认证要求,针对SI24R1这款芯片,一般过的认证频率为:2402MHz 2440MHz 2480MHz。可以通过下面的代码来完成定频中的功率等级、速率、信道频率、单载波及调制模式的设置:

#include "SI24R1.h"
#include "delay.h"
#define RF_POWER_F12    0x00//-12dBm
#define RF_POWER_F6     0x01//-6dBm
#define RF_POWER_F4     0x02//-4dBm
#define RF_POWER_0      0x03//0dBm
#define RF_POWER_1      0x04//1dBm
#define RF_POWER_3      0x05//3dBm
#define RF_POWER_4      0x06//4dBm
#define RF_POWER_7      0x07//7dBm

#define RF_FREQ_250K    0x20//250Kbps
#define RF_FREQ_1M      0x00//1Mbps,对应带宽1MHz
#define RF_FREQ_2M      0x08//2Mbps,对应带宽2MHz

#define RF_CH_2525      0x7D//125  
#define RF_CH_2500      0x64//100 
#define RF_CH_2482      0x52//82   
#define RF_CH_2480      0x50//80  2480MHz
#define RF_CH_2463      0x3F//63   
#define RF_CH_2462      0x3E//62   
#define RF_CH_2442      0x2A//42   
#define RF_CH_2440      0x28//40  2440MHz
#define RF_CH_2402      0x02//02  2402MHz
#define RF_CH_2400      0x00//00   
#define Single_Carrier_MODE  1    //单载波模式
#define Modulated_Wave_MODE  0    //调制波模式
#define ADV_INTERVAL_MS      50   //广播间隔

供认证测试设置使用的函数

void Set_CERTIFIED_Mode(unsigned charrf_Ch,unsigned char rf_Power,unsigned char rf_Freq ,unsigned char rf_Mode)
{
	static unsigned char RF_value = 0;
	CE = 0;
	SI24R1_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); 
	SI24R1_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
	SI24R1_Write_Reg(WRITE_REG + EN_AA, 0x01); 
	SI24R1_Write_Reg(WRITE_REG + EN_RXADDR,0x01); 
    SI24R1_Write_Reg(WRITE_REG + SETUP_RETR,0x0a); 
	rf_Ch = rf_Ch&0xff;
	SI24R1_Write_Reg(WRITE_REG + RF_CH,rf_Ch); 
	RF_value |= rf_Power;
	RF_value |= rf_Freq;
	switch(rf_Mode)
	{
	case Single_Carrier_MODE:
	  RF_value |= 0x80;//cont_wave
    RF_value |= 0x10;//pll_lock
   break;
   case Modulated_Wave_MODE:
   break;
	}
	RF_value =  RF_value&0xff;
	SI24R1_Write_Reg(WRITE_REG + RF_SETUP,RF_value);   
  SI24R1_Write_Reg(WRITE_REG + CONFIG,0x0e);      
}

void send_packet(unsigned int interval_ms,unsigned char *data_value)
{
	SI24R1_TxPacket(data_value);
	delay_ms(interval_ms);	 // Broadcasting interval
}

设置认证参数

unsigned char adv_data[32]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xF0,0xE0,0xD0,0xC0,0xB0,0xA0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10,0x00};//数据包
void main(void)
{
  SI24R1_Init();	
Set_CERTIFIED_Mode(RF_CH_2402,RF_POWER_0,RF_FREQ_1M,Single_Carrier_MODE);//设置频率、功率、速率、模式
while(1)
{
  send_packet(ADV_INTERVAL_MS,adv_data);//定时发包
}
}

认证常见问题

1)、杂散问题
在不影响传输距离的情况下,适当降低功率,可以改善RF匹配的滤波电路。
2)、EMC问题
注意VCC端加滤波电容电路。

模拟BLE信号

BLE是用的2.4G ISM频段,由于Si24r1的调制方式接近,我们可以使用Si24R1来模拟BLE的广播信号(仅仅只能模拟BLE的广播信号)。首先,我们解析一下BLE的包的结构。
1、前导码1Byte,0x55或0xAA,硬件根据访问地址的第一个bit自动添加生成
2、访问地址4Byte,固定为0x8E89BED6
3、帧头1Byte,广播包类型
4 、负载长度1Byte
5、 负载数据0~37Byte
6、 帧尾1Byte,CRC校验和,Si24R1硬件会自动计算出CRC,由于BLE使用LFSR生成的24位的CRC值,故需要禁止掉SI24R1的硬件自动CRC算法。如下图:
在这里插入图片描述使用多项式的CRC算法生成蓝牙的3-bytes CRC。BLE的收发包过程如下图:
在这里插入图片描述切入正题,主要的实现函数如下:

/*************** BLE  ***************/
#define GAP_ADTYPE_MESH_TYPE_ADVDATA         0x2A
#define GAP_ADTYPE_LOCAL_NAME_COMPLETE       0x09 //!< Complete local name
#define GAP_ADTYPE_MANUFACTURER_SPECIFIC     0xFF //!< Manufacturer Specific Data: first 2 octets contain the Company Identifier Code followed by the additional manufacturer specific data
/*BLE的CRC校验函数,24bit-CRC算法*/
static void LeLfsrCrc(const unsigned char* Data, unsigned char Len, unsigned char* Dst)
{
	unsigned char _v, _t, _d;
	while(Len--)
	{ 
		_d = *Data++;
		for(_v = 0; _v < 8; _v++, _d >>= 1)
		{
			_t = Dst[0] >> 7;
			Dst[0] <<= 1;
			if(Dst[1] & 0x80) Dst[0] |= 1; Dst[1] <<= 1;
			if(Dst[2] & 0x80) Dst[1] |= 1; Dst[2] <<= 1;           
			if(_t != (_d & 1))
			{
				Dst[2] ^= 0x5B;
				Dst[1] ^= 0x06;
			}
		} 
	}
}

/*单字节高低位互换函数,大小端*/
static unsigned char Bit_Swap(unsigned char Byte)
{
	unsigned char Value = 0,i;
	unsigned char Data[8];
	for(i=0;i<8;i++)
	{
		Data[i] = 0x01<<i;  
		if(Byte & Data[i])
		Value |= 0x80>>i;
	}
  return Value;
}

/*BLE LFSR白化实现*/
static void LeLfsrWhite(unsigned char* Data, unsigned char Len, unsigned char Coeff)
{
	unsigned char i;
	while(Len--)
	{
		for(i = 1; i; i <<= 1)
		{
			if(Coeff & 0x80)
			{
				Coeff ^= 0x11;
				(*Data) ^= i;
			}
			Coeff <<= 1;
		}
		Data++;
	}
}

/*加密BLE包*/
static void EncodeBlePacket(unsigned char* Packet, unsigned char Len, unsigned char Chan)
{
	unsigned char i, DataLen = Len - 3;
	LeLfsrCrc(Packet, DataLen, Packet + DataLen);
	
	for(i = 0; i < 3; i++, DataLen++) Packet[DataLen] = Bit_Swap(Packet[DataLen]);
	
	LeLfsrWhite(Packet, Len, Bit_Swap(Chan)|2);
	
	for(i = 0; i < Len; i++) Packet[i] = Bit_Swap(Packet[i]);
}
/*设置BLE模式*/
void SI24R1_BLE_Mode(void)
{
	CE = 0;
	SI24R1_Write_Reg(WRITE_REG+CONFIG,0x12);//关闭最大重发计数中断,关闭CRC,开机模式,发射模式
	SI24R1_Write_Reg(WRITE_REG+EN_AA,0x00); /* no ack ,不使能自动确认*/
	SI24R1_Write_Reg(WRITE_REG+EN_RXADDR,0x00); /* no rx,不使能接收数据管道地址 */
	SI24R1_Write_Reg(WRITE_REG+SETUP_AW,0x02); /* 4-byte addr,发射地址宽度4字节 */
	SI24R1_Write_Reg(WRITE_REG+SETUP_RETR,0x00); /* no auto-retransmit,关闭自动重发 */
	SI24R1_Write_Reg(WRITE_REG+RF_SETUP,0x06); /* 1Mbps at 0dbm */
	SI24R1_Write_Reg(WRITE_REG+STATUS,0x3e); /* clear flags,清除标志 */
	SI24R1_Write_Reg(WRITE_REG+DYNPD,0x00); /* no dynamic payloads,不使能动态负载长度 */
	SI24R1_Write_Reg(WRITE_REG+FEATURE,0x00); /* no features,不使能动态负载*/
	SI24R1_Write_Reg(WRITE_REG+RX_PW_P0,32); /* always rx 32 bytes,接收数据管道0数据字节数32字节 */
	SI24R1_Write_Reg(WRITE_REG+EN_RXADDR, 0x01); /* rx on pipe 0 ,使能接收数据管道0地址*/
    TX_ADDRESS[0] = Bit_Swap(0x8E);
    TX_ADDRESS[1] = Bit_Swap(0x89);
    TX_ADDRESS[2] = Bit_Swap(0xBE);
    TX_ADDRESS[3] = Bit_Swap(0xD6);
	SI24R1_Write_Buf(WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS, 4);//set wirte address 设置发射方的发射地址
	SI24R1_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS, 4);//set wirte address 数据管道0的接收地址,发射方需要接收ACK信号,需设一样的地址。
}

/*低8位校验和计算*/
static unsigned char check_lockkey(unsigned char *Data,unsigned char Len) 
{
    unsigned char result;
    int i,num = 0;
    for (i = 0; i < Len; i++)
    {
       num = (num + Data[i]) % 256;
    }
    result = (char)num;
    return result;
}

/*模拟BLE广播包*/
static unsigned char Imitate_Ble_Packet(unsigned char *data_value,unsigned char *data_mac,unsigned char *data_name)
{
	unsigned char Value=0;
	buf[Value++] = 0x42|0x40; //PDU type, random address; Android:0x42 iPhone:0x40
	buf[Value++] = 21;     // payload length 
				  
	buf[Value++] = data_mac[0];
	buf[Value++] = data_mac[1];
	buf[Value++] = data_mac[2];
	buf[Value++] = data_mac[3];
	buf[Value++] = data_mac[4];
	buf[Value++] = data_mac[5];
	#if 0		  
	buf[Value++] = 2;   //flags (LE-only, general discoverable mode)
	buf[Value++] = 0x01;
	buf[Value++] = check_lockkey(data_value,5);//0x06;//A9;//0x06;
			  
	buf[Value++] = 4;   // length of the name, including type byte
	buf[Value++] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;//0x09
	buf[Value++] = data_name[0];//'A';
	buf[Value++] = data_name[1];//'X';
	buf[Value++] = data_name[2];//'K';
				  
	buf[Value++] = 6;   // length of custom data, including type byte
	
	buf[Value++] = GAP_ADTYPE_MANUFACTURER_SPECIFIC;//0xFF 
	
	buf[Value++] = data_value[0];//0x11;
	buf[Value++] = data_value[1];//0x22;	
	buf[Value++] = data_value[2];//0x33;// some test data
	buf[Value++] = data_value[3];//0x44;
	buf[Value++] = data_value[4];//0x55; 
  #else
	buf[Value++] = 14;   //flags (LE-only, general discoverable mode)
	buf[Value++] = GAP_ADTYPE_MESH_TYPE_ADVDATA;
		
	buf[Value++] = check_lockkey(data_mac,6);
	buf[Value++] = data_mac[0];
	buf[Value++] = data_mac[1];
	buf[Value++] = data_mac[2];
	buf[Value++] = data_mac[3];
	buf[Value++] = data_mac[4];	
	buf[Value++] = data_mac[5];
		
	buf[Value++] = check_lockkey(data_value,6); 
	buf[Value++] = data_value[0];//0x11;
	buf[Value++] = data_value[1];//0x22;	
	buf[Value++] = data_value[2];//0x33;// some test data
	buf[Value++] = data_value[3];//0x44;
	buf[Value++] = data_value[4];//0x55; 
	#endif
	buf[Value++] = 0x55;//55;	//CRC start value: 0x555555
  buf[Value++] = 0x55;//55;
	buf[Value++] = 0x55;//55;
	return Value;
}

/*BLE发包函数*/
void send_ble_packet(unsigned int interval_ms,unsigned char *data_value,unsigned char *data_mac,unsigned char *data_name)
{
	static unsigned char Len=0;
	for(ch=0; ch<sizeof(chRf); ch++)
	{ 
		Len = Imitate_Ble_Packet(data_value,data_mac,data_name);
		SI24R1_Write_Reg(WRITE_REG+RF_CH, chRf[ch]);//hop channel设置信道
		SI24R1_Write_Reg(WRITE_REG+STATUS, 0x6E); // clear flags		  
    EncodeBlePacket(buf, Len, chLe[ch]);	  
		SI24R1_Write_Reg(FLUSH_TX,0xff); //Clear TX Fifo
		SI24R1_Write_Reg(FLUSH_RX,0xff); //Clear RX Fifo		
		SI24R1_TxPacket(buf);
    delay_ms(2);
	}
  delay_ms(interval_ms);	 // Broadcasting interval
}``

Si24R1通信异常问题集锦

2.4G通信异常一般都有如下问题:
1、一次也不能收到数据
(初诊:硬件接线和软件配置问题)
2、在发射端或接收端重新上电的时候,可接收到一次
(初诊:没有及时清空RX FIFO和接收中断标志)
3、由发送模式切换为接收模式后,就不能接收了
(初诊:没有及时清空TX FIFO,RX FIFO和接收中断标志)
4、设置高功率等级之后,就不能接收了
(初诊:供电电流不足)
5、无规律偶发不能接收
(初诊:存在电源干扰)
6、通信距离短,远距离容易丢包
(初诊:硬件结构和PCB设计影响了天线净空区,造成了信号衰减)
7、接收数据后,进入待机模式下,功耗比较大,达到了mA级
(初诊:CE脚没有被拉低)
8、一发多收的时候,存在丢包问题
(初诊:广播通信数量过多的情况下,需要设置更高的信道,适当调整发包间隔)

硬件部分排查

我们在写Si24R1通信代码前,一定要首先保证硬件原理图、PCB以及结构设计是正常的。
(1)、MCU SPI和Si24R1 SPI的IO引脚连接无误。
(2)、Si24R1模块电源脚附近放大小电容10uF和0.1uF。
(3)、处于接收模式时,Si24R1模块的CE引脚应为高电平,正常是3V以上。
(4)、稳定3.3V,纹波<30mV为宜,供电电流要充足。
(5)、Si24R1的天线净空区要做好,禁止靠近高频器件,金属结构件,电路电线。
(6)、用示波器检测SI24R1的IRQ引脚是否有波形变化。

软件部分排查

(1)、保证收发端的设备地址、射频信道、射频传输速率、地址宽度、传输数据宽度设置值是一致的。
(2)、发送完成要及时清空TX FIFO和发送中断标志以及最大发射中断标志,接收完成要及时清空RX FIFO和接收中断标志。
(3)、检测通过SPI读写Si24R1的寄存器是否正常。
(4)、熟悉Si24R1芯片手册的工作模式状态机切换过程。

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值