一、基礎認識
ADC就是模數轉換,即將模擬量轉換為數字量
l 解析度,讀出的資料的長度,如8位就是最大值為255的意思,即範圍[0,255],12位就是最大值為4096,即範圍[0,4096]
l 通道,ADC輸入引腳,通常一個ADC控制器控制多個通道,如果需要多通道的話,就得進行每個通道掃描了。
l ADC DMA功能,DMA是記憶體到記憶體或記憶體到儲存的直接對映,資料不用經過微控制器處理器而直接由硬體進行資料的傳遞。方便直接將讀取的ADC值放到記憶體變數中。
ADC晶片通常有正參考電壓和負參考電壓,通常正參考電壓連線到VCC,負參考電壓連線到GND
在STM32中ADC還可以用於採集晶片的溫度、RTC供電電壓
一般來說,取樣時間越長,結果越準確,取樣時間要更具ADC的時鐘週期和ADC通道設定的取樣週期計算,如STM32F103C8T6配置的ADC時鐘週期為12MHZ,取樣週期配置的是239.5 Cycles。
ADC的轉換方式:
l 單次轉換,一次只轉換一個通道
l 連續轉換,轉換完成一個通道後立即自動執行下一個通道的轉換
l 掃描模式,開啟一次後,自動的連續讀取多個通道
ADC的三種工作方式:
l 阻塞模式(查詢模式)
l 中斷模式
l DMA模式
二、cubemx基礎配置
使用外部晶振
使用SWD除錯
時鐘配置
ADC時鐘12MHZ,取樣週期
三、 單個通道,查詢阻塞模式
缺點:佔用CPU的使用率
流程:
- 啟動ADC
- 等待EOC標誌位
- 讀取暫存器資料
選擇引腳,選擇未ADC1的通道0和設定為模擬通道
需要配置的功能,看門狗應該是可以設定上限下限的值,以產生中斷報警。
獨立模式,不可選
Data Alignment : 對齊模式,可選左對齊和右對齊
Conversion Mode:掃描轉換模式是否開啟
Continuous Conversion Mode:連續轉換模式是否開啟
Discontinuous Conversion Mode:不連續轉換模式 是否開啟
Enable Regular Conversions:是否使能轉換
Number Of Conversion:轉換的通道數
External Trigger Conversion Source:觸發開始轉換事件選擇:
可選由軟體或定時器觸發採集
Rank 編號1,如果有多個通道的話就有多個Rank,每個Rank有如下引數配置:
Channel:所選擇的通道
Sampling Time:採用週期,一個週期的時間要看ADC的時鐘,如當前時鐘圖裡設定的是12MHZ。這個時間設定越長取樣越準確,但也相對要佔用更長的取樣時間。但不管再長,這採集都是微秒級別的。
轉換函式
uint16_t ADC_Value=0; uint16_t dong_get_adc(){ //開啟ADC1 HAL_ADC_Start(&hadc1); //等待ADC轉換完成,超時為100ms HAL_ADC_PollForConversion(&hadc1,100); //判斷ADC是否轉換成功 if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)){ //讀取值 return HAL_ADC_GetValue(&hadc1); } return 0; }
呼叫
ADC_Value=dong_get_adc();
轉換的值為0-4096,對應0-3.3V
四、 三通道,查詢阻塞模式
選擇引腳
獨立模式
資料右讀取,如果是多通道,則必須開啟掃描模式(scan conversion mode)和不連續採集模式,最後一個1表示每個通道為一組
設定為3個通道
採用軟體觸發方式啟動採集
3個通道各自的引數設定
轉換函式
uint16_t ADC_Value[3]={0}; uint16_t dong_get_adc(){ //開啟ADC1 HAL_ADC_Start(&hadc1); //等待ADC轉換完成,超時為100ms HAL_ADC_PollForConversion(&hadc1,100); //判斷ADC是否轉換成功 if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)){ //讀取值 return HAL_ADC_GetValue(&hadc1); } return 0; }
使用
for(uint8_t i=0;i<3;i++){ //分別存放通道1、2、3的ADC值 ADC_Value[i]=dong_get_adc(); }
五、 ADC中斷方式多通道採集
這個可以正確讀出資料,但是順序是亂的,所以謹慎使用
第一步:啟動ADC,使能中斷
第二步:等待中斷觸發
第三步:在中斷中讀取暫存器資料
引腳設定
使能了連續轉換
開啟中斷
把優先順序設定低一點
兩個函式
#define ADC_MAX_NUM 3*5 //3組ADC,每組最多儲存5個值 uint16_t ADC_Values[ADC_MAX_NUM]={0}; uint16_t adc_value_flg=0; //啟動函式,需要在main中呼叫一次 void dong_start_adc(){ //開啟ADC1,使能中斷 HAL_ADC_Start_IT(&hadc1); } //ADC轉換完成自動呼叫函式 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ //獲取值並儲存 ADC_Values[adc_value_flg++]=HAL_ADC_GetValue(hadc); if(adc_value_flg==ADC_MAX_NUM) { adc_value_flg=0;//清零下標 } }
六、ADC DMA方式多通道採集
步驟:
l 啟動ADC
l 配置DMA緩衝區
l 讀取緩衝區資料
引腳選擇
基礎配置
開啟連續轉換模式
關閉中斷
DMA配置
mode:模式
Normal:正常模式,當一次DMA資料傳輸完後,停止DMA傳送 ,也就是隻傳輸一次
Circular: 迴圈模式,傳輸完成後又重新開始繼續傳輸,不斷迴圈永不停止
data width:資料寬度
byte:位元組,通用8位,與u8相同
word:字長,與硬體的位數相同,STM32是32位,所以對應是u32
Half Word:半個字長,所以對應是u16
Memory打鉤表示儲存ADC值的記憶體地址(陣列)會自增
程式碼也很簡單,只要在main中呼叫一次啟動函式即可
#define ADC_MAX_NUM 3*5 //3組ADC,每組最多儲存5個值 uint16_t ADC_Values[ADC_MAX_NUM]={0}; //啟動函式,需要在main中呼叫一次 void dong_start_adc(){ //啟動DMA HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Values,ADC_MAX_NUM); }
測試發現,資料還是很穩的