STM32CubeMX教程13 ADC - 单通道转换
1、準備材料
開發板(正點原子stm32f407探索者開發板V2.4)
ST-LINK/V2驅動
STM32CubeMX軟件(Version 6.10.0)
keil μVision5 IDE(MDK-Arm)
CH340G Windows系統驅動程序(CH341SER.EXE)
XCOM V2.6串口助手
1個滑動變阻器
2、實驗目標
使用STM32CubeMX軟件配置STM32F407開發板的ADC實現單通道ADC采集,具體為使用ADC1_IN5通道通過軟件/定時器觸發采集滑動變阻器上的分壓
3、ADC概述
ADC即模擬數字轉換,是將模擬電壓量轉換為數字量的一種手段,如下圖所示為STM32F407單個ADC的結構框圖(注釋1),其主要包括5個部分,分別為①ADC電源引腳、②ADC輸入引腳、③ADC觸發源、④ADC轉換規則和⑤ADC中斷觸發,下面從這五個方面分別介紹STM32F407的ADC
①ADC電源引腳有VDDA、VSSA、VREF+和VREF-四個引腳,STM32的ADC采集范圍為VREF- ≤ VIN ≤ VREF+,一般將ADC的負端參考電壓與VSSA短接然后接地,將ADC的正端參考電壓接VDDA即3.3V,這樣ADC的采集范圍就設置為0~3.3V,對于12位分辨率的ADC,其采集數字量范圍為0-4095,這樣就可以將0-3.3V的電壓映射到0-4095的數字量,使其可以相互轉化,ADC電源即參考電壓引腳具體描述如下圖所示(注釋1)
②STM32F407有三個ADC可供使用,每個ADC又擁有16個通道ADCx_IN[15:0],其中ADC1還擁有Temperature Sensor Channel、Vrefint Channel和Vbat Channel三個內部通道,Temperature Sensor Channel通道用于測量芯片內部溫度,范圍為-40℃~125℃,精度為±1.5℃,Vrefint Channel用于測量內部參考電壓,Vbat Channel用于測量備用電源電壓的一半,ADC的轉換主要依靠12位分辨率的片上模數轉換器
③注入通道和規則通道均有16個觸發源,可以選擇定時器外部源觸發/定時器比較捕獲觸發/軟件常規觸發,具體參看上圖ADC框架中的紫色框框
④ADC啟動轉換時需要按照一定通道順序轉化,該順序由規則通道和注入通道兩者共同決定,其中注入通道其數據寄存器為4*16位,因此可以同時轉換四個通道,但是規則通道的數據寄存器只有一個16位的寄存器,因此必須一個通道一個通道的轉換,每轉換完一個通道,就需要及時將轉換完成的結果從規則通道數據寄存器中讀出去,其中注入通道類似ADC通道轉換過程的中斷,如下圖所示(注釋2)
⑤ADC的中斷事件有DMA溢出、ADC轉換結束、注入轉換結束和模擬看門狗事件共四個事件,前三個中斷和其名字表述類似,當轉換結束/溢出時就會產生中斷,模擬看門狗可以設置ADC轉換值的上限和下限,當超出限制之后就會產生中斷,可以用于警報,如下表所示(注釋1)
ADC有獨立模式、二重和三重采集模式,當只有ADC1啟動時只能使用獨立模式,當ADC1/2啟動時可以使用二重采集模式,當ADC1/2/3/全部啟動時可以使用三重采集模式,本實驗只介紹獨立模式
4、實驗流程
4.0、前提知識
本實驗為ADC獨立模式單通道單次轉換模式,主要利用ADC1_IN5通道由軟件/定時器啟動ADC轉換,如果是軟件手動啟動的ADC轉換則在單次轉換模式下每次轉換完成一次之后均需要再次手動啟動ADC轉換,另外需要注意ADC在開始精確轉換之前需要一段穩定時間tSTAB,如下圖所示為ADC轉化所經過的路徑
4.1、CubeMX相關配置
請先閱讀“STM32CubeMX教程1 工程建立”實驗3.4.1小節配置RCC和SYS
4.1.1、時鐘樹配置
系統時鐘樹配置均設置為STM32F407總線能達到的最高時鐘頻率,具體如下圖所示
4.1.2、外設參數配置
本實驗需要需要初始化USART1作為輸出信息渠道,具體配置步驟請閱讀“STM32CubeMX教程9 USART/UART 異步通信”
設置TIM3通用定時器溢出時間100ms,外部觸發事件選擇更新事件,參數詳解請閱讀“STM32CubeMX教程6 TIM 通用定時器 - 生成PWM波”實驗,具體配置如下圖所示
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中ADC1,在Mode中勾選需要使用的輸入通道,本實驗為單通道轉換實驗,因此任意勾選IN0~IN15之間的任一通道均可,筆者勾選了IN5
在Configuration中對ADC1_IN5的轉換參數進行配置,下面介紹一些比較重要的參數
------------------ ADCs_Common_Settings ------------------
①Mode(模式):現在只能選擇獨立模式,當同時啟用了ADC1/2或ADC1/2/3時這里會出現多重ADC采集的模式可選
------------------------- ADC_Settings -------------------------
②Clock Prescaler(時鐘分頻):決定ADC轉換的頻率,分頻越少ADC轉換的頻率越高,最少2分頻,一個通道一次ADC轉換的總時間為N+12個ADC時鐘周期,其中N為設置的采樣次數Cycles
③Resolution(ADC轉換精度):可以選擇12/10/8/6位精度的轉換值,精度選擇不同需要的轉換時鐘周期也不同
④Data Alignment(數據對齊):由于規則數據寄存器為16位,但是最高轉換精度為12位,因此數據可以選擇以右對齊/左對齊的方式放入寄存器
⑤Scan Conversion Mode(掃描轉換模式):規則通道同時只能轉換一個通道,啟用該參數后,當規則通道中有多個通道等待轉換時其轉換完當前通道會自動轉換組內的下一個通道
⑥Continuous Conversion Mode(連續轉換模式):啟用該參數,ADC結束一個轉換立即開始一個新的轉換,與參數⑤共同啟用,則組內最后一個通道轉換完畢后會立即切換到第一個通道繼續轉換
⑦DMA Continuous Requests(DMA請求):需要在DMA Settings中添加DMA請求后,該參數才可以使能
⑧End Of Conversion Selection(結束轉換標志):選擇是一個通道轉換完就產生EOC標志,還是一個組內所有通道全部轉換完才產生EOC標志
------------------ ADC_Regular_ConversionMode------------------
⑨NumberOfConversion(轉換通道數量):常規規則通道希望轉換的通道數量
⑩External Trigger Conversion Source(外部觸發轉換源)
?External Trigger Conversion Edge(外部觸發轉換邊沿)
?Rank(規則通道排序)
------------------ ADC_Injected_ConversionMode------------------
?NumberOfConversion(注入通道轉換模式通道數量):注入通道希望轉換的通道數量
具體參數配置如下圖所示
4.1.3、外設中斷配置
在Pinout & Configuration頁面左邊System Core/NVIC中勾選ADC1/2/3全局中斷,然后選擇合適的中斷優先級即可,步驟如下圖所示
4.2、生成代碼
請先閱讀“STM32CubeMX教程1 工程建立”實驗3.4.3小節配置Project Manager
單擊頁面右上角GENERATE CODE生成工程
4.2.1、外設初始化調用流程
在生成的工程代碼主函數main()中調用了MX_ADC1_Init()函數完成了對ADC1基本參數的配置,ADC常規規則通道/注入通道等參數配置
然后在ADC初始化函數HAL_ADC_Init()函數中調用了HAL_ADC_MspInit()函數對ADC1時鐘和中斷進行了使能,對中斷優先級進行了配置,對ADC1_IN5輸入引腳做了復用操作
如下圖所示為ADC1單通道初始化的具體函數調用流程
4.2.2、外設中斷調用流程
使能ADC1/2/3全局中斷后在stm32f4xx_it.c中自動生成了TIM4的中斷處理函數ADC_IRQHandler()
ADC_IRQHandler()調用了HAL庫的ADC中斷處理函數HAL_ADC_IRQHandler(),該函數處理所有的ADC中斷事件
在ADC轉換完成之后最終調用了ADC轉換完成中斷回調函數HAL_ADC_ConvCpltCallback(),該函數為虛函數
如下圖所示為ADC1單通道轉換中斷回調的具體函數調用流程
4.2.3、添加其他必要代碼
在adc.c中重新實現ADC轉換完成中斷回調函數HAL_ADC_ConvCpltCallback(),在該函數中獲取ADC的轉換值,然后將其計算為電壓值*1000,并將這兩個值通過串口輸出,具體代碼如下圖所示
源代碼如下
/*轉換完成中斷回調*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/*定時器中斷啟動單通道轉換*/
if(hadc->Instance == ADC1)
{
uint32_t val=HAL_ADC_GetValue(&hadc1);
uint32_t Volt=(3300*val)>>12;
printf("val:%d, Volt:%d\r\n",val,Volt);
}
}
在主函數中以中斷方式啟動ADC轉換,然后啟動ADC的觸發源TIM3定時器,具體代碼如下圖所示
5、常用函數
/*啟動ADC轉換*/
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)
/*停止ADC轉換*/
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc)
/*以中斷方式啟動ADC轉換*/
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc)
/*停止ADC轉換*/
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc)
/*輪詢ADC是否轉換完畢*/
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
/*獲取ADC轉換值*/
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc)
/*ADC轉換完成中斷回調函數*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
6、燒錄驗證
6.1、實驗具體流程
“配置USART1用于輸出信息 -> 配置通用定時器TIM3實現100ms定時 -> TIM3外部觸發事件選擇為更新事件 -> 啟動ADC1的通道5并配置相關參數 -> 外部觸發轉換源選擇TIM3的外部觸發事件 -> 啟動ADC1/2/3全局中斷 -> 重新實現ADC轉換完成中斷回調HAL_ADC_ConvCpltCallback()函數 -> 在回調函數中讀取ADC轉換值并通過串口輸出 -> 在主函數中啟動定時器和ADC轉換”
6.2、實驗現象
燒錄程序,上電后打開串口,串口會每100ms傳來一次ADC采集的數據,旋轉滑動變阻器從一端到另一端,可以看到ADC采集到的值從0逐漸變為最大值4095
7、軟件觸發ADC采集
如果你希望不采用定時器觸發中斷采集的方式,而是想使用軟件手動觸發輪詢采集的方式,需要先將ADC規則轉換模式中觸發源修改為軟件觸發,然后使用HAL_ADC_Start()啟動轉換,使用HAL_ADC_PollForConversion()輪詢檢測是否轉換完成,轉換完成后使用可以HAL_ADC_GetValue()獲取轉換后的ADC值,具體參考如下圖所示
源代碼如下
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,200)==HAL_OK)
{
uint32_t val=HAL_ADC_GetValue(&hadc1);
uint32_t Volt=(3300*val)>>12;
printf("val:%d, Volt:%d\r\n",val,Volt);
}
HAL_Delay(500);
8、注釋詳解
注釋1:圖片來自STM32F4xx中文參考手冊 RM0090
注釋2:圖片來自【STM32】HAL庫 STM32CubeMX教程九---ADC_cubemx adc-CSDN博客
參考資料
STM32Cube高效開發教程(基礎篇)
更多內容請瀏覽 OSnotes的CSDN博客
總結
以上是生活随笔為你收集整理的STM32CubeMX教程13 ADC - 单通道转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神经网络优化篇:详解指数加权平均数(Ex
- 下一篇: 面试官:实际工作中哪里用到了自定义注解?