STM32CubeMX—串口空閒中斷+DMA接收

一、實驗說明

實驗平臺: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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章