ATtiny88微控制器包含一個10bit解析度的ADC模組,擁有8個通道,最大取樣率15kSPS,轉換時間14us。ATtiny88的ADC參考電壓可以來自外部,也可以使用內部1.1V的電壓源。支援自由執行模式和單次轉換模式,支援多種自動觸發源,在睡眠模式下擁有噪聲消除器。
注意:為了使用ADC模組, PRR
暫存器的 PRADC
位必須設為0。
ADC轉換結果儲存在 ADCH
和 ADCL
暫存器中,可以通過 ADLAR
位來選擇左對齊還是右對齊。為了防止在讀取ADC結果時,ADC結果發生改變,必須先讀取 ADCL
暫存器,然後再讀取 ADCH
暫存器。因為在讀取 ADCL
暫存器時,ADC轉換的結果會被鎖定,直到 ADCH
暫存器被讀取為止。
ADC有兩種模式:單次觸發模式和自由執行模式。在單次觸發模式下,向 ADSC
位寫1啟動切換,轉換完成後該位會自動清零;在自由執行模式下, ADSC
位會一直維持1。
在睡眠模式下,ADC模組可以啟用噪聲消除器減少來自CPU核心和其他I/O外設的噪聲,方法如下:
注意:進入除空閒模式及ADC噪聲減少模式外的其他睡眠模式時,不會自動關閉ADC,建議在進入這些睡眠模式時將 ADEN
位清零。
ADC轉換結果與電壓的關係如下式所示:
ATtiny88內部有一個溫度感測器,它連線到ADC8通道,在測量溫度時,必須選擇內部1.1V參考電壓。
ADC的測量電壓與溫度約為線性關係,靈敏度約為1LSB/℃,典型值如下:
為了獲得更高的精度,可以使用如下公式進行軟體校正:
其中, \(k\) 是斜率,是固定的,通常數值非常接近1, \(T_{OS}\) 是感測器偏移量。
REFS0
:參考電壓選擇。ADLAR
:ADC結果左對齊,設為0右對齊,設為1左對齊。MUX[3:0]
:模擬通道選擇。ADEN
:使能ADC。ADSC
:啟動ADC轉換,轉換結束後自動清零。ADATE
:使能ADC自動觸發。ADIF
:ADC中斷標誌位,中斷程式執行結束後清零,或者也可以寫1清零。ADPS[2:0]
:ADC分頻選擇,分頻後的頻率不要超過1MHz。ADTS[2:0]
:ADC自動觸發源選擇。ADCnD
:關閉對應ADC引腳的數位輸入緩衝。下面的程式碼展示瞭如何使用ATtiny88的ADC模組讀取ADC0通道(PC0引腳)的電壓值,程式碼檔案的整體組織結構如下:
.
├── Makefile
├── inc
│ ├── serial.h
│ └── serial_stdio.h
└── src
├── main.c
├── serial.c
└── serial_stdio.c
src/main.c
原始檔的內容如下:
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <serial_stdio.h>
static void delay(void);
int main(void)
{
cli();
stdio_setup(); // initialize stdio and redirect it to serial
ADMUX = _BV(REFS0); // external reference, align right, select channel ADC0(PC0)
ADCSRA = _BV(ADEN) | _BV(ADIF) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
// enable ADC, clear ADC interrupt flag, disable ADC interrupt, division factor = 128
DIDR0 = _BV(ADC0D); // disable digital input buffer of ADC0 pin
sei();
for (;;) {
ADCSRA |= _BV(ADSC); // start conversion
while (!(ADCSRA & _BV(ADIF))); // wait for completion
uint16_t value = ADCL; // read low byte first
value |= ADCH << 8; // then read the high
uint16_t voltage = (5000UL * value) >> 10; // convert digital value to voltage
printf("ADC0 value: 0x%04X, voltage: %dmV.\r\n", value, voltage);
ADCSRA |= _BV(ADIF); // clear flag
delay();
}
}
static void delay(void)
{
for (volatile uint32_t i = 0; i < 0x8000; i++);
}
本文來自部落格園,作者:chinjinyu,轉載請註明原文連結:https://www.cnblogs.com/chinjinyu/p/17665334.html