方案名称:915MHZ中远距离无线通信模块
设计简要说明:
利用MCU+RF实现中心频率915MHZ的无线收发系统,具体参数规格如下:
通信距离:1000-2000m
通信速率:0~57600kbs
接口类型:Micro USB/TTL串口
供电方式:USB/外部电源供电
供电范围:DC5-18V
申请物料:
HY0320 10颗
HY0620 10颗
方案名称:915MHZ中远距离无线通信模块
设计简要说明:
利用MCU+RF实现中心频率915MHZ的无线收发系统,具体参数规格如下:
通信距离:1000-2000m
通信速率:0~57600kbs
接口类型:Micro USB/TTL串口
供电方式:USB/外部电源供电
供电范围:DC5-18V
申请物料:
HY0320 10颗
HY0620 10颗
方案设计
方案采用MCU+RF的结构,MCU采用STM2F042F6P6作为主控,RF收发器采用siliconlabs的高性能Sub1G芯片SI4463,两个主芯片均工作在低功耗模式下,保证系统在性能可靠的前提下,降低系统功耗,通过经过优化算法的数传无线收发算法,保证数据能考可靠稳定的进行传输。
下面开始上电路图
电源电路,输入电压范围DC5V-24V,增加了可恢复保险丝,由于空间问题没有在输入端增加TVS做保护
TTL串口电路,为了增加系统稳定性和可靠性,串联了电阻,另外为做好接口兼容性,保证5V TTL串口电平,中间使用了后羿电子提供的MOSFET HY0320作为电平转换,保证3.3V和5V电平相互转换。
MCU主控电路,主控电路与RF芯片之间通过SPI接口进行通信,完成数据的收发以及控制。
RF射频电路,该电路需要通过大量测试进行参数匹配,保证系统信号完整性。其中为了降低系统功耗,使用后羿电子提供的HY0620 进行电源的供电与断开的控制。
本来打算等样片到了再继续搞,过一段时间会比较忙,所以不等样片了,先搞起来了,本来可以做2层板的,但是由于体积限制,板子空间太小,被迫做了4层PCB,好在目前的4层PCB的成本也不高,上PCB图,板子尺寸:30*15mm
PCB布局图(顶层)
PCB布局图(底层)
顶层布线,射频进行了50欧姆阻抗控制,保证信号的完整性。对射频电路进行了合理的规划布局。中间层
中间层(电源层)
底层布线
主程序结构如下:
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_IWDG_Init();
MX_SPI1_Init();
// MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
//GetLockCode();
//rev_ID_write(Lock_Code1);
//Lock_Code=0;
//Lock_Code=rev_ID_read();
// if(Lock_Code != Lock_Code1)
// return 0; //??0x123456789ABC??????ID
RF_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
RF_TX_RX_CTRL();
RF_Process();
HAL_IWDG_Refresh(&hiwdg);//watch dog
}
/* USER CODE END 3 */
}产品设计中涉及用到的外设包括SPI、USART、DMA、定时器以及看门狗。
其中SPI用来与RF射频收发器进行数据传输以及参数配置,USART作为用户数据的收发,DMA与USART配合提高数据收发效率
RF收发器调试,首先通过SPI接口读取RF收发器的ID,如果ID为4463,那么可以证明通信接口通信没问题,对RF收发芯片的初始化配置操作在工程中void RF_init()函数中实现,下面上具体参数配置源码
void RF_init()
{
Si4463_GpioInt();
HAL_DMA_Abort_IT(&hdma_usart1_tx);
HAL_DMA_Abort_IT(&hdma_usart1_rx);
RF_parameters_init();
RF_parameters_read();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA(&huart1,tx_ph_data,buffer_size);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //??????
sdn_reset();// reset RF
SI4463_init(); // RF INIT
delay_us(200);
spi_read_info();
delay_us(200);
HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);
HAL_NVIC_ClearPendingIRQ(EXTI2_3_IRQn);
HAL_NVIC_SetPriority(EXTI2_3_IRQn, 1, 0);
delay_us(200);
nIRQ=1;
recv_end_flag=0;
uart_rx_len=0;
rx_len_tmp=0;
len_var=0;
rx_init();
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_IWDG_Start(&hiwdg);//start iwdg
}
spi_read_info();为读取id函数,返回值为4463,证明通信接口正常工作。
void SI4463_init(void)
{
U8 app_command_buf[20];
//spi_write(0x07, RF_GPIO_PIN_CFG_data);
app_command_buf[0] = 0x13; // SET GPIO PORT
app_command_buf[1] = 0x14; // gpio 0 ,Rx data
app_command_buf[2] = 0x02; // gpio1, output 0
app_command_buf[3] = 0x21; // gpio2, hign while in receive mode
app_command_buf[4] = 0x20; // gpio3, hign while in transmit mode
app_command_buf[5] = 0x27; // nIRQ
app_command_buf[6] = 0x0b; // sdo
spi_write(7, app_command_buf);
// spi_write(0x05, RF_GLOBAL_XO_TUNE_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x00;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x00;
app_command_buf[4] = 125; // freq adjustment
spi_write(5, app_command_buf);
// spi_write(0x05, RF_GLOBAL_CONFIG_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x00;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x03;
app_command_buf[4] = 0x40; // tx = rx = 64 byte,PH,high performance mode
spi_write(5, app_command_buf);
spi_write(0x08, (unsigned char *)RF_FRR_CTL_A_MODE_4_data); // disable all fast response register
// spi_write(0x0D, RF_PREAMBLE_TX_LENGTH_9_data); // set Preamble
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x10;
app_command_buf[2] = 0x09;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x08; // 8 bytes Preamble
app_command_buf[5] = 0x14; // detect 20 bits
app_command_buf[6] = 0x00;
app_command_buf[7] = 0x0f;
app_command_buf[8] = 0x31; // no manchest.1010.??
app_command_buf[9] = 0x00;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0x00;
app_command_buf[12] = 0x00;
spi_write(13, app_command_buf);
// RF_SYNC_CONFIG_5_data, // set sync
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x11;
app_command_buf[2] = 0x05;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x01; // no manchest , 2 bytes
app_command_buf[5] = 0x2d; // sync byte3
app_command_buf[6] = 0xd4; // sync byte2
app_command_buf[7] = 0x00; // sync byte1
app_command_buf[8] = 0x00; // sync byte0
spi_write(9, app_command_buf);
// packet crc
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x81; // CRC = itu-c, enable crc
spi_write(5, app_command_buf);
// packet gernale configuration
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x06;
app_command_buf[4] = 0x02; // CRC MSB, data MSB
spi_write(5, app_command_buf);
// spi_write(0x07, RF_PKT_LEN_3_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x03;
app_command_buf[3] = 0x08;
app_command_buf[4] = 0x0a;
app_command_buf[5] = 0x01;
app_command_buf[6] = 0x00;
spi_write(7, app_command_buf);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x0c;
app_command_buf[3] = 0x0d;
app_command_buf[4] = 0x00;
app_command_buf[5] = 0x05;
app_command_buf[6] = 0x04;
app_command_buf[7] = 0xaa;
app_command_buf[8] = 0x00;
app_command_buf[9] = payload_length;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0xaa;
app_command_buf[12] = 0x00;
app_command_buf[13] = 0x00;
app_command_buf[14] = 0x00;
app_command_buf[15] = 0x00;
spi_write(16, app_command_buf); // set length of Field 1 -- 4
// spi_write(0x0C, RF_PKT_FIELD_4_LENGTH_12_8_8_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x08;
app_command_buf[3] = 0x19;
app_command_buf[4] = 0x00;
app_command_buf[5] = 0x00;
app_command_buf[6] = 0x00;
app_command_buf[7] = 0x00;
app_command_buf[8] = 0x00;
app_command_buf[9] = 0x00;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0x00;
spi_write(12, app_command_buf);
spi_write(0x10, (unsigned char *)RF_MODEM_MOD_TYPE_12_data);
spi_write(0x05, (unsigned char *)RF_MODEM_FREQ_DEV_0_1_data);
spi_write(0x10, (unsigned char *)RF_MODEM_TX_RAMP_DELAY_12_data);
spi_write(0x10, (unsigned char *)BCR_NCO_OFFSET_2_12_data);
spi_write(0x10, (unsigned char *)RF_MODEM_TX_RAMP_DELAY_12_data);
spi_write(0x07, (unsigned char *)RF_MODEM_AFC_LIMITER_1_3_data);
//spi_write(0x10, BCR_NCO_OFFSET_2_12_data);
spi_write(0x05, (unsigned char *)RF_MODEM_AGC_CONTROL_1_data);
spi_write(0x10, (unsigned char *)AGC_WINDOW_SIZE_12_data);
spi_write(0x0c, (unsigned char *)RF_MODEM_RAW_CONTROL_8_data);
// spi_write(0x10, (unsigned char *)AGC_WINDOW_SIZE_12_data);
// spi_write(0x05, RF_MODEM_RSSI_COMP_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x20;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x4e;
app_command_buf[4] = 0x40;
spi_write(5, app_command_buf);
spi_write(0x10, (unsigned char *)COE13_7_0_12_data);
spi_write(0x10, (unsigned char *)COE1_7_0_12_data);
spi_write(0x10, (unsigned char *)COE7_7_0_12_data);
// RF_PA
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x22;
app_command_buf[2] = 0x04;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x08;
app_command_buf[5] = POWER; // set max power
app_command_buf[6] =0x00;
app_command_buf[7] = 0x3d;
spi_write(8, app_command_buf);
spi_write(0x0B, (unsigned char *)RF_SYNTH_PFDCP_CPFF_7_data);
// header match
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x30;
app_command_buf[2] = 0x0c;
app_command_buf[3] = 0x00;
app_command_buf[4] = rf_id[0];
app_command_buf[5] = 0xff;
app_command_buf[6] = 0x40;
app_command_buf[7] = rf_id[1];
app_command_buf[8] = 0xff;
app_command_buf[9] = 0x01;
app_command_buf[10] = rf_id[2];
app_command_buf[11] =0xff;
app_command_buf[12] =0x02;
app_command_buf[13] = rf_id[3];
app_command_buf[14] = 0xff;
app_command_buf[15] =0x03;
spi_write(16, app_command_buf); // ????í·??
spi_write(6, (unsigned char *)RF_MODEM_RAW_SEARCH2_2_data);
// RF_FREQ_CONTROL_INTE_8_data[5] =uRF_FREQ_CONTROL[0];
// RF_FREQ_CONTROL_INTE_8_data[6] =uRF_FREQ_CONTROL[1];
// RF_FREQ_CONTROL_INTE_8_data[7] =uRF_FREQ_CONTROL[2];
spi_write(12, (unsigned char *)RF_FREQ_CONTROL_INTE_8_data); // set frequency
} 系统整个工作流程大概如下:
首先配置好RF收发器,使其可以正常收发数据,这包括寄存器参数配置,设备ID、中心频率、空中传输速度、中断等等配置
然后用户通过串口发送数据时,系统在DMA的控制下直接将数据存入指定发送缓冲区,并且将发送标志位置位,此时无线收发系统RF检测到有数据要发送,便会启动发送数据,当RF发送数据完成后,通过中断通知CPU数据发送完成。需要注意的是RF每次最多发送64字节 数据,当待发送数据超过64字节时,系统会自动拆包处理,接收数据过程与发送数据类似,只是方向相反。
