好久沒寫博客了,最近挺忙的,近來有些好玩的實作,網上的資料并不是非常詳細,打算慢慢寫下來,希望別人能少走一點彎路, 因為希望提高ADC的采樣率,這次我試著實作了一下三重ADC交替采樣+DMA搬運至記憶體+TIM的TRGO觸發采樣(環境是stm32cubemx 6.5.0和keil 5)
首先打開cubemx進行基礎設定(設定時鐘樹,RCC,SYS)
然后設定ADC1(下圖為具體設定,僅供參考)
此處我們將ADC_Mode設定為Triple regular simultaneous mode only,并打開DMA連續請求(為了使DMA能夠填滿陣列,按照我們的預期作業)
外部觸發源設定為TIM2的TRGO

由于已經設定了ADC模式,ADC2和ADC3是跟隨ADC1的,所以他們的模式是不能改變的,和ADC1一樣設定就可以了
接下來我們設定DMA,記住要設定成circular模式,不然他就只會傳輸一次,選擇一次傳輸Half Word,從外設搬運到記憶體

主要的設定就這些,串口的初始化已經省略了,后面我們將用串口重定向列印資料至串口(詳見我之前的博客串口重定向發送和接收)
現在我們只需要生成代碼,打開工程
這里有個小細節:DMA和ADC的初始化順序不能錯了,要先初始化DMA再初始化ADC(其實用到DMA傳輸資料的外設都要在DMA初始化之后再進行初始化,因為不先初始化DMA的話,在初始化其他外設時,當配置到DMA相關的設定時會出現錯亂,導致外設無法正常作業,比如ADC就會傳輸資料失敗,但是DMA一直是處于busy狀態)
下面我們進行垃圾核心代碼的撰寫
我的初始化順序(僅供參考)
1 MX_GPIO_Init(); 2 MX_DMA_Init(); 3 MX_ADC1_Init(); 4 MX_ADC2_Init(); 5 MX_ADC3_Init(); 6 MX_DAC_Init(); 7 MX_TIM2_Init(); 8 MX_USART1_UART_Init();
主函式當中撰寫的代碼如下:
1 HAL_ADC_Start(&hadc1); 2 HAL_ADC_Start(&hadc2); 3 HAL_ADC_Start(&hadc3);//啟動ADC 4 HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t *)ADC_value,3000); 5 HAL_TIM_Base_Start(&htim2);//啟動TIM2,用于觸發ADC采樣
對于資料的處理,我更傾向于寫在回呼函式里面
1 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) 2 { 3 int i; 4 for(i = 0;i < 1000;i++) 5 { 6 printf("%f,%f,%f\n",ADC_value[3 * i] * 3 / 4096.0,ADC_value[3 * i + 1] * 3 / 4096.0,ADC_value[3 * i + 2] * 3 / 4096.0); 7 } 8 return; 9 }
我們再編譯,燒錄程式, 至此,我們就可以實作ADC三重交替采樣了
/*------------------------------------------------------------------------分割線------------------------------------------------------------------------*/
我思來想去感徑訓是在回呼函式里面改變一個標志位就可以了,把這么一大段處理放進去不太好,容易出現中斷嵌套等我們不希望出現的現象
盡量把處理的步驟寫到函式里面去執行,只需通過判斷標志位即可達到同等效果
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/500719.html
標籤:其他
