STM32CubeMX教程15 ADC - 多重ADC转换
1、準備材料
開發板(正點原子stm32f407探索者開發板V2.4)
STM32CubeMX軟件(Version 6.10.0)
keil μVision5 IDE(MDK-Arm)
ST-LINK/V2驅動
野火DAP仿真器
XCOM V2.6串口助手
3個滑動變阻器
2、實驗目標
使用STM32CubeMX軟件配置STM32F407開發板的ADC實現多重ADC采集,具體為使用ADC1_IN5、ADC2_IN6實現二重ADC采集,使用ADC1_IN5、ADC2_IN6和ADC3_IN5實現三重ADC采集
3、二重ADC轉換
3.0、前提知識
STM32F407的三個ADC可以組合實現多重ADC采集,當僅僅開啟一個ADC時,該ADC只能工作在獨立模式;當同時啟動ADC1和ADC2,則以ADC1為主器件,ADC2為從器件可以工作在雙重ADC采集模式下;當同時啟動ADC1/2/3,則以ADC1為主器件,ADC2/3為從器件可以工作在三重ADC采集模式下;
在多重 ADC 模式下可實現以下6種模式
- 二/三重注入同時模式 + 規則同時模式
- 二/三重規則同時模式 + 交替觸發模式
- 二/三重注入同時模式
- 二/三重規則同時模式
- 二/三重交替模式
- 二/三重交替觸發模式
本實驗我們只介紹二/三重規則同時模式,如下圖所示為CubeMX配置中可選的所有模式
工作在多重ADC模式下的DMA請求擁有三種DMA模式,這里只介紹DMA access mode 1/2,不會涉及DMA access mode 3
二重規則同時模式ADC采集時只能選擇DMA access mode 2,三重規則同時模式ADC采集時只能選擇DMA access mode 1
下面請讀者重點理解采集完成的數據是如何通過DMA存入用戶定義好的數組中的!
當ADC工作在二重規則同時模式下,此時DMA模式為DMA access mode 2,在ADC1或ADC2轉換事件結束時,會生成一個32位DMA傳輸請求,此請求會將存儲在 ADC_CDR 32 位寄存器高位半字中的 ADC2 轉換數據傳輸到SRAM,然后將存儲在ADC_CCR低位半字中的ADC1轉換數據傳輸到 SRAM,也就是說我們只需定義一個包含一個元素的uint32_t DataBuffer[1]數組,以DMA方式啟動ADC轉換后,只需每次從高16位讀取ADC2采集的數據,從低16位讀取ADC1采集的數據即可
當ADC工作在三重規則同時模式下,此時DMA模式為DMA access mode 1,在ADC1、ADC2或ADC3轉換事件結束時,會生成三個32位DMA傳輸請求,之后會發生三次從 ADC_CDR 32 位寄存器到SRAM的傳輸:首先傳輸 ADC1 轉換數據,然后是 ADC2 轉換數據,最后是 ADC3 轉換數據,也就是說我們需定義一個包含三個元素的uint32_t DataBuffer[3]數組,其中第一個元素DataBuffer[0]表示ADC1采集的數據,第二個元素DataBuffer[1]表示ADC2采集的數據,第三個元素DataBuffer[2]表示ADC3采集的數據
上述描述如下圖所示 (注釋1)
如下圖所示為多重ADC框圖,當工作在二重ADC時不存在ADC3,ADC1/2/3三個ADC只有ADC1為主ADC,當以多重ADC工作時,只需要配置主ADC的DMA傳輸,從ADC無需設置,在啟動多重ADC采集時也只能以DMA方式啟動主ADC,從ADC以普通方式啟動即可,不能將從ADC也以DMA方式啟動,多重ADC采集的數據均會存入32位的通用規則數據寄存器中
3.1、CubeMX相關配置
3.1.0、工程基本配置
打開STM32CubeMX軟件,單擊ACCESS TO MCU SELECTOR選擇開發板MCU(選擇你使用開發板的主控MCU型號),選中MCU型號后單擊頁面右上角Start Project開始工程,具體如下圖所示
開始工程之后在配置主頁面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具體如下圖所示
詳細工程建立內容讀者可以閱讀“STM32CubeMX教程1 工程建立”
3.1.1、時鐘樹配置
系統時鐘使用8MHz外部高速時鐘HSE,HCLK、PCLK1和PCLK2均設置為STM32F407能達到的最高時鐘頻率,具體如下圖所示
3.1.2、外設參數配置
本實驗需要需要初始化USART1作為輸出信息渠道,具體配置步驟請閱讀“STM32CubeMX教程9 USART/UART 異步通信”
設置TIM3通用定時器溢出時間100ms,外部觸發事件選擇更新事件,參數詳解請閱讀“STM32CubeMX教程6 TIM 通用定時器 - 生成PWM波”實驗,具體配置如下圖所示
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中ADC1,勾選IN5通道
Mode (ADC模式):修改為Dual regular simultaneous mode only(需要啟用ADC2通道才可以選擇二重ADC采集模式)
DMA Access Mode (DMA模式):選擇DMA access mode 2
DMA Continuous Requests (DMA連續轉化請求):使能(需要先增加DMA請求才可以使能)
其他參數與“STM32CubeMX教程13 ADC - 單通道轉換”實驗均保持一致,具體配置如下圖所示
單擊Configuration中的DMA Settings選項卡對ADC1的DMA請求進行設置,所有配置均與“STM32CubeMX教程14 ADC - 多通道DMA轉換”實驗保持一致,具體配置如下圖所示
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中ADC2,勾選IN6通道,注意除 Rank 和 DMA Continuous Requests 參數外所有參數配置必須與ADC1保持一致,否則ADC采集將出現錯誤,具體配置如下圖所示
3.1.3、外設中斷配置
在Pinout & Configuration頁面左邊System Core/NVIC中勾選DMA2 Stream0 全局中斷,然后選擇合適的中斷優先級即可,具體配置如下圖所示
3.2、生成代碼
3.2.0、配置Project Manager頁面
單擊進入Project Manager頁面,在左邊Project分欄中修改工程名稱、工程目錄和工具鏈,然后在Code Generator中勾選“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后單擊頁面右上角GENERATE CODE生成工程,具體如下圖所示
詳細Project Manager配置內容讀者可以閱讀“STM32CubeMX教程1 工程建立”實驗3.4.3小節
3.2.1、外設初始化調用流程
請閱讀“STM32CubeMX教程14 ADC - 多通道DMA轉換”實驗“3.2.1、外設初始化調用流程”小節
3.2.2、外設中斷調用流程
請閱讀“STM32CubeMX教程14 ADC - 多通道DMA轉換”實驗“3.2.2、外設中斷調用流程”小節
3.2.3、添加其他必要代碼
在adc.c中重新實現ADC轉換完成回調函數HAL_ADC_ConvCpltCallback(),具體代碼如下所示
源代碼如下
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/*定時器中斷啟動DMA二重ADC轉換*/
uint32_t Volt1,Volt2;
uint32_t adcValue=DataBuffer[0];
/*從低16位取出ADC1采集數據*/
uint32_t ADC1_val=adcValue & 0x0000FFFF;
Volt1=3300*ADC1_val;
Volt1=Volt1>>12;
/*從高16位取出ADC2采集數據*/
uint32_t ADC2_val=adcValue & 0xFFFF0000;
ADC2_val= ADC2_val>>16;
Volt2=3300*ADC2_val;
Volt2=Volt2>>12;
printf("Volt1:%d, Volt2:%d\r\n",Volt1,Volt2);
}
在主函數main中啟動二重ADC轉化,一些全局變量定義及啟動源代碼如下
/*main.c全局變量定義*/
uint32_t DataBuffer[BATCH_DATA_LEN];
/*main.h變量聲明*/
#define BATCH_DATA_LEN 1
extern uint32_t DataBuffer[BATCH_DATA_LEN];
/*ADC啟動代碼*/
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1,DataBuffer,BATCH_DATA_LEN);
HAL_TIM_Base_Start(&htim3);
為什么二重ADC轉化下DMA要將數據傳輸到uint32 DataBuffer[1]?
二重ADC轉化下DMA模式為DMA access mode 2,在該模式下ADC1轉換完成的數據會傳輸到32位的 DataBuffer[0] 的低16位,而ADC2轉換完成的數據會傳輸到32位的 DataBuffer[0] 的高16位
4、常用函數
/*多重ADC以DMA方式啟動*/
HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
5、燒錄驗證
燒錄程序,單片機上電之后,串口不斷的輸出ADC1_IN5、ADC2_IN6的采集值轉化為的電壓值,筆者將兩個滑動變阻器按照ADC1_IN5、ADC2_IN6的順序,分別從一端緩慢擰到另一端,可以從串口輸出的數據看到,三個通道采集到的電壓值從最小值0慢慢變到最大3300
6、三重ADC轉換
6.1、CubeMX相關配置
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中ADC3,勾選IN5通道,所有參數與二重ADC轉換ADC2參數一致,在配置ADC1為三重ADC規則通道采集時ADC3的觸發源參數會消失,因此無需理會,具體ADC3參數配置如下圖所示
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中ADC1,將其模式修改為Triple regular simultaneous mode only,DMA模式修改為DMA access mode 1
ADC1的其他參數與二重ADC轉換時的參數一致,ADC2的配置、ADC1 DMA的配置和NVIC的設置均與二重ADC采集一致,具體ADC1參數配置如下圖所示
6.2、添加其他必要代碼
/*main.c全局變量定義*/
uint32_t DataBuffer[BATCH_DATA_LEN];
/*main.h變量聲明*/
#define BATCH_DATA_LEN 3
extern uint32_t DataBuffer[BATCH_DATA_LEN];
/*主函數中ADC啟動代碼*/
HAL_ADC_Start(&hadc2);
HAL_ADC_Start(&hadc3);
HAL_ADCEx_MultiModeStart_DMA(&hadc1,DataBuffer,BATCH_DATA_LEN);
HAL_TIM_Base_Start(&htim3);
/*adc.c中重新實現轉換完成中斷回調*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/*定時器中斷啟動DMA三重ADC轉換*/
uint32_t val=0,Volt=0;
for(uint8_t i=0;i<BATCH_DATA_LEN;i++)
{
val=DataBuffer[i];
Volt=(3300*val)>>12;
printf("ADC%d, val:%d, Volt:%d\r\n",i,val,Volt);
}
printf("\r\n");
}
為什么三重ADC轉化下DMA要將數據傳輸到uint32 DataBuffer[3]?
二重ADC轉化下DMA模式為DMA access mode 1,在該模式下ADC1轉換完成的數據會傳輸到32位的 DataBuffer[0],ADC2轉換完成的數據會傳輸到32位的 DataBuffer[1],ADC3轉換完成的數據會傳輸到32位的 DataBuffer[2]
6.3、實驗現象
燒錄程序,單片機上電之后,串口不斷的輸出ADC1_IN5、ADC2_IN6和ADC3_IN5的采集值,筆者將三個滑動變阻器按照ADC1_IN5、ADC2_IN6和ADC3_IN5的順序,分別從一端緩慢擰到另一端,可以從串口輸出的數據看到,三個通道采集到的ADC數據從最小值0慢慢變到最大4095
7、注釋詳解
注釋1:圖片來源STM32F4xx中文參考手冊
8、參考資料
主要參考STM32Cube高效開發教程(基礎篇)320頁14.6小節實驗
筆者認為該章節提到一個BUG其實是錯誤的,從ADC不應該以DMA方式啟動,也無需在STM32CubeMX生成的工程代碼中手動修改DMAContinuousRequests為ENABLE
更多內容請瀏覽 STM32CubeMX+STM32F4系列教程文章匯總貼
總結
以上是生活随笔為你收集整理的STM32CubeMX教程15 ADC - 多重ADC转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次 .NET某MES自动化桌面程序
- 下一篇: DevEco中被忽略的实用功能