HAL庫_串口接收/發送_阻塞+中斷


標准庫中打開串口的函數:

USART_Cmd(USART1, ENABLE);

標准庫中打開中斷的函數:需要單獨設置被打開的中斷的類型

USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);    

在HAL中,打開串口和中斷合並成了一個函數:發送就打開發送中斷,接收就打開接收中斷

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

標准庫和HAL庫中都有阻塞式發送接收和非阻塞式發送接收(中斷或DMA)

標准庫中阻塞式發送和接收函數

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)

HAL庫中阻塞式發送和接收

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

阻塞式發送和接收在使用上都沒有太大的差別,發送就等着發送完,HAL中阻塞式發送函數的第4個參數Timeout,可以設置一個超時時間,超時后沒發完就不再阻塞。

接收沒有差別。超時時間根據systic的計數頻率和計數值確定

 

中斷式發送和接收

先說接收

標准庫中接收的話需要自己在中斷函數里面判斷中斷類型,清標志位

在HAL中void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);這個庫函數幫我們完成了中斷類型判斷和清除標志位,我們只需要在具體的函數中寫邏輯即可。

上面這個庫函數判斷出不同的類型,然后調用不同的回調函數,我們處理接收中斷回調函數HAL_UART_TxCpltCallback即可。

全部回調函數如下:

1 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
2 void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
3 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
4 void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
5 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
6 void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart);
7 void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart);
8 void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);

發送和接收中斷的一些問題:

HAL_UART_Transmit_IT(huart11,datass,2 ); 
HAL_UART_Receive_IT(&huart1,recivedatass,3);

關於中斷式發送和接收,可以看到這兩個函數的第3個參數,是設置要接收多少個、發送多少個字節。發送的中斷就不用說了,有個全部發送完成和發送一半。

接收的話,每接收到一個字節就會產生一個接收中斷,但是我們可能需要接收完3個字節的數據才想處理一次。HAL_UART_IRQHandler內部做了判斷,當接收到3個字節后才會調用一個回調函數 HAL_UART_RxCpltCallback

 

實驗:使用串口中斷每接收到3個字節后,在中斷回調函數中使用串口中斷式發送2個字節的字符串“TR”,當發送完成后,在發送完成中斷中翻轉LED。

main.c :打開串口並開啟接收中斷

    uint8_t datass[100] ="TR";
    uint8_t recivedatass[100]="";

 HAL_UART_Receive_IT(&huart1,recivedatass,3);
 
 HAL_Delay(2000);

接收中斷回調函數

void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart11)
{
    HAL_UART_Transmit_IT(huart11,datass,2 );
 
    HAL_UART_Receive_IT(&huart1,recivedatass,3);//再次打開接收中斷,以便下次繼續接收
}

發送完成中斷回調函數

void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart11)
{
    
    HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
    //HAL_UART_Transmit_IT(&huart1,datass,2);
}

遇到的問題:

接到幾次就會卡死,后來發現是HAL_UART_IRQHandler函數內部每接收到一個字節就會關閉接收中斷,如果我們還要繼續接收,則需要在接收中斷回調函數中打開接收中斷。

而在發送完成中斷中不用打開發送中斷。打開了會死循環發送。

 

CUbeMx配置串口

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM