天天看點

STM32CubeMX STM32F407ZGTx HAL USART 發送和接收配置

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檔案,定義接收數組,位置和代碼如下:

      uint8_t RecvBuffer[1];

      打開usart.h檔案,增加接收數組聲明代碼,位置和代碼如下:

      extern uint8_t RecvBuffer[];

7、找到main.c檔案中的MX_USART1_UART_Init(); 在其後的之後添加以下代碼:

      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)

      {

        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)

            huart->RxCpltCallback(huart);

      #else

            HAL_UART_RxCpltCallback(huart);

      #endif

      可以看到回調函數HAL_UART_RxCpltCallback的調用處。 在回調函數名上右鍵選擇GO TO Definition Of,定位到回調函數          體,發現此回調函數中的一段話:

      意為當需要回調時,不應修改此函數,可以在使用者檔案中實作,即不建議在HAL庫檔案中實作此回調函數。

      仔細看此處的回調函數定義,前面有__weak修飾符,同其意,稱其為“弱函數”,加上了__weak 修飾符的函數,編譯時會首          先檢視是否有使用者重複定義的同名函數,若有則首先選擇使用者定義的函數,若沒有重新定義才就會執行__weak 聲明的函數。

      是以建議找到usart.c檔案,拉到最底部,

      在此處去重新實作回調函數。

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);//及時清除溢出中斷

      }

繼續閱讀