WiFi簡單通信文章中有個通信中每次數據開頭出現亂碼的bug,經過排查發現是demo程序中的邏輯問題。
產生原因:
要了解產生原因,首先要知道HAL_UART_Receive_IT()函數的執行機制——stm32每次執行此函數是爲下一次的接收做準備,所以說在main函數前執行HAL_UART_Receive_IT(&huart1,my_re_buf1,1),當huart1接收到數據時,stm32將數據第一個字節存入my_re_buf[0]這個位置,然後執行串口接收中斷回調函數HAL_UART_RxCpltCallback()裏的HAL_UART_Receive_IT爲下一次接收做準備。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
HAL_UART_Receive_IT(&huart1,&my_re_buf1[++pt_w1],1);
}
if(huart==&huart2)
{
HAL_UART_Receive_IT(&huart2,&my_re_buf2[++pt_w2],1);
}
}
接收中斷回調函數,將數據存儲完後纔會執行這個函數。
if(htim==&htim4)
{
t4_count++;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
while(pt_r1<pt_w1 )
{
HAL_UART_Transmit(&huart2,&my_re_buf1[pt_r1++],1,1000);
}
if(pt_r1>=pt_w1)
{
pt_w1=pt_r1=0;
}
}
按照這個代碼邏輯執行並分別發送“abc”、“123”會出現下圖這種情況:
爲什麼第二次發送的字符串“123”的第一個字節‘1’會出現在數組最後面?
在第一個字符串“abc”最後一個字符‘c’接收完成後會進入接收中斷回調函數,這個時候pt_w1等於2,因此執行HAL_UART_Receive_IT(&huart1,&my_re_buf1[++pt_w1],1)後再接收的下一個字節‘1’會存在my_re_buf1[3]這個位置,雖然定時器中斷函數中將pt_w1置零,但是這並不會對HAL_UART_Receive_IT函數產生影響。
爲什麼發送第二個字符串的時候數據第一個數據時‘a’不變?
數組下標爲0的空間第一次接收到數據後,在後期執行都無法對其修改,因爲pt_w1每次賦值爲0,但是HAL_UART_Receive_IT()函數中執行++pt_w1(每次從my_re_buf[1]的位置開始存數據)。因此在正常執行程序的時候串口助手接收到板子發來的數據第一個字節都是與本次數據無關的字符。
解決方法:
if(pt_r1>=pt_w1)
{
pt_w1=pt_r1=0;
HAL_UART_AbortReceive_IT(&huart1);
HAL_UART_Receive_IT(&huart1,my_re_buf1,1);
}
將定時器中斷函數中添加這兩行代碼,程序將pt_w1和pt_r1置零之後通過HAL_UART_AbortReceive_IT()函數將串口接收功能關閉,然後通過HAL_UART_Receive_IT()函數再次打開接收中斷並把下一次接收存儲位置設爲my_re_buf[0]。