標准庫中打開串口的函數:
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配置串口