日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

stm32cubemx adc_STM32CubeMX__Exp5_ADC1_2CH_DMA_TIM3_Trig__简明指导文件__jyb

發布時間:2025/3/15 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32cubemx adc_STM32CubeMX__Exp5_ADC1_2CH_DMA_TIM3_Trig__简明指导文件__jyb 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用定時器TIM3觸發DMA方式的雙通道ADC定時采樣:

拷貝STM32CubeMX工程文件LED_Flash_PC12.ioc,修改為:Exp5_ADC1_2CH_DMA_TIM3_Trig.ioc

(1)配置ADC1的通道和參數

配置ADC通道參數

(2)配置ADC1的DMA

①通過點"Add"按鈕,添加ADC1---DMA1 Channel 1。選擇后ADC1后自動添加其DMA通道。

② DMA Request Settings:配置結果如下圖所示。

Mode:Circular;設置DMA的傳輸模式為連續不斷的循環模式。若只想訪問一次后就不要訪問了(或按指令操作來反問,也就是想要它訪問的時候就訪問,不要它訪問的時候就停止),可以設置成通用模式:DMA_Mode_Normal。

Peripheral:Increment Address:不勾選。如果DMA通道有外設,可以通過DMA通道將數據輸出。

Memory:勾選。DMA通過地址遞增方式將數據存儲到內部數據存儲器中。

  Data Width:Word。Word是32bits,Half Word是16bits。選擇要與ADC轉換結果的數據寬度相同。

配置ADC的DMA

(3)配置ADC1的NVIC:不做任何選擇,按默認即可,如下圖所示。DMA1中斷已經默認強制選擇了。我們在這里是采用TIM3的定時溢出事件觸發ADC轉換的,在DMA中斷服務程序中讀取數據,所以不需要使能ADC的中斷。

配置ADC的NVIC

(4)"User Constants"和"GPIO Settings"按默認即可。

(5)配置TIM3。配置結果如下圖所示。

配置TIM3

用其更新事件作為TRGO觸發ADC。用鼠標點"Pinout & Configuration"點"Timers"點"TIM3""Mode"選項卡中,"Clock Source"選"Internal Clock""TIM3 Mode and Configuration"的"Configuration"菜單欄中,點"Parameter Settings""Trigger Output(TRGO)Parameters"下拉選項中,"Trigger Event Selection"選擇"Update Event"。這樣就為ADC的啟動提供觸發信號。72MHz的時鐘信號經過(7199+1)和(39999+1)分頻后,頻率為0.25Hz,其周期為4秒,也就是說每4秒觸發一次ADC轉換。

(6) 為了觀察程序運行,添加PC12接LED。

(7) ADC的時鐘為12MHz

配置ADC的時鐘

(8)配置完成,保存STM32CubeMX工程文件,點擊"GENERATE CODE",生成代碼工程框架并打開。

添加代碼

(1) 在main.c里面添加ADC轉換的相關變量

/* USER CODE BEGIN PV */

uint32_t ADC_Value[10]; //通道IN6、IN7采樣5次的值

uint8_t i,j,ADC_DMA_ConvCpltFlag=0; //ADC1_DMA方式轉換結束標志

uint32_t IN6_Value[5],IN7_Value[5]; //從DMA轉換值中分離IN6和IN7的值

uint32_t IN6_AverageValue,IN7_AverageValue; //IN6和IN7的平均值

/* USER CODE END PV */

(2)開啟定時器TIM3,通過TIM3啟動ADC。開啟DMA方式的ADC1

/* USER CODE BEGIN 2 */

HAL_TIM_Base_Start(&htim3); //啟動TIM3基本定時功能,定時到觸發ADC啟動

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 10); //啟動DMA方式的ADC轉換,采樣到10個之后觸發DMA方式的ADC中斷

/* USER CODE END 2 */

(3)在中斷回調函數中做簡單的數據處理

/* USER CODE BEGIN 4 */

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle) //DMA方式的ADC中斷回調函數

{

// HAL_TIM_Base_Stop(&htim3);

// HAL_ADC_Stop_DMA(&hadc1);

j=0; //將采樣到的10個ADC轉換值分離給IN6和IN7

for(i = 0; i < 10;i++)

{

IN6_Value[j]=ADC_Value[i];

i++;

IN7_Value[j]=ADC_Value[i];

j++;

}

ADC_DMA_ConvCpltFlag=1; //置DMA方式的ADC轉換結束標志

}

/* USER CODE END 4 */

(4)在主程序中做復雜些的數據處理

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

HAL_GPIO_TogglePin(GPIOB,LED1_Pin); //用LED1指示主程序運行

HAL_Delay(200); //每200msLED1閃爍一次

if(ADC_DMA_ConvCpltFlag==1) //判斷DMA方式的ADC轉換結束了沒有

{

IN6_AverageValue=0; //一次DMA方式的ADC轉換結束,計算兩個通道的平均值

IN7_AverageValue=0;

for(i =0;i <5;i++)

{

IN6_AverageValue+=IN6_Value[i];

IN7_AverageValue+=IN7_Value[i];

}

IN6_AverageValue=IN6_AverageValue/5;

IN7_AverageValue=IN7_AverageValue/5;

// HAL_TIM_Base_Start(&htim3);

// HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 10);

ADC_DMA_ConvCpltFlag=0; //清除轉換結束標志,以便判斷下次中斷

}

}

/* USER CODE END 3 */

在啟動了TIM3定時器后,TIM3計數溢出事件將觸發ADC啟動轉換,ADC轉換按照規定的DMA方式進行,先轉換IN6通道,再轉換IN7通道,這就是掃描轉換各個通道一次,等到下一次TIM3溢出事件再次啟動ADC轉換,這樣反復5次,轉換得到10個ADC轉換值,將觸發DMA中斷,在DMA中斷回調函數中做簡單的數據處理,置DMA中斷標志。在主程序中,通過LED1指示主程序的運行情況,檢測到DMA中斷后對采樣到的數據做處理,并復位DMA中斷標志。

這里你也許會問,DMA中斷為什么是void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)這個函數呀?這個函數不是當開啟AD的中斷的時候才調用的嗎? 對,是這樣的。我們仔細分析一下開啟AD的DMA中斷函數,在里面就會發現這個函數也在啊。在main.c中找到HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 10);,在HAL_ADC_Start_DMA上點鼠標右鍵,跟蹤其定義可以找到函數:HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length),該函數中有一句:

/* Set the DMA transfer complete callback */

hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;

DMA傳輸完成,自動調用名字為ADC_DMAConvCplt函數,在ADC_DMAConvCplt上點鼠標右鍵,跟蹤其定義,進入到void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)函數里面可以找到

/* Conversion complete callback */

#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)

hadc->ConvCpltCallback(hadc);

#else

HAL_ADC_ConvCpltCallback(hadc);

#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */

發現DMA方式的ADC轉換,按照開辟的數據區大小,轉換結果將數據區填滿后,轉換完成,還是調用HAL_ADC_ConvCpltCallback(hadc); 這個回調函數,在回調函數中對數據做初步處理。今后用到AD,不論是中斷方式還是DMA方式,都可以直接調用這個回調函數了,不用再糾結了。需要注意的是,中斷方式的ADC在回調函數中需要通過uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle); 獲得ADC的轉換值,而DMA方式的ADC,則通過DMA直接將轉換值存放在用數組名開辟的片內RAM中,當數組存滿數據后會觸發DMA中斷,在回調函數中直接從數組中取轉換結果即可。

以上程序是連續啟動ADC轉換的,如果要想控制這個轉換過程,可以通過以下語句實現:

HAL_TIM_Base_Stop(&htim3); //關閉定時器,停止溢出事件觸發ADC

HAL_ADC_Stop_DMA(&hadc1); //停止DMA方式的ADC轉換

HAL_TIM_Base_Start(&htim3); //啟動定時器,定時溢出事件觸發ADC

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 10); //啟動DMA方式的ADC轉換,得到10個轉換值后中斷

第三步:編譯、下載、運行

為觀察到變化效果,可以先將PA6(IN6)和PA7(IN7)懸空,此時測量到是干擾。程序運行后,可以看到LED持續閃爍,表明主程序一直在運行,不用設置斷點,全速運行程序,在觀察窗口中添加變量ADC_Value、IN6_Value、IN7_Value、IN6_AverageValue、IN7_AverageValue、i、j,可以看到,每隔4秒鐘ADC_Value的值以組(IN6和IN7)為單位變化一次,因為TIM3定時4秒,所以每隔4秒觸發一次ADC轉換,轉換結果通過DMA送給ADC_Value數組。需要20秒后,ADC_Value填滿,觸發DMA中斷,IN6_Value和IN7_Value在中斷回調函數中得到各自的轉換結果,如下圖所示。也可以將PA6和PA7接GND、3.3V,做進一步觀察。

觀察運行結果

總結

以上是生活随笔為你收集整理的stm32cubemx adc_STM32CubeMX__Exp5_ADC1_2CH_DMA_TIM3_Trig__简明指导文件__jyb的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。