STM32 ADC詳細篇(基於HAL庫)

一、基礎認識

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的使用率

流程:

  1. 啟動ADC
  2. 等待EOC標誌位
  3. 讀取暫存器數據

選擇引腳,選擇未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);
    
}

測試發現,數據還是很穩的

 

本人影片號://space.bilibili.com/162091292

Tags: