方案名称: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字节时,系统会自动拆包处理,接收数据过程与发送数据类似,只是方向相反。