Lab 2
Lab 2
Lucrarea 2
Microcontrolerul ATmega32. Utilizarea modulelor timer
Scopul lucrării
2
Figura 1. Schema bloc a modulului Timer/Counter0 pe 8 biţi
3
Figura 3. Setarea modului de funcţionare al Timer/Counter0
6
Figura 7. Schema bloc a modulului timer pe 16 biţi
7
Astfel, pentru a scrie o valoare în regiştrii de tip prag sau în cel de numărare,
se va scrie mai întâi partea superioară (de exemplu OCR1AH) şi apoi partea
inferioară (de exemplu OCR1AL). Când se citeşte o valoare din regiştrii de tip prag
ai timerului sau din cel de numărare, se va citi mai întâi partea inferioară şi apoi
partea superioară.
Modurile principale de funcţionare ale timerului de 16 biţi sunt:
- funcţionare normală
- re-iniţializare la atingerea valorii de prag (CTC)
- semnal PWM rapid
- semnal PWM corect în fază
- semnal PWM corect în fază şi frecvenţă
8
1 0 0 fosc/256
1 0 1 fosc/1024
frecvenţa semnalului de pe pinul
1 1 0
T1, frontul descendent
frecvenţa semnalului de pe pinul
1 1 1
T1, frontul ascendent
9
3.2. Modul de funcţionare cu re-iniţializare la atingerea valorii de prag (CTC)
10
În acest mod de funcţionare, când TCNT1 este setat să numere până la valoarea
registrului OCR1A, utilizatorul o poate modifica oricând deoarece ea nu va fi
transferată în modulul timer decât după ce TCNT1 a ajuns la valoarea maximă.
11
4. Exemple de programe
a) Să se scrie un program care generează pe pinul OC0 (PB3) un semnal dreptunghiular cu
frecvenţa de aproximativ 15 Hz şi factor de umplere 50%.
START
Setare porturi
Setare Timer 0
Buclă infinită
.include "[Link]"
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,0xFF
out DDRB,r16 ; OC0 este pe pinul PB3
main:
cli ;dezactivare intreruperi
ldi r16,0b00011000 ;setare timer: se utilizeaza pinul OC0, timerul este oprit deocamdata
out TCCR0,r16 ;modul va fi CTC cu prag dat de OCR0
in r16, TIMSK
andi r16,0b11111100 ;nu se utiliz. nici o intrer., fara a modifica alti biti din TIMSK
out TIMSK, r16
ldi r16, 0xFA ;se incarca valoarea de prag: 0xFA=250
out OCR0,r16 ;250 * 1/(8MHz/1024) =~ 32ms
in r16,TCCR0
andi r16,0b11111101 ;se porneste timerul si este setat sa numere
ori r16,0b00000101 ;la fiecare 1024 perioade de ceas, fara a modifica alti biti
out TCCR0,r16
bucla:
rjmp bucla
12
b) Să se scrie un program care într-un interval de aproximativ 8s efectuează următoarele operaţii:
după 2s aprinde ledurile portului A, după 6,5s aprinde ledurile portului C iar la finalul
intervalului stinge toate ledurile.
START
Setare porturi
Setare Timer 1
S-a produs
întrerupere
DA Aprinde
leduri port A
la prag A?
NU
S-a produs
întrerupere
DA Aprinde
leduri port C
la prag B?
NU
S-a produs
DA Stinge leduri
întrerupere
port A şi C
la val. max?
Pre-iniţializare
contor Timer 1
NU
.include "[Link]"
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp prag_2sec
jmp prag_6_5sec
jmp prag_8sec
jmp reset
13
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,0xFF
out DDRA,r16
out DDRC,r16
main:
cli ;dezactivare globala intreruperi
ldi r16,0b00000000 ;setare timer: nu se utiliz. OC1A si OC1B, oprit deocamdata
out TCCR1A,r16 ;modul va fi normal
ldi r16,0b00000000
out TCCR1B,r16
in r16, TIMSK
andi r16,0b11000011
ori r16,0b00011100 ;se utiliz. toate intreruperile, fara a modifica alti biti din TIMSK
out TIMSK, r16
ldi r16, 0x3D ;se incarca valoarea de prag A: 0x3D09=15625
out OCR1AH,r16 ;15625 * 1/(8MHz/1024) =~ 2s
ldi r16, 0x09
out OCR1AL,r16
ldi r16, 0xC6 ;se incarca valoarea de prag: 0xC65D=50781
out OCR1BH,r16 ;50781 * 1/(8MHz/1024) =~ 6,5s
ldi r16, 0x5D
out OCR1BL,r16
ldi r16, 0x0B ;se incarca o valoarea initiala: 0x0BDB=3035 si 65535-3035=62500
out TCNT1H,r16 ;62500 * 1/(8MHz/1024) = 8s
ldi r16, 0xDB
out TCNT1L,r16
in r16,TCCR1B
andi r16,0b11111101 ;se porneste timerul care va numara la 1024 impulsuri de ceas
ori r16,0b00000101
out TCCR1B,r16
sei ;activare globala a intreruperilor
bucla:
rjmp bucla
prag_2sec:
in r20, SREG
ldi r18,0xFF
out PORTA,r18
out SREG,r20
reti
prag_6_5sec:
in r20, SREG
ldi r18,0xFF
out PORTC,r18
out SREG,r20
reti
prag_8sec:
in r20, SREG
ldi r18,0x00
out PORTA,r18
out PORTC,r18
ldi r16, 0x0B ;se incarca o valoarea initiala: 0x0BDB=3035 si 65535-3035=62500
out TCNT1H,r16 ;62500 * 1/(8MHz/1024) = 8s
14
ldi r16, 0xDB
out TCNT1L,r16
out SREG,r20
reti
c) Să se scrie un program care schimbă starea ledului conectat pe pinul PA7 dacă s-a ţinut apăsat
cel puţin 6s pe butonul conectat pe PC7.
START
Setare porturi
Setare timere
Resetare contor
secunde (r18)
S-a produs Se
întrerupere prag
DA apasă
DA
A Timer 1? PC7?
Inc. r18
NU NU
S-a produs
NU întrerupere val. DA
max Timer 0?
Se
DA NU
apasă
PC7?
r18≥6?
DA
Timer
Resetare NU 1
contor Timer 1
pornit?
NU Schimbare
stare PA0
Pornire
Timer 1
DA
Resetare r18
Oprire Timer 1
15
.include "[Link]"
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp prag_1sec
jmp reset
jmp reset
jmp reset
jmp scanare_butoane ;la fiecare 32ms se verifica starea butonului
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
jmp reset
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,0x00
out DDRC,r16
ldi r16,0xFF
out DDRA,r16
out PORTC,r16
ldi r18,0x00 ;r18 este contorul de secunde
main:
cli ;dezactivare globala intreruperi
ldi r16,0b00000000 ;setare timer: nu se utiliz. OC1A si OC1B, oprit deocamdata
out TCCR1A,r16 ;modul va fi CTC
ldi r16,0b00001000
out TCCR1B,r16
in r16, TIMSK
andi r16,0b11000011
ori r16,0b00010000 ;se utiliz. doar intrer. prag A fara a modifica alti biti din TIMSK
out TIMSK, r16
ldi r16, 0x7A ;se incarca valoarea de prag A: 0x7A12=31250
out OCR1AH,r16 ;31250 * 1/(8MHz/256) = 1s
ldi r16, 0x12
out OCR1AL,r16
scanare_butoane:
in r20, SREG
in r16,PINC
sbrc r16,PC7 ;verific daca se apasa pe buton
rjmp turn_off
in r16,TCCR1B
mov r17,r16
andi r17,0b00000111
16
cpi r17,0b00000100 ;daca timerul e deja pornit nu il mai pornesc
breq end
ldi r17,0x00
out TCNT1H,r17
out TCNT1L,r17 ;inainte de o noua pornire se reseteaza
andi r16,0b11111000 ;se porneste timerul cu numarare la fiecare 256 impulsuri de ceas
ori r16,0b00000100
out TCCR1B,r16
rjmp end
turn_off:
cpi r18,6 ;s-a tinut apasat cel putin 6s ?
brlo end1 ;nu, se opreste timer si se iese din intrerupere
in r16,PINA ;am tinut apasat cel putin 6s, citesc starea ledului
ldi r17,0b10000000 ; ca sa o pot schimba
eor r16,r17
out PORTA, r16 ;trimit noua stare a ledului
end1:
ldi r18,0x00 ;pregatesc contorul pt. o noua numarare
in r16,TCCR1B
andi r16,0xF8
out TCCR1B,r16
end:
out SREG,r20
reti
prag_1sec:
in r20, SREG
in r16,PINC
sbrs r16,PC7 ;verific daca inca se mai apasa pe buton
inc r18
out SREG,r20
reti
5. Teme şi exerciţii
17