一、基礎認識
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); }
測試發現,數據還是很穩的