串口發原理
????在stm32每個串口內部有發送寄存器和發送移位寄存器。
????當調用HAL_UART_Transmit
時,cpu會將發送的數據放入發送寄存器中。發送移位寄存器會將數據轉換成電平的高低,從TX發出。
1、輪詢模式配置、發送與接收
????輪詢模式時cpu會不斷檢測發送數據寄存器的數據是否已經發送到發送移位寄存器。直到把本次數據全部發完,或者超時。 CPU會一直處于忙碌狀態。
1.1、配置
1.2、發送
char message[] = "hello world\r\n";
HAL_UART_Transmit(&huart1, (uint8_t *)message, strlen(message), 1000);
1.3、接收
uint8_t rxbuf[1];
HAL_UART_Receive(&huart1, rxbuf, 1, HAL_MAX_DELAY);
2、中斷模式
????采用中斷的串口發送接收模式,不會一直占用cpu。
2.1、配置
2.2、發送
????與輪詢的代碼區別就是在函數后加了-IT
char message[] = "hello world\r\n";
HAL_UART_Transmit_IT(&huart1, (uint8_t *)message, strlen(message));
HAL_Delay(1100);
2.3、接收
????中斷接收三字節數據:
HAL_UART_Receive_IT(&huart1, rxbuf, 3);
2.4、中斷接收串口命令控制小燈亮滅
????調用HAL_UART_Receive_IT(&huart1, rxbuf, 3)
函數后,如果串口接收到3字節的數據后就會調用HAL_UART_RxCpltCallback
表示數據接收完成,我們在這里解析數據,控制小燈亮滅即可。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{HAL_UART_Transmit_IT(&huart1, (uint8_t *)rxbuf, 3);if(rxbuf[0]=='A'){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);}if(rxbuf[0]=='B'){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);}HAL_UART_Receive_IT(&huart1, rxbuf, 3);
}
3、串口的DMA模式
????DMA (Direct Memory Acess)模式可以減少cpu的負載,幫助cpu來搬運數據。
3.1 串口DMA配置
????點擊add按鈕添加即可
3.2 DMA代碼
????DMA模式還是有中斷參與的(DMA傳輸完成中斷),代碼和普通中斷(串口接收完成中斷,串口發送完成中斷)模式的區別就是把IT改為DMA即可,如下,可以完成對小燈的控制:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{HAL_UART_Transmit_DMA(&huart1, (uint8_t *)rxbuf, 3);if(rxbuf[0]=='A'){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);}if(rxbuf[0]=='B'){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);}HAL_UART_Receive_DMA(&huart1, rxbuf, 3);
}
4、串口實現收發不定長數據
????該功能的實現主要依靠串口的空閑中斷,此中斷的觸發條件與接收的字節數無關,只有當RX引腳上無數據進入時,也就是串口從忙碌轉為空閑時才會觸發。
????所以我們可認為觸發空閑中斷時,一幀數據完成,在此中斷服務函數中編寫我們的代碼即可。
????這里HAL庫給我們提供了一個擴展函數:HAL_UARTEx_ReceiveToIdle_DMA
可以幫我們實現接收不定長數據,當由忙碌到空閑時會觸發中斷進入HAL_UARTEx_RxEventCallback
函數。
4.1、接收不定長數據代碼實現
????將接收到的數據再通過串口發送出來
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rxbuf, 100);void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{HAL_UART_Transmit_DMA(&huart1, (uint8_t *)rxbuf, Size);HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rxbuf, 10);
}
4.3、DMA傳輸過半中斷
????DMA傳輸過半中斷指的是當串口接收到指定最大長度的一半時也會觸發中斷導致進入HAL_UARTEx_RxEventCallback
函數。上面沒出現這種情況是因為我們receive時設置的參數較大100,當該值設的較小時就會出現問題。
????關閉DMA傳輸過半中斷的函數是:__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);