- 硬件
- STM32L475
- 方案
- 使用通过修改HAL库,加入IDLE中断,实现不定长数据接收
- 参考资料
- LAT0534_UART_IDLE中断使用_接收不定长串口数据_V0.3
- cubemx配置
- 实现过程
- 首先接入接受的数据缓冲区,并设置缓冲区的大小
//Store the revceived bytes number uint32_t Rev_Size = 0; //Receive buffer uint8_t UART_RX_Buf[15];
- 然后修改HAL库的usart.c文件
- 加入extern uint32_t Rev_Size;变量声明
- 修改HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)该函数
#else //修改后的代码 CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE)); // CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));//修改前的代码 CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); #endif /* USART_CR1_FIFOEN */
- 修改HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)该函数,这里需要注意一下加入代码的位置。
__HAL_UNLOCK(huart); /* Enable the UART IDLE Interrupt*/ //加入的代码 SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); /* Enable the UART Parity Error Interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
- 修改void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)函数,光放文档里面的是 USART_SR_IDLE需要换成 USART_ISR_IDLE,NDTR换成CNDTR(具体原因看技术手册和源码)
#if defined(USART_CR1_FIFOEN) if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) || ((cr3its & USART_CR3_RXFTIE) != 0U))) #else //加入的代码 if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET)) { //Record the received bytes number Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->CNDTR; //clear the IDLE flag __HAL_UART_CLEAR_IDLEFLAG(huart); //Abord the received process HAL_UART_AbortReceive_IT(huart); return; } if (((isrflags & USART_ISR_RXNE) != 0U) && ((cr1its & USART_CR1_RXNEIE) != 0U)) #endif /* USART_CR1_FIFOEN */ { if (huart->RxISR != NULL) { huart->RxISR(huart); } return; } }
- 在main.c里面进行函数修改
- 添加中断,该中断是在开启接收后,当接收到的数据没有到达最大的接收位的时候,但是总线上停止了数据传输,总线进入空闲状态,则产生中止中断。,并进入该函数进行数据处理。
void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart) { //Print received Bytes printf("\n\r[IDLE]Received %d Bytes:",Rev_Size); for(uint16_t i = 0; i < Rev_Size; i++) { printf(" 0x%02X", UART_RX_Buf[i]); } //Re-start receiving HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15); /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file. */ }
- 该中断的解释
/** * @brief Abort ongoing Receive transfer (Interrupt mode). * @param huart UART handle. * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be * considered as completed only when user abort complete callback is executed (not when exiting function). * @retval HAL status */
- HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15);接收中断的启动函数,通过启动接收,并在中止中断里面再次开启实现循环接收。其中15是最大的可接受的数据。
- 具体使用,需要注意的是,printf函数需要自己加入printf支持。
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(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ printf("123456789\r\n"); HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
- 结果
- 添加中断,该中断是在开启接收后,当接收到的数据没有到达最大的接收位的时候,但是总线上停止了数据传输,总线进入空闲状态,则产生中止中断。,并进入该函数进行数据处理。
- 首先接入接受的数据缓冲区,并设置缓冲区的大小
STM32接收不定长数据
声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
本篇所含全部资料,点击此处留下邮箱我会发给你
资料明细:使用IDLE中断实现不定长数据接收。
觉得内容不错的朋友,别忘了一键三连哦!
全部留言
0/200
- dy-xGqRDsfq 1星期前老师,能不能发我一下资料,谢谢! 11****@****.com
- zhouspace 2022-03-27 09:07老师,能不能发我一下资料,谢谢! 14****@****.com
- 阿飞的秘术屋 2021-08-27 18:39老师,能不能发我一下资料,谢谢! 56****@****.com