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