[Arduino_AVR] 12-Analog Digital Convert

Morgan Ting
閱益如美
Published in
7 min readAug 4, 2020
Photo by Steve Harvey on Unsplash

Analog Digital Convert, ADC 類比/數位轉換在微處理器使用頻繁,本篇文章介紹 Atmega328P 的類比/數位轉換,了解轉換方式與如何設定各項 ADC 暫存器。

使用工具/材料

  1. Arduino UNO *1
  2. 10K 歐姆可變電阻 *1

ADC 是什麼 ?

在數位的世界中資料都是以 0 或 1 來表示而在人們生活的類比世界中放眼望去光線、電壓、溫度等等物理量都是連續變動的,電腦不能直接處理類比量因此需要透過轉換之後才能繼續處理,於是類比/數位轉換 (Analog Digital Convert, ADC) 就派上用場了。

Atmega328P 的 ADC

Atmega328P 微處理器有 6 個ADC 輸入通道可以使用,轉換解析度為 10-bit 也就是說把物理量切成 1024 等分,取樣頻率約為 50K ~ 200K Hz ,參考電壓可以選擇 AVCC 腳位或 VREF 腳位以及內部 1.1 V 參考電壓,Arduino UNO 上 VREF 腳位空接而 AVCC 連接到 +5 V,一般使用 AVCC 作為參考電壓是個不錯的選擇,需要注意待測物理量對應的電位不可以高於參考電位,例如一個分壓電路有10V卻用內部1.1 V 做參考電位,就好像拿一把小直尺去量大象鼻子長度一樣。

計算

  • ADC 轉換計算 ADC = Vin * VREF / 1024。
  • 反過來也可以推算量測到的電位大小 Vin = ADC * VREF / 1024 [v]

用到的暫存器

  • ADMUX : ADC Multiplexer Selection Register 用來設定參考電位來源、資料左/右對齊與轉換通道選擇。

REFS[1:0] Reference selection bit 選擇參考電位來源。

ADLAR : ADC Left Ajust Result 選擇轉換結果左/右對齊,儲存轉換結果的暫存器是 16-bit,如果要獲得 8-bit 解析度的轉換結果可以將ADLAR設「1」左對齊如此只需要讀出儲存結果的暫存器高位元組即可,如果用 10-bit 解析度做 ADC 轉換不需要做資料左對齊。

MUX[3:0] : Analog Channel Selection Bit 選擇對哪一個通道進行 ADC 轉換。

  • ADCSRA : ADC Control and Status Register A 包含了幾個 ADC 轉換的重要設定。
  1. ADEN : ADC Enable 設置「1」開啟 ADC 功能, 設置「0」關閉 ADC 功能。
  2. ADSC : ADC Start Convertion 設置「1」開使進行轉換。
  3. ADATE : ADC Auto Trigger Enable 設定使否啟動自動觸發轉換來源,若啟動則須配合 ADCSRB 選擇觸發來源。
  4. ADIF : ADC Interrupt Flag 中斷旗標,完成轉換與寫入轉換結果到資料暫存器後會設置「1」,若有使用中斷服務常式會在執行中斷服務常式後自動清零。
  5. ADIE : ADC Interrupt Enable 是否開啟中斷功能,配合SREG中斷控制位元設置「1」即可開啟中斷功能。
  6. ADPS[2:0] : ADC Prescaler Selections 選擇 ADC 除頻,注意到 ADC 取樣頻率 50K ~ 200K 的限制。
  • ADCSRB : ADC Control and Status Register B 設定觸發來源,若 ADCSRA 的ADATE 設置「1」才需要設定觸發來源。

實驗

常見的 ADC 應用在分壓器上量測電位藉由可變電阻進行電位調整,電位變化範圍為 0 ~ 5 V。透過中斷服務常式 ISR(ADC_vect) 取得轉換值後將結果呈現在 Arduino Serial Monitor 上。

相關設定如下:

  1. 設定參考電位 AVCC ,由於 Arduino UNO 的 AVCC 連接到 +5 v 因此參考電位即是 +5v。
  2. 轉換通道選擇 ADC0 ,以 Arduino UNO 的類比腳位 A0 作為輸入。
  3. 開啟 ADC 與中斷功能。
  4. 選擇除頻 128。

程式碼

  1. ISR(ADC_vect) 中斷服務常式當 ADC 轉換完成就會觸發,這時利用變數 adc_value 來儲存轉換結果,依照 Datasheet 說明要先讀取低位元組 ADCL 再讀取高位元組 ADCH。
  2. ADC_setup() 副程式主要設定 ADC 功能,包含選用 AVCC 做為參考電位、開啟 ADC 功能、開啟中斷以及設定除頻 128 ,最後再啟動 ADC 轉換。
  3. pin_setup() 副程式設定 PORTC0 作為輸入。
  4. int main() 主程式中宣告變數 adc_voltage 用來換算成電壓,在迴圈中測試 ADSC 是否清零,ADSC 暫存器會在轉換結束後自動清零因此可以拿來判斷轉換是否完成。轉換完成後將變數 adc_value 帶入算式計算出取樣的電壓,之後再利用 Arduino 的 Serial Monitor 顯示結果。_delay_ms(3000) 延遲3秒是為了能觀察轉換結果否則 Serial Monitor 會一直跑,最後再度啟動 ADC 轉換進行下一次轉換程序。

實驗結果

從 Serial Monitor 可以看到轉換結果,每停留 3 秒就進行一次轉換是為了方便觀察。

總結

Atmega328P 的 Analog Digital Convert, ADC 類比轉數位的運作與設定藉由實驗得到驗證,相關知識點如下整理:

  1. Atmega328P ADC 轉換取樣率設定在 50K ~ 200K Hz 之間,不要將除頻設定太小。
  2. Atmega328P ADC 轉換解析度是 10-bit,也可以藉由資料左對齊形成 8-bit 解析度。
  3. 參考電位可以選擇 AVCC、VREF 或內部1.1 v ,待測電壓不可高於參考電壓。
  4. 讀取轉換結果要先讀低位元組 ADCL 再讀 ADCH,這是一個 16 位元暫存器讀取方式。
  5. Atmega328P 有 6 個通道 PORTC0 ~ PORTC5,也就是 Arduino UNO 類比腳位 A0 ~ A5。
  6. 轉換程序有一次性轉換與連續性轉換,差別在於轉換會有初始化的動作而一次性轉換會從初始化進行到轉換完成因此耗用較多時間,連續性轉換則是只做一次初始化之後就持續轉換。兩種使用方式依需求而定並無優劣之分。
感謝有您
感謝讀者閱讀文章若有任何意見與想法歡迎留言指導讓知識擴大加深,秉持愛學習與愛分享的精神歡迎分享與轉載並請標註來源,謝謝您。

--

--

Morgan Ting
閱益如美

用好奇心探索世界。喜愛學習樂於分享。