Informacje dodatkowe     Ciekawostki o 8-bitowych mikrokontrolerach AVR


Od kilku lat programuję 8-bitowe mikrokontrolery AVR i przez ten czas zdobyłem trochę wiedzy
na ich temat. Poniżej znajduje się kilka ciekawostek o tych układach.


1. Rozpoznawanie wersji (rewizji)
2. Stany przejściowe wejść/wyjść
3. Wyłączanie zbędnych modułów
4. Pomiar rezystancji wewnętrznych rezystorów podciągających
5. Pomiar częstotliwości wewnętrznego zegara taktującego
6. Pomiar napięcia wewnętrznego źródła odniesienia
7. Maksymalny prąd wewnętrznych diod zabezpieczających
8. Wewnętrzny oscylator PLL
9. Programowa instrukcja XCHG (eXCHanGe two registers)

1. Rozpoznawanie wersji (rewizji)

Wersja (rewizja) mikrokontrolera jest oznaczana jedną literą (zgodnie z porządkiem liter w alfabecie: "Rev. A" - oznacza
pierwszą, "Rev. B" - drugą/nowszą wersję mikrokontrolera, itd.). Poznanie wersji posiadanego mikrokontrolera jest
czasem potrzebne, bo w niektórych występują błędy (zwykle drobne), które są usuwane w nowszych wersjach układu.
Błędy te są opisane w rozdziale "Errata" noty katalogowej danego modelu mikrokontrolera.
Wersja mikrokontrolera zwykle jest podana w postaci napisu na spodzie jego obudowy DIP. Nowe układy mają ozna-
czenie w formacie 354XXZ lub 355XXZ, a starsze 196XXZ, gdzie: XX - numer układu (może zawierać literę), Z - wersja
układu (litera). W przypadku mikrokontrolerów w obudowach DIP8 nie ma na nich zbyt dużo miejsca, dlatego wersję
układu oznacza się jedną literą (pierwszą w drugiej linii).
Na innych rodzajach obudów, wersja mikrokontrolera może nie być podana wprost i aby ją ustalić, należy kontaktować
się z pomocą techniczną firmy Atmel/Microchip. Można też próbować określić wersję na podstawie 4-cyfrowego kodu,
oznaczającego datę produkcji układu (YYWW, gdzie: YY - dwie ostatnie cyfry roku; WW - numer tygodnia), ale nie jest
to pewny sposób.

Na poniższych zdjęciach są wyróżnione na czerwono litery, które oznaczają wersję danego modelu mikrokontrolera.


ATtiny85 (20PU)

ATmega48 (20PU)

ATmega32A (PU)


2. Stany przejściowe wejść/wyjść

Po włączeniu/resecie mikrokontrolera wszystkie jego piny są ustawione jako wejścia (IN) w stanie nieustalonym, czyli
wysokiej impedancji (Z). Aby zmniejszyć pobór prądu i wyeliminować zakłócenia, które trafiają przez takie piny do mi-
krokontrolera, należy wymusić na nich ustalony stan logiczny (niski/wysoki). Najprościej można to zrobić programowo,
włączając na tych pinach wewnętrzne rezystory podciągające Rpu (pull-up) lub ustawiając je, jako wyjścia (OUT) z nis-
kim/wysokim stanem logicznym (L/H). Jednak te sposoby nie działają podczas i po włączeniu/resecie mikrokontrolera.
Rozwiązaniem, które zawsze działa jest dodanie na tych pinach zewnętrznych rezystorów, podłączonych na stałe do
plusa Vcc (pull-up) lub masy GND (pull-down) zasilania. Nie jest zalecane podłączanie nieużywanych pinów bezpo-
średnio do plusa lub masy zasilania, gdyż może to spowodować przepływ znacznego prądu, jeśli dany pin zostanie
przypadkowo ustawiony jako wyjście.
Do programowej konfiguracji pinów w danym porcie PX, służą bity DDXn w rejestrze DDRX (Data Direction Register
port X), bity PORTXn w rejestrze PORTX (PORT X data register) oraz bit PUD w rejestrze MCUCR (MicroController
Unit Control Register), gdzie: X - litera oznaczająca dany port (np. A, B, C, D), n - numer konkretnego pinu w porcie X
(0-7). Zapisanie "1" do bitu PUD w rejestrze MCUCR, spowoduje całkowite wyłączenie rezystorów podciągających
(pull-up) na wszystkich pinach każdego portu mikrokontrolera.
Poniższa tabela przedstawia konfigurację danego pinu PXn w zależności od wartości, odpowiadających mu bitów
DDXn/PORTXn w rejestrach DDRX/PORTX oraz bitu PUD w rejestrze MCUCR.

DDXn
 (DDRX) 
PORTXn
 (PORTX) 
PUD
 (MCUCR) 
 Konfiguracja 
pinu PXn
00XIN Z
010IN H (pu)
011IN Z
10XOUT L
11XOUT H
IN / OUT - pin skonfigurowany jako wejście/wyjście, (pu) - włączony rezystor podciągający,
L / H / X - niski/wysoki/dowolny stan logiczny, Z - stan nieustalony/wysokiej impedancji (Hi-Z).

Ponieważ o konfiguracji danego pinu PXn decydują 2 bity w rejestrach DDRX/PORTX, a jedną instrukcją w ciągu jed-
nego cyklu zegarowego można zmienić wartość tylko jednego z tych bitów, to w tym czasie na konfigurowanym pinie
PXn może pojawić się przejściowy stan logiczny. Poniższa tabela przedstawia, jakie stany przejściowe występują na
pinie PXn w zależności, od kolejności zmian wartości bitów DDXn/PORTXn.

Początkowa konfiguracja
 pinu PXn [DDXn:PORTXn] 
Docelowa konfiguracja pinu PXn [DDXn:PORTXn]
IN Z [0:0] IN H (pu) [0:1]  OUT L [1:0] OUT H [1:1]
IN Z [0:0]-IN H (pu) [0:1]OUT L [1:0] IN H (pu) [0:1] 
OUT H [1:1]
OUT L [1:0]
OUT H [1:1]
IN H (pu) [0:1]IN Z [0:0]-OUT H [1:1]
OUT L [1:0]
IN Z [0:0]
OUT L [1:0]
OUT H [1:1]
OUT L [1:0]IN Z [0:0]OUT H [1:1]
IN H (pu) [0:1]
IN Z [0:0]
IN H (pu) [0:1]
-OUT H [1:1]
OUT H [1:1] IN H (pu) [0:1] 
IN Z [0:0]
OUT L [1:0]
IN Z [0:0]
IN H (pu) [0:1]OUT L [1:0]-
IN / OUT - pin skonfigurowany jako wejście/wyjście, (pu) - włączony rezystor podciągający,
L / H / X - niski/wysoki/dowolny stan logiczny, Z - stan nieustalony/wysokiej impedancji (Hi-Z).

3. Wyłączanie zbędnych modułów

Wyłączenie nie potrzebnych peryferiów mikrokontrolera nie tylko zmniejsza pobór prądu, ale redukuje też poziom ge-
nerowanych przez nie szumów, co ma duże znaczenie np. przy wykonywaniu pomiarów wewnętrznym przetwornikiem
analogowo-cyfrowym ADC.
Nowsze mikrokontrolery mają rejestr PRR (Power Reduction Register), który służy do zatrzymywania taktowania nie-
używanych modułów mikrokontrolera (przetwornika ADC, timerów/liczników, czy interfejsów komunikacyjnych TWI/SPI/
USART). W tym celu, należy zapisać "1" do bitu w rejestrze PRR, który odpowiada zatrzymywanemu modułowi.
Niektóre modele z większą liczbą peryferiów mają dwa takie rejestry PRR0 i PRR1 (np. ATmega1284).
Po zatrzymaniu taktowania aktualny stan modułu nie zmienia się, a jego rejestry przestają być dostępne do odczytu/
zapisu. Wszystkie zasoby, których używał zatrzymany moduł pozostają zajęte. Dlatego przed zatrzymaniem taktowania
danego modułu, powinno się go najpierw wyłączyć.

Poniższy rysunek przedstawia poszczególne moduły mikrokontrolera - te oznaczone ikoną "Power"
można wyłączyć/zatrzymać według zamieszczonych opisów.


 
Aby wyłączyć timer WDT (Watch-Dog Timer), należy
ustawić wartość fuse bitu WDTON na "1" oraz zapi-
sać "0" do bitów: WDRF w rejestrze MCUSR (Micro-
Controller Unit Status Register), WDE i WDIE w re-
jestrze WDTCR (WatchDog Timer Control Register)
- według procedury opisanej w nocie katalogowej.
Domyślnie timer WDT jest wyłączony po włączeniu/
resecie fabrycznie nowego mikrokontrolera.

Aby wyłączyć moduł monitorowania napięcia zasi-
lania BOD (Brown-Out Detector), należy ustawić
wartość fuse bitów BODLEVEL2-0 na "1".
Domyślnie moduł ten jest wyłączony w fabrycznie
nowym mikrokontrolerze.

Aby wyłączyć moduł debugowania dW (debugWire),
należy ustawić wartość fuse bitu DWEN na "1".
Domyślnie moduł ten jest wyłączony w fabrycznie
nowym mikrokontrolerze.

Aby wyłączyć przetwornik analogowo-cyfrowy ADC
(Analog to Digital Converter), należy zapisać "0" do
bitu ADEN w rejestrze ADCSRA (ADC control and
Status Register A) - spowoduje to całkowite odłą-
czenie jego napięcia zasilania. Dopiero później
można zapisać "1" do bitu PRADC w rejestrze PRR (jeśli mikrokontroler go posiada) - spowoduje to całkowite odłą-
czenie jego zegara taktującego. W niektórych modelach zatrzymanie zegara przetwornika ADC, powoduje jednocze-
sne zatrzymanie pewnych obwodów komparatora analogowego, który nie może być używany w takiej sytuacji (np.
ATtiny25/45/85, ATtiny261/461/861). Domyślnie przetwornik ADC jest wyłączony po włączeniu/resecie mikrokontrolera,
ale jest taktowany zegarem.

Aby wyłączyć komparator analogowy AC (Analog Comparator), należy zapisać "1" do bitu ACD w rejestrze ACSR
(Analog Comparator control and Status Register) - spowoduje to całkowite odłączenie jego napięcia zasilania.
Domyślnie komparator analogowy jest włączony po włączeniu/resecie mikrokontrolera.

Aby wyłączyć cyfrowy bufor wejściowy DIB (Digital Input Buffer) na pinie ADCx przetwornika analogowo-cyfrowego
lub ANx komparatora analogowego, należy zapisać "1" do odpowiadającego mu bitu ADCxD lub ANxD w rejestrze
DIDR0/1 (Digital Input Disable Register 0/1). W przypadku modeli, w których drugą funkcją pinu AREF jest tylko funkcja
cyfrowa, rejestr DIDR0 zawiera dodatkowo bit AREFD (np. ATtiny261/461/861).
Jeśli na wejściowy pin analogowy jest podawany sygnał o napięciu zbliżonym do wartości Vcc/2, to wtedy włączony
na tym pinie cyfrowy bufor wejściowy pobiera znaczny prąd. Dlatego, aby zmniejszyć pobór prądu cyfrowe bufory
wejściowe, powinny być zawsze wyłączone na wejściach analogowych. Domyślnie cyfrowe bufory wejściowe są
włączone po włączeniu/resecie mikrokontrolera.

Aby wyłączyć wewnętrzne źródło napięcia odniesienia IBRV (Internal Bandgap Reference Voltage), należy wyłączyć
moduł BOD (fuse bity BODLEVEL2-0=1) i przetwornik ADC (bit ADEN=0 w rejestrze ADCSRA) oraz odłączyć to
źródło od komparatora analogowego (bit ACBG=0 w rejestrze ACSR). Domyślnie wewnętrzne źródło napięcia
odniesienia jest wyłączone po włączeniu/resecie fabrycznie nowego mikrokontrolera.

Aby wyłączyć timer/licznik TCx (Timer/Counter x), należy zapisać "0" we wszystkich bitach CSx w rejestrze TCCRx
(Timer/Counter Control Register x) - spowoduje to zatrzymanie działania licznika. Dopiero później można zapisać
"1" do bitu PRTIMx w rejestrze PRR (jeśli mikrokontroler go posiada) - spowoduje to całkowite odłączenie jego
zegara taktującego. Domyślnie timer/licznik TCx jest wyłączony po włączeniu/resecie mikrokontrolera, ale jest
taktowany zegarem.

Aby wyłączyć moduł SPI (Serial Peripheral Interface), należy zapisać "0" do bitu SPE w rejestrze SPCR (SPi Control
Register) - spowoduje to zatrzymanie działania interfejsu SPI. Dopiero później można zapisać "1" do bitu PRSPI w re-
jestrze PRR (jeśli mikrokontroler go posiada) - spowoduje to całkowite odłączenie jego zegara taktującego. Niektóre
modele zamiast modułu SPI mają moduł USI, który może pracować w trybie SPI (np. ATtiny25/45/85, ATtiny261/461/
861). Domyślnie moduł ten jest wyłączony po włączeniu/resecie mikrokontrolera, ale jest taktowany zegarem.

Aby wyłączyć moduł TWI (Two-Wire serial Interface), należy zapisać "0" do bitu TWEN w rejestrze TWCR (TWi Control
Register) - spowoduje to zatrzymanie działania interfejsu TWI. Dopiero później można zapisać "1" do bitu PRTWI w re-
jestrze PRR (jeśli mikrokontroler go posiada) - spowoduje to całkowite odłączenie jego zegara taktującego. Niektóre
modele zamiast modułu TWI mają moduł USI, który może pracować w trybie TWI (np. ATtiny25/45/85, ATtiny261/461/
861). Domyślnie moduł ten jest wyłączony po włączeniu/resecie mikrokontrolera, ale jest taktowany zegarem.

Aby wyłączyć moduł USI (Universal Serial Interface), należy zapisać "0" do wszystkich bitów w rejestrze USICR (USI
Control Register) - spowoduje to zatrzymanie działania interfejsu USI. Dopiero później można zapisać "1" do bitu
PRUSI w rejestrze PRR (jeśli mikrokontroler go posiada) - spowoduje to całkowite odłączenie jego zegara taktującego.
Moduł USI może pracować w trybie SPI/TWI i mają go tylko niektóre modele (np. ATtiny25/45/85, ATtiny261/461/861).
Domyślnie moduł ten jest wyłączony po włączeniu/resecie mikrokontrolera, ale jest taktowany zegarem.

Aby wyłączyć moduł USARTx (Universal Synchronous/Asynchronous serial Receiver and Transmitter), należy zapisać
"0" do bitów RXENx i TXENx w rejestrze UCSRxB (Usart Control and Status Register x B) - spowoduje to zatrzymanie
działania interfejsu USARTx. Dopiero później można zapisać "1" do bitu PRUSARTx w rejestrze PRR (jeśli mikrokon-
troler go posiada) - spowoduje to całkowite odłączenie jego zegara taktującego. Niektóre modele nie mają modułu
USART (np. ATtiny25/45/85, ATtiny261/461/861). Domyślnie moduł ten jest wyłączony po włączeniu/resecie mikro-
kontrolera, ale jest taktowany zegarem.

4. Pomiar rezystancji wewnętrznych rezystorów podciągających

Według not katalogowych rezystor podciągający Rpu (pull-up) na pinie I/O może mieć wartość 20-50k (na pinie RESET
30-60k). Jego dokładną rezystancję można zmierzyć przy użyciu multimetru. W tym celu dowolny pin mikrokontrolera,
należy ustawić jako wejście z wysokim stanem (pull-up), wymuszonym włączeniem rezystora podciągającego (DDXn:0,
PORTXn:1, PUD:0). Później mierzymy i zapamiętujemy dokładną wartośc napięcia zasilania Vcc mikrokontrolera.
Następnie ustawiamy multimetr na najniższy zakres pomiaru prądu (np. do 2mA), mierzymy i zapamiętujemy dokładną
wartość prądu Ix, płynącego między podciągniętym pinem mikrokontrolera, a masą zasilania. Wartość rezystora pod-
ciągającego można obliczyć ze wzoru: Rpu [Ohm] = Vcc [V] / Ix [A]. Zasada pomiaru jest przedstawiona na poniższym
rysunku.

Przykładowo w moim ATtiny85 zasilanym napięciem Vcc=5.0V, prąd
płynący między podciągniętym pinem PB0, a masą zasilania wynosił
0.138mA. Stąd, po obliczeniach: Rpu = 5V / 0.000138A = 36231.88
omów.

Wartości wewnętrznych rezystorów mogą być inne w różnych egzem-
plarzach tego samego modelu mikrokontrolera, ale są bardzo zbliżone
do siebie na różnych pinach jednego układu. Rezystory te są prawdo-
podobnie wykonane na krzemie, jako tranzystory FET z długim cienkim
kanałem. Zajmują mniej miejsca, są łatwiejsze i tańsze w produkcji niż
tradycyjne rezystory, ale mają gorszą liniowość i stabilność tempera-
turową.


5. Pomiar częstotliwości wewnętrznego zegara taktującego

Można zmierzyć częstotliwość z jaką pracuje mikrokontroler przy użyciu miernika częstotliwości. W tym celu, należy ust-
awić wartość fuse bitu CKOUT na "0" (w fabrycznie nowym mikrokontrolerze CKOUT=1). Nie każdy model mikrokontro-
lera posiada ten fuse bit.
Po tej operacji na pinie CLKO, pojawi się częstotliwość pracy mikrokontrolera (inne funkcje tego pinu zostaną wyłączo-
ne). Jeśli mikrokontroler używa wewnętrznego dzielnika (prescaler), to na pinie CLKO pojawi się częstotliwość po po-
dziale. Teraz wystarczy podłączyć do tego pinu miernik częstotliwości, aby sprawdzić z jaką rzeczywistą częstotliwością
pracuje mikrokontroler.
To rozwiązanie jest dedykowane do taktowania zewnętrznych układów, współpracujących synchronicznie z mikrokon-
trolerem. Może również posłużyć do dokładnej, programowej kalibracji częstotliwości wewnętrznego oscylatora RC
(za pomocą rejestru OSCCAL).
W niektórych modelach sygnał na pinie CLKO jest dostępny również podczas włączania/resetu mikrokontrolera
(np. ATtiny48/88, ATmega48/88/168/328, ATmega164/324/644/1284). W przypadku modeli, w których drugą funkcją
pinu CLKO jest XTAL2, nie można wtedy używać rezonatorów kwarcowych/ceramicznych (np. ATtiny25/45/85,
ATtiny261/461/861).

6. Pomiar napięcia wewnętrznego źródła odniesienia

Można zmierzyć wartość wewnętrznego napięcia odniesienia przy użyciu woltomierza. W tym celu, należy włączyć
przetwornik analogowo-cyfrowy ADC (bit ADEN=1 w rejestrze ADCSRA) oraz tak ustawić bity REFSx w rejestrze
ADMUX (ADc MUltipleXer selection register), aby wybrać wewnętrzne źródło napięcia odniesienia z zewnętrznym
kondensatorem na pinie AREF ("Internal x.xV Voltage Reference with external capacitor at AREF pin"). Nie każdy
model mikrokontrolera pozwala na taką konfigurację.
Po tej operacji na pinie AREF, pojawi się napięcie referencyjne Vref z wewnętrznego źródła odniesienia. Teraz wy-
starczy podłączyć do tego pinu woltomierz o dużej rezystancji wejściowej (np. 10M), aby sprawdzić jaką rzeczywistą
wartość ma to napięcie.
Źródło wewnętrznego napięcia odniesienia ma bardzo dużą rezystancję wyjściową, a więc zapewnia bardzo małą
wydajność prądową. Dlatego do pinu AREF powinno podłączać się tylko obciążenia pojemnościowe (np. konden-
sator filtrujący 100nF). Wszystkie obciążenia rezystancyjne (rezystory pull-up/pull-down) powinny zostać odłączone
od tego pinu.

7. Maksymalny prąd wewnętrznych diod zabezpieczających

Każdy pin mikrokontrolera posiada dwie diody zabezpieczające (clamping diodes) o spadku napięcia 0.5V, które
chronią układ przed za wysokim/niskim napięciem wejściowym Vin w stosunku do jego napięcia zasilania Vcc.
Utrzymują one wszystkie sygnały trafiające do mikrokontrolera w zakresie jego maksymalnych napięć wejściowych
(od GND-0.5V do Vcc+0.5V), wymienionym w nocie katalogowej. Wewnętrzna budowa pinu mikrokontrolera jest
przedstawiona na poniższym rysunku.


 
Podanie napięcia Vin o wartości wyższej niż Vcc+0.5V, spowoduje przepływ
prądu przez górną diodę zabezpieczającą Dup do plusa zasilania, a w re-
zultacie zmniejszenie napięcia Vin do wartości Vcc+0.5V. Z kolei podanie
napięcia Vin o wartości niższej niż GND-0.5V, spowoduje przepływ prądu
przez dolną diodę zabezpieczającą Ddn do masy zasilania, a w rezultacie
zmniejszenie napięcia Vin do wartości GND-0.5V.
Jedynym ograniczeniem jest zalecany maksymalny prąd płynący przez wew-
nętrzne diody zabezpieczające, który nie powinien przekroczyć wartości 1mA.
Większy prąd może spowodować uszkodzenie diody zabezpieczającej,
a następnie pinu/portu mikrokontrolera.
Wynika z tego, że stosując odpowiednio dużą wartość rezystancji wejściowej
Rin, na pin mikrokontrolera można podać napięcie wejściowe Vin, o wartości
znacznie przekraczającej jego maksymalny zakres podany w nocie katalogo-
wej (od GND-0.5V do Vcc+0.5V).
Przy rezystorze Rin=1M na pin mikrokontrolera można podać napięcie uje-
mne/dodatnie Vin=1000V, bez obawy o jego uszkodzenie. Jest to dokładnie opisane w nocie aplikacyjnej "AVR182:
Zero Cross Detector" firmy Atmel/Microchip.

8. Wewnętrzny oscylator PLL

Mikrokontrolery ATtiny25/26/45/85/261/461/861 zawierają wewnętrzny oscylator PLL (Phase Locked Loop). Na jego
wyjściu uzyskuje się sygnał o częstotliwości 64 MHz (8x częstotliwość wewnętrznego oscylatora RC 8MHz) lub 32MHz
(8x 4MHz). Sygnał ten może służyć do asynchronicznego taktowania timera/licznika 1 (32/64MHz) lub do taktowania
samego mikrokontrolera po podziale przez 4 (8/16 MHz).

9. Programowa instrukcja XCHG (eXCHanGe two registers)

Lista instrukcji 8-bitowych mikrokontrolerów AVR nie zawiera żadnej instrukcji, która służy do wymiany zawartości
dwóch rejestrów, np. Raa i Rbb (Raa, Rbb = R0-R31). Najprostszym rozwiązaniem problemu jest wykorzystanie
trzeciego rejestru tymczasowego Rxx:

mov  Rxx,Raa
mov  Raa,Rbb
mov  Rbb,Rxx

Jednak nie zawsze jest do dyspozycji taki wolny rejestr tymczasowy. Jak się okazuje zadanie to można wykonać
również bez niego (oba rozwiązania mają jednakową liczbę, rozmiar i czas wykonywania instrukcji):

eor  Raa,Rbb
eor  Rbb,Raa
eor  Raa,Rbb