STM32CubeMX Lesson 8 ─ ADC單通道與多通道讀取

   ADC (Analog-to-Digital Converter) 即數位類比轉換器,輸入類比的訊號,透過MCU轉換成數位離散訊號。STM32 ADC 為12bits的逐次逼近型。以Nucleo-L053為例,共有16個外部類比輸入。

  時間在 ADC 的轉換與存取成了很重要的一點,採樣的時間與精準度是息息相關的,根據Nyquist Sampling Theorem奈奎斯特取樣定律,採樣的頻率必須是輸入信號的兩倍頻率,才可以使採樣訊號較完整。且採樣時間也不宜過快,否則會犧牲採樣的精準度。

下文將以STM32L053R8Tx為示範,使用意法半導體官方所提供的Nucleo開發板配合自行設計的STM32L031F6Px開發板完成該實驗,使用的IDE為Keil uVision5(MDK-ARM),而STM32CubeMX的版本為6.2.1。

在進入STM32CubeMX的專案建立前,先來談談同步與非同步的差異,在 ADC 或相關事件來說有很大的不同。同步主要是排隊等待待處理事件完成後再接著處理,逐次依序;而非同步是不須等待需求完成就可以先執行其他內容。

首先在CubeMX當中的Analog選單有 ADC ,將IN0勾選,則可以看到PA0被選取為ADC_IN0。下方設定非同步並除頻32,使 ADC 的基頻為1MHz進行採樣,並選擇12-Bit的解析度,因為暫存器為16位元,因此可以選擇靠左或是靠右對齊,若是靠左(MSB)對齊,則是將低4位元皆補0,在此選擇靠右對齊。

時脈設定好之後,就可以產生程式碼到Keil。在main當中可以看見多了 ADC 的初始化設定。

需先宣告一個全域變數voltage。接著while中先開啟 ADC ,並等待 ADC 轉換,將Timeout時間設定為1ms,判斷若轉換完成,則取得 ADC 的數值。可讀取0~3.3V的電壓值,轉換為12位元的數位訊號(0~4095)。

HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc,0x01);
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc),HAL_ADC_STATE_REG_EOC)){
   voltage = HAL_ADC_GetValue(&hadc);
}

若我們要將轉換的數值由0~4095轉成電壓數值,則將0~4095 mapping到0~3300即可,因此可以在voltage變數上做scale。

HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc,0x01);
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc),HAL_ADC_STATE_REG_EOC)){
   voltage = HAL_ADC_GetValue(&hadc);
	 voltage=voltage*3300/4095;
}

透過Debug Mode可以查看全域變數voltage的數值。使用可變電阻提供輸入電壓,使用FLUKE 289量測為1.6262V,從Watch視窗觀察到數值為1669,為16.69V。

若需要使用多通道,則回到CubeMX開啟IN1或更多 ADC 輸入。

回到Keil,把voltage改為陣列,並讀取兩次即可。

HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc,0x01);
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc),HAL_ADC_STATE_REG_EOC)){
    voltage[0] = HAL_ADC_GetValue(&hadc);
		voltage[0]=voltage[0]*3300/4095;
}
HAL_ADC_PollForConversion(&hadc,0x01);
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc),HAL_ADC_STATE_REG_EOC)){
    voltage[1] = HAL_ADC_GetValue(&hadc);
		voltage[1]=voltage[1]*3300/4095;
}
		

若需要使用中斷的方式執行,可以在CubeMX開啟中斷致能,由Callback Function做ADC_GetValue即可,也歡迎嘗試看看,並一起交流!

2 則留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *