MDK:Keil v5.38/STM32CubeMX
MCU:STM32G431CBUx
外设:串口USART1
初始化部分
static void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ LL_USART_InitTypeDef USART_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the peripherals clocks */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = LL_GPIO_PIN_9; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_10; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_Init 1 */ /* USART1 interrupt Init */ NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),2, 1)); NVIC_EnableIRQ(USART1_IRQn); /* USER CODE END USART1_Init 1 */ USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; USART_InitStruct.BaudRate = 115200; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART1, &USART_InitStruct); LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8); LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8); LL_USART_DisableFIFO(USART1); LL_USART_ConfigAsyncMode(USART1); /* USER CODE BEGIN WKUPType USART1 */ /* USER CODE END WKUPType USART1 */ LL_USART_Enable(USART1); /* Polling USART1 initialisation */ while((!(LL_USART_IsActiveFlag_TEACK(USART1))) || (!(LL_USART_IsActiveFlag_REACK(USART1)))) { } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ }
串口接收数据结构体,设置标志位,表示空闲中断工作状态
struct RxData_Via_UART{ unsigned char RxBuffer[200]; uint8_t RxPointer; //接收数据指针 uint8_t RxIDLECounter; //当长时间(空闲一个字节)没有从串口接收到数据时,认为一帧接收结束 uint32_t RxLength; //接收数据帧长度 volatile uint8_t RxFrameEnd; //帧结束标注 uint32_t RxCmd;//四字节接收到的命令字段 }; extern struct RxData_Via_UART CMD_RxDataViaUSART1;
中断服务函数
void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ USART1_RXIdleCallback(); /* USER CODE END USART1_IRQn 0 */ /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART3_IRQn 1 */ }
接收不定长数据函数;
调试过程中发现系统上电后会自动进入一次IDLE中断,所以将使能IDLE中断写入服务函数中,保证初始化时不进入一次IDLE中断
void USART1_RXIdleCallback(void) { uint8_t res_usart1; //接收中断 if(LL_USART_IsActiveFlag_RXNE(USART1)) { res_usart1=LL_USART_ReceiveData8(USART1); CMD_RxDataViaUSART1.RxBuffer[CMD_RxDataViaUSART1.RxLength++]=res_usart1; CMD_RxDataViaUSART1.RxIDLECounter=0; LL_USART_EnableIT_IDLE(USART1); LL_USART_ClearFlag_IDLE(USART1);//发现上电会进一次IDLE中断,所以将使能中断写在这里 } //空闲中断 if(LL_USART_IsActiveFlag_IDLE(USART1)) { LL_USART_ClearFlag_IDLE(USART1); CMD_RxDataViaUSART1.RxIDLECounter=1; LL_USART_DisableIT_IDLE(USART1); } }
通过在主程序while(1)循环中检测标志位是否改变来判断是否介绍不定长数据帧,进入命令帧解析程序
while (1) { while(Timer2ReadyFlag==0); Timer2ReadyFlag = 0;//定时器中断,用于定期执行功能 /*other code*/ /* USART1 get Data CODE */ if((CMD_RxDataViaUSART1.RxIDLECounter==1)) { USART1_CmdJudge(); } }