当前位置:   article > 正文

STM32CubeMX STM32F407ZGTx HAL USART 发送和接收配置_stm32f407 hal 串口2

stm32f407 hal 串口2

1、Connectivity选择USART1

2、Mode选择Asynchronous

3、Parameter Settings: 

     Baud Rate        115200  Bit/s

     Word Length      8  Bits

     Parity     None

     Stop  Bits      1

     Data Direction    Receive and Transmit

     Over Sampling    16  Samples

4、NVIC Settings:

      USART1 global interrupt         打√

5、生成代码

6、找到usart.c文件,定义接收数组,位置和代码如下:

      /* USER CODE BEGIN 0 */
      uint8_t RecvBuffer[1];
      /* USER CODE END 0 */

      打开usart.h文件,增加接收数组声明代码,位置和代码如下:

      /* USER CODE BEGIN Includes */
      extern uint8_t RecvBuffer[];
      /* USER CODE END Includes */

7、找到main.c文件中的MX_USART1_UART_Init(); 在其后的/* USER CODE BEGIN 2 */之后添加以下代码:
      HAL_UART_Receive_IT(&huart1,RecvBuffer,1);//使能串口1接收中断

8、接下来写串口接收中断回调函数,首先对其来龙去脉进行介绍。

      串口中断函数在stm32f4xx_it.c文件中,打开此文件,找到 void USART1_IRQHandler(void)函数内,找到                   HAL_UART_IRQHandler(&huart1)函数,右键点击函数并选择GO TO Definition Of,定位到stm32f4xx_hal_uart.c文件的      HAL_UART_IRQHandler函数体,关于所有UART的中断,都由此函数统一管理。

      函数开始处:

      errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
      if (errorflags == RESET)
      {
        /* UART in mode Receiver -------------------------------------------------*/
        if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        {
          UART_Receive_IT(huart);
          return;
        }
      }

      即若无任何错误,进入UART_Receive_IT函数,找到此函数体,为static HAL_StatusTypeDef                   UART_Receive_IT(UART_HandleTypeDef *huart),然后找到函数中的此处:

      #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
            /*Call registered Rx complete callback*/
            huart->RxCpltCallback(huart);
      #else
            /*Call legacy weak Rx complete callback*/
            HAL_UART_RxCpltCallback(huart);
      #endif /* USE_HAL_UART_REGISTER_CALLBACKS */

      可以看到回调函数HAL_UART_RxCpltCallback的调用处。 在回调函数名上右键选择GO TO Definition Of,定位到回调函数          体,发现此回调函数中的一段话:

      /* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_RxCpltCallback could be       implemented in the user file */

      意为当需要回调时,不应修改此函数,可以在用户文件中实现,即不建议在HAL库文件中实现此回调函数。

      仔细看此处的回调函数定义,前面有__weak修饰符,同其意,称其为“弱函数”,加上了__weak 修饰符的函数,编译时会首          先查看是否有用户重复定义的同名函数,若有则首先选择用户定义的函数,若没有重新定义才就会执行__weak 声明的函数。

      所以建议找到usart.c文件,拉到最底部,

      /* USER CODE BEGIN 1 */

      /* USER CODE END 1 */

      在此处去重新实现回调函数。

9、实现串口中断回调函数:

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        if (huart->Instance == huart1.Instance)
        {
            HAL_UART_Transmit(&huart1, RecvBuffer, 1, 0xFFFF);// 将收到的数据在发回去
            HAL_UART_Receive_IT(&huart1, RecvBuffer, 1);// 再次使能接收中断
        }
    }

    此处注意:函数名一定书写正确,建议之间使用__weak同名函数进行复制,否则不能正确回调。

此处需要再次使能接收中断的原因为:找到stm32f4xx_hal_uart.c中的UART_Receive_IT函数体,在if (--huart->RxXferCount == 0U)代码之后可以看到,接收完成后会关闭中断,所以若想下次继续接收,需要重新使能接收中断。

10、下载代码进行测试。

      注意。此种单个字符的发送和接收方式,当UART波特率较高时,串口中断优先级较其他中断优先级低,或因为未知代码造成接收中断进入慢,容易产生溢出错误。所以建议使用总线空闲中断来减少串口接收中断的进入次数。

     下面展示通过在中断中清除溢出错误,来提高接收准确性的方法,但此方式治标不治本。

      if(((READ_REG(huart->Instance->SR))& USART_SR_ORE) != RESET)
      {
          CLEAR_BIT(huart->Instance->SR, USART_SR_ORE);//及时清除溢出中断
      }

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号