![]() |
Obsługa przetwornika ADC | ![]() |
Kompilacja |

![]() | Po wybraniu/zmianie wejścia dla przetwornika ADC w multiplekserze (bity MUXn w rejestrze ADMUX), do źródła Vin zostaje podłączony kon- densator Cmux przez rezystor Rmux. Po włącze- niu przetwornika ADC (bit ADEN w rejestrze ADCSRA), przełącznik Ssh podłącza do źródła Vin kondensator Csh przez rezystor Rsh. Po uru- chomieniu pojedynczej konwersji (bit ADSC w re- jestrze ADCSRA), kondensator Csh zostaje odłą- czony od źródła Vin. Po zakończeniu wykonywa- nia konwersji kondensator Csh zostaje ponownie podłączony do źródła Vin. Aby uzyskany wynik każdego pomiaru był prawi- dłowy, czas Tsh pomiędzy kolejnymi konwersjami powinien wynosić: Tsh = 6*Rin*Cin, gdzie Rin - |
.include "m48def.inc" ;definicje dla ATmega48
;.include "m88def.inc" ;definicje dla ATmega88
;.include "m168def.inc" ;definicje dla ATmega168
;.include "m328def.inc" ;definicje dla ATmega328
.cseg ;pamięć programu (FLASH)
.org $0000 ;wektory przerwań (dla ATmega48/88: 26 wektorów 2-bajtowych, o adresach $0000-$0019,
;dla ATmega168/328: 26 wektorów 4-bajtowych, o adresach $0000-$0032).
;Jeśli żadne przerwania nie będą używane, to w tym miejscu można bezpośrednio umieścić kod programu
;Wektor nr 1 (Reset)
;rjmp RESET ;dla ATmega48/88 musi to być instrukcja RJMP o rozmiarze 2 bajtów,
;jmp RESET ;dla ATmega168/328 musi to być instrukcja JMP o rozmiarze 4 bajtów,
;ponieważ wszystkie wektory w tych mikrokontrolerach mają taki rozmiar.
;RESET:
;Inicjalizacja wskaźnika stosu (zbędna dla ATmega48/88/168/328)
;ldi R16,LOW(RAMEND)
;out SPL,R16
;ldi R16,HIGH(RAMEND)
;out SPH,R16
;Konfiguracja mikrokontrolera
ldi R16,$01 ;częstotliwość pracy mikrokontrolera (CLK): 1-20 [MHz]
mov R15,R16
ldi R16,$EE ;zatrzymanie zbędnych modułów (TWI, SPI, USART, TC0, TC1, TC2)
sts $64,R16 ;zapis rejestru PRR
ldi R16,$80 ;wyłączenie zasilania komparatora analogowego
sts $50,R16 ;zapis rejestru ACSR
ldi R16,$FF
out PORTB,R16 ;ustawienie pinów PB0-PB7 jako wejść z wysokim stanem (pull-up)
out DDRD,R16 ;ustawienie pinów PD0-PD7 jako wyjść z niskim stanem
ldi R16,$30
out PORTD,R16 ;ustawienie wysokiego stanu na wyjściach PD4-PD5
;(PD0-PD3/PD6-PD7 stan niski).
ldi R16,$3E
out PORTC,R16 ;ustawienie pinów PC1/ADC1-PC5/ADC5 jako wejść z wysokim stanem (pull-up)
ldi R16,$01 ;wyłączenie cyfrowego bufora wejściowego na pinie PC0/ADC0
sts $7E,R16 ;zapis rejestru DIDR0
Aby zmniejszyć zakłócenia i pobór prądu, zostaje wyłączony komparator analogowy oraz zatrzymane
;Konfiguracja wyświetlacza LCD 2x16 znaków (HD44780)
rcall LCDi ;inicjalizacja LCD (włączenie trybu 4-bitowego)
ldi R18,$28 ;ustawienie opcji: 2 linie, znaki 5x8 pikseli, interfejs 4-bit
rcall LCDwi ;zapis instrukcji do LCD
ldi R18,$0C ;włączenie LCD bez kursora
rcall LCDwi ;zapis instrukcji do LCD
rcall LCDclr ;czyszczenie LCD
ldi ZL,LOW(Text0<<1)
ldi ZH,HIGH(Text0<<1)
rcall LCDwf ;wyświetlenie na LCD ciągu ASCIIZ z pamięci FLASH
ldi R18,$C0 ;ustawienie kursora na pozycji 1 w 2 linii
rcall LCDwi ;zapis instrukcji do LCD
rcall LCDwf ;wyświetlenie na LCD ciągu ASCIIZ z pamięci FLASH
Inicjalizacja i włączenie wyświetlacza LCD oraz wyświetlenie na nim początkowych napisów.
;Główna pętla programu
Loop:
;Obsługa zworki J1 - wybieranie wejścia dla przetwornika ADC
sbic PINC,$05 ;odczyt stanu pinu PC5/ADC5
rjmp Loop0 ;skok, jeśli na pinie PC5/ADC5 jest stan wysoki (zworka J1=OFF)
;Zworka J1=ON (zwarta): wybranie wewnętrznego źródła napięcia odniesienia (1.1V) jako wejścia dla ADC
ldi R16,$4E ;wybranie napięcia odniesienia z pinu AVCC i wejścia dla ADC
sts $7C,R16 ;zapis rejestru ADMUX
rjmp Loop1
;Zworka J1=OFF (rozwarta): wybranie pinu PC0/ADC0 jako wejścia dla ADC
Loop0: ldi R16,$40 ;wybranie napięcia odniesienia z pinu AVCC i wejścia dla ADC
sts $7C,R16 ;zapis rejestru ADMUX
;Uruchomienie konwersji ADC
Loop1: ldi R16,$C3 ;włączenie ADC i wykonanie pojedynczej konwersji z f=CLK/8 (125 kHz)
sts $7A,R16 ;zapis rejestru ADCSRA
;Czekanie na zakończenie konwersji przez ADC
Loop2: lds R16,$7A ;odczyt rejestru ADCSRA
andi R16,$40
brne Loop2 ;skok, jeśli bit ADSC=1 (konwersja trwa)
;Odczyt wyniku konwersji ADC
lds R23,$78 ;odczyt rejestru ADCL (młodszy bajt wyniku)
lds R16,$79 ;odczyt rejestru ADCH (starszy bajt wyniku)
;Konwersja 16-bitów wyniku do systemu HEX-ASCIIZ: [R16:R23] => "NNNN"
ldi ZL,LOW(sbuf)
ldi ZH,HIGH(sbuf) ;adres bufora wyjściowego w pamięci SRAM
rcall ConBH ;konwersja bajtu do systemu HEX-ASCIIZ
mov R16,R23 ;młodszy bajt wyniku
rcall ConBH ;konwersja bajtu do systemu HEX-ASCIIZ
;Wyświetlenie szesnastkowej wartości wyniku na LCD
sbiw ZL,$04
ldi R18,$C7 ;ustawienie kursora na pozycji 8 w 2 linii
rcall LCDwi ;zapis instrukcji do LCD
rcall LCDws ;wyświetlenie na LCD ciągu ASCIIZ z pamięci SRAM
ldi R16,$FF ;opóźnienie 25.5 ms
rcall Wait ;pętla opóźniająca
rcall Wait ;pętla opóźniająca
rcall Wait ;pętla opóźniająca
rcall Wait ;pętla opóźniająca
rjmp Loop
Główna pętla programu, która jest wykonywana bez przerwy. Na początku program sprawdza stan zwo-
|
Po wykryciu zakończenia konwersji (bit ADSC= 0) przez pętlę warunkową, 16-bitowy wynik jest odczytywany z rejestrów [ADCH:ADCL] (najsta- rsze 6-bitów ma zawsze wartość 0). Każdy bajt tego wyniku jest zamieniany na szesnastkowy ciąg ASCII i zapisywany do bufora w pamięci SRAM mikrokontrolera. Uzyskany w ten sposób 4-znakowy ciąg ASCIIZ jest wyświetlany na LCD, począwszy od pozycji nr 8 w 2 linii. Przed końcem pętli znajduje się kod generujący opóźnienie ok. 102ms, aby spowolnić wyświe- tlanie nowych wartości na LCD. Instrukcja skoku RJMP zamyka pętlę. Dzięki temu podczas pracy programu na wyś- wietlaczu LCD można obserwować aktualną 4-cyfrową wartość szesnastkową, która odpo- wiada napięciu na pinie PC0/ADC0 (J1=OFF) lub napięciu wewnętrznego źródła odniesienia (J1=ON) mikrokontrolera. Otrzymana wartość zależy bezpośrednio od na- pięcia zasilania Vcc mikrokontrolera (pin AVCC), ponieważ jest ono jednocześnie napięciem od- niesienia Vref dla przetwornika ADC. Aby wyniki pomiarów nie były zależne od napięcia zasilania Vcc, należy na pin AREF podać napięcie odnie- | ||||||
![]() Rysunek 1 ![]() Rysunek 3 | ![]() Rysunek 2 |
;Zapis szesnastkowej wartości bajtu do pamięci SRAM w postaci ciągu ASCIIZ: "NN"
ConBH: ldi R17,$02
ConBH0: swap R16 ;bajt do konwersji
mov R18,R16
andi R18,$0F
subi R18,$D0
cpi R18,$3A
brlt ConBH1
subi R18,$F9 ;subi R18,$D9 - małe litery (a-f)
ConBH1: st Z+,R18
dec R17
brne ConBH0
st Z,R17 ;wyjście danych
ret
;Inicjalizacja wyświetlacza LCD
LCDi:
;Czekanie na ustabilizowanie się napięcia zasilania
ldi R16,$C8 ;opóźnienie 20 ms
rcall Wait ;pętla opóźniająca
rcall Wait ;pętla opóźniająca
;Wysłanie trzech instrukcji $30 do LCD
ldi R18,$03
LCDi0: ldi R16,$B3
out PORTD,R16 ;E=1, RS=0 (PD4-PD5=1)
;(wait 4 CL)
cbi PORTD,$07 ;E=0, RS=0 (PD4-PD5=1)
ldi R16,$32 ;opóźnienie 5 ms
rcall Wait ;pętla opóźniająca
dec R18
brne LCDi0
;Wysłanie instrukcji $20 do LCD (włączenie trybu 4-bitowego)
ldi R16,$B2
out PORTD,R16 ;E=1, RS=0 (PD4-PD5=1)
;(wait 4 CL)
cbi PORTD,$07 ;E=0, RS=0 (PD4-PD5=1)
ldi R16,$0A ;opóźnienie 1 ms
rcall Wait ;pętla opóźniająca
ret
;Zapis instrukcji do wyświetlacza LCD (tryb 4-bitowy)
LCDwi: ldi R20,$B0 ;E=1, RS=0 (PD4-PD5=1)
rjmp LCDwc0
;Zapis znaku do wyświetlacza LCD (tryb 4-bitowy)
LCDwc: ldi R20,$F0 ;E=1, RS=1 (PD4-PD5=1)
LCDwc0: ldi R21,$02
LCDwc1: swap R18 ;bajt do wysłania
mov R19,R18
andi R19,$0F
andi R20,$F0 ;E=1, RS=początkowa wartość (PD4-PD5=1)
add R20,R19
out PORTD,R20 ;wysłanie 4-bitów do LCD (najpierw starsze, później młodsze)
;(wait 4 CL)
cbi PORTD,$07 ;E=0, RS=początkowa wartość (PD4-PD5=1)
ldi R16,$01 ;opóźnienie 100 us
rcall Wait ;pętla opóźniająca
dec R21
brne LCDwc1
ret
;Czyszczenie wyświetlacza LCD i powrót kursora na pozycję 1 w 1 linii
LCDclr: ldi R18,$01 ;czyszczenie LCD i powrót kursora
rcall LCDwi ;zapis instrukcji do LCD
ldi R16,$10 ;opóźnienie 1.6 ms
rcall Wait ;pętla opóźniająca
ret
;Zapis ciągu ASCIIZ z pamięci SRAM do wyświetlacza LCD (tryb 4-bitowy)
LCDws0: rcall LCDwc ;zapis znaku do LCD
LCDws: ld R18,Z+ ;odczyt znaku z pamięci SRAM
tst R18
brne LCDws0
ret
;Zapis ciągu ASCIIZ z pamięci FLASH do wyświetlacza LCD (tryb 4-bitowy)
LCDwf0: rcall LCDwc ;zapis znaku do LCD
LCDwf: lpm R18,Z+ ;odczyt znaku z pamięci FLASH
tst R18
brne LCDwf0
ret
;Pętla opóźniająca o zadany czas: 100u - 25.5m [s]
Wait: mov R2,R15 ;R15 (CLK) = częstotliwość pracy mikrokontrolera: $01-$14 (1-20 MHz)
ldi R17,$19
mul R16,R17 ;R16 (DLY) = wartość opóźnienia: $01-$FF (100us-25.5ms)
Wait0: movw YL,R0
Wait1: sbiw YL,$01
brne Wait1
dec R2
brne Wait0
ret
;Napisy dla wyświetlacza LCD
Text0: .db "*** ADC test ***",0,"Value:",0
.dseg ;pamięć danych (SRAM)
.org $0100
sbuf: .byte 5 ;rezerwuje N-bajtów w pamięci SRAM