一、實驗說明
實驗平臺:STM32F103C8T6
實驗內容:使用串口一空閒中斷結合DMA 完成不定長數據接收
STM32的串口接收數據的方式
1、輪詢接收
所謂輪詢,就是在主函數中判斷接收完成的標誌位。舉個不太恰當例子,就比如,此時你正在考試作弊,手機藏在兜裏,你的隊友再給你發答案,但是你的手機靜音,所以你不得不寫一會題看一會手機,有的時候答案已經發來了但是你此時在假裝寫,沒有看,導致你沒能及時看到答案浪費了時間(僅僅爲了舉例而已。。。。)。輪詢接收數據也是這樣。
2、中斷接收
串口接收配置爲中斷模式,當有數據收到時,進入到串口接收中斷中讀取數據。繼續上面的例子(你爲了不浪費時間且及時抄到答案,你把手機開了震動,消息一來立馬看,這是就比上面好多了,能夠及時發現消息。但是又出了一個問題,你的豬隊友,寫一個選擇給你發一次,不停的震動,完全擾亂了你的節奏)。其實也就是,串口接收數據時,一次接收一個字節,當數據量較大時,顯然這樣頻繁的進入中斷,打斷主程序,嚴重影響系統性能。
3、空閒中斷接收
空閒中斷接收,當一幀數據接收完成之後,串口會進入到空閒中斷中去,然後在空閒中斷中處理收到的數據。這種模式對處理不定長數據幀帶來很大的便利,我們不必頻繁的進入接收中斷處理數據,但是弊端也是明顯的,由於每次都要接收完一個完整的數據幀後才空閒中斷,所以當一幀數據出錯時,我們也不得不接收這幀錯誤的數據。在通訊可靠的場合,使用空閒中斷接收模式接收串口數據,將會大大提高系統的性能。
二、實驗步驟
1、基礎配置
1)、sys中,選好調試方式,例如jtag-4pin。
2)、RCC時鐘,晶振選擇。
3)、時鐘樹配置。
4)、中斷分組配置。
以上步驟可以參考串口中斷實驗。
本實驗要配置好printf函數便於演示效果
2、串口和DMA配置
1)、串口一配置。
2)、DMA選擇
3)、生成工程代碼
然後生成代碼。
4)、添加代碼
// 這裏沒有使用中斷回調函數,這樣寫更直接一點。
extern volatile uint8_t rx_len;//接收到的數據長度
extern volatile uint8_t recv_end_flag; //接收完成標誌位
extern uint8_t rx_buffer[200]; //數據緩存數組
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
temp = huart1.Instance->SR;
temp = huart1.Instance->DR;
HAL_UART_DMAStop(&huart1);
temp = hdma_usart1_rx.Instance->CNDTR;
rx_len = 200 - temp;
recv_end_flag = 1;
}
HAL_UART_IRQHandler(&huart1);
}
如下圖,在usart.c 文件中先把變量定義上,同時把支持printf的函數添加上。
//注:**這三個變量 需要在stm32f1xx_it.c和main.c中外部聲明**
volatile uint8_t rx_len=0; //接收到的數據長度
volatile uint8_t recv_end_flag=0;//接收成功標誌位
uint8_t rx_buffer[200];//緩存數組
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,rx_buffer,200);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN WHILE */
printf("DMA_TEST");
while (1)
{
if(recv_end_flag ==1)
{
printf("接收到的數據長度爲%d\r\n",rx_len);
HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);
for(uint8_t i=0;i<rx_len;i++)
{
rx_buffer[i]=0;
}
printf("\r\n");
rx_len=0;
recv_end_flag=0;
}
HAL_UART_Receive_DMA(&huart1,rx_buffer,200);
/* USER CODE END WHILE */
}
}
3 燒錄調試
代碼下載地址 提取碼 wqoo