c++ 中断_STM32 HAL库学习系列第10篇---串口空闲中断接收不定长数据

原文首发于同名微信公号「Allen5G」,欢迎大家搜索关注!

54d17f020bf7e747bc6b24abdb85c811.png

串口重定向配置:

/************************************************* * 函数功能: 重定向c库函数printf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */int fputc(int ch, FILE *f){ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); return ch;} /** * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */int fgetc(FILE * f){ uint8_t ch = 0; while(HAL_UART_Receive(&huart1,&ch, 1, 0xffff)!=HAL_OK); return ch;}/*****************************************************/

串口空闲中断接收不定长数据

整体思路:

首先我在初始化的时候调用__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);打开了串口的接收中断。注意这个时候我还没有打开空闲中断。而是在接收到了一个byte以后打开空闲中断。

就这样会一直接收数据一帧的其他数据,一帧接受完以后就会出现一个空闲的时间。这个时候空闲中断就会发生。这时候我就把空闲中断和接收中断都关了。存在buf区的数据就是完整的一帧数据。

处理完一帧数据以后我再把串口中断打开重复上面的流程,就可以完整的接收一帧一帧的数据。同时利用空闲中断也可以省去很多的的判断。

空闲中断到底是在什么时候发生?我刚开始还理解错了,以为一上电初始化的时候打开空闲中断,假如我没有收到数据就会进入空闲中断。实际上不是这样的,空闲中断是在收到数据之后再次出现空闲的时候就会触发。所以在利用空闲中断的时候不用担心一上电就会触发了他。不过我例程里面是接收到数据以后才打开,这种情况也不用考虑了。

/*官方的中断函数*/ voidUSART1_IRQHandler(void) {  /* USER CODE BEGIN USART1_IRQn 0 */  /* USER CODE END USART1_IRQn 0 */  HAL_UART_IRQHandler(&huart1);  /* USER CODE BEGIN USART1_IRQn 1 */  /* USER CODE END USART1_IRQn 1 */ }   /*改成自己的函数*/ voidUSART1_IRQHandler(void) {  /* USER CODE BEGIN USART1_IRQn 0 */  user_Uart1Handler(); //添加自己的串口中断处理函数  /* USER CODE END USART1_IRQn 0 */  /* USER CODE BEGIN USART1_IRQn 1 */  /* USER CODE END USART1_IRQn 1 */ }   voiduser_Uart1Handler() {  if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))  {  if(uart1RxState==UART_RX_STATE_READY) //接收到一帧中的第一个字节  {  uart1RxState=UART_RX_STATE_START;  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //打开空闲中断  uart1RxCounter=0; //计数清零  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR&(uint8_t)0x00FF);  uart1RxCounter++;  }  elseif(uart1RxState==UART_RX_STATE_START)   {  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR&(uint8_t)0x00FF);  uart1RxCounter++;  }  __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);    }  if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)) //进入空闲中断  {   __HAL_UART_DISABLE_IT(&huart1,UART_IT_IDLE); //关了空闲中断  __HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE); //关了接收完成中断  uart1RxState=UART_RX_STATE_DEAL; //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开  } }

除了这里的改造外还需要在void HAL_UART_MspInit(UART_HandleTypeDef*uartHandle)这个函数里面添加一句:打开串口接收中断的函数。

/* USER CODE BEGIN USART1_MspInit 1 */  __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);   /* USER CODE END USART1_MspInit 1 */
针对STM32G4HAL库串口空闲中断接收不定数据的问题,可以按照以下步骤进行解决: 1. 开启串口空闲中断,即在初始化串口时,将USART_CR1_REG中的USART_CR1_IDLEIE位设置为1。 2. 在串口空闲中断中,通过读取USART_ISR_REG寄存器中的位USART_ISR_RXNE和USART_ISR_IDLE来判断是接收数据还是空闲中断。 3. 如果是接收数据,则读取USART_RDR_REG寄存器中的数据,并将其存储到缓冲区中。 4. 如果是空闲中断,则通过计算接收到的数据度来确定数据度,并将其存储到缓冲区中。 5. 在数据度达到预定度时,可以通过回调函数或者其他方式来通知数据接收已经完成。 下面是一个示例代码: ```c uint8_t rx_buffer[100]; uint8_t rx_counter = 0; uint8_t rx_length = 0; uint8_t rx_flag = 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USARTx) { if(rx_flag == 0) { //接收数据 if((__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) == RESET)) { rx_buffer[rx_counter++] = (uint8_t)(huart->Instance->RDR & 0x00FF); } //空闲中断 else if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) { rx_length = rx_counter; rx_counter = 0; rx_flag = 1; } } } } ``` 在上面的代码中,当接收数据时,将数据存储到缓冲区中,并将计数器rx_counter加1。当空闲中断发生时,计算接收到的数据度,并将其存储到rx_length中。在接收完成后,将rx_flag设置为1,表示数据接收已经完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值