×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-06-03 发布时间:
|

串口重定向配置:


可以直接复制使用


/*************************************************

  * 函数功能: 重定向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 */




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430F5529 上手小例程2