📄 lab2.asm
字号:
.include "C:\Program Files\Labcenter Electronics\Proteus 6 Professional\Tools\AVRASM\APPNOTES\m16def.inc"
.equ TIME_LIMIT = 15625 ; pana unde tre' sa numere contoru pe 16 biti.
.dseg
digit_table: .BYTE 10 ; tabela de cifre
digit: .BYTE 1 ; cifra curenta
.cseg
;tabela de intreruperi
.org 0
jmp main ; reset interrupt
.org $0C
jmp cmp_handler ; TMR0/A compare int
.org $2A
main:
ldi r16, HIGH(RAMEND) ; initializeaza stiva
out SPH, r16
ldi r16, LOW(RAMEND)
out SPL, r16
call init_portb ; initializeaza portul B
call init_alimentare_display_LED ; initializeaza portul D
call build_table ; construieste tabela pentru cifre
call init_digit ; seteaza valoarea initiala pentru digit (0) + afiseaza
call init_timer1 ; initializeaza timer1 (bate secunda)
sei ; da drumu la intreruperi
loop:
jmp loop
; initializeaza portul B: trebuie setat pe output. fiecare pin trebuie lasat in 1 logic
; pentru ca 7-segment sa nu afiseze nimic
init_portb:
; TODO #1
ldi r16, 0b11111111
out DDRB, r16
out PORTB, r16
ret
init_alimentare_display_LED:
push r16
ldi r16, 0
out DDRD, r16
out PORTD, r16
sbi DDRD, 7 ; pin 7 = alimentare display
pop r16
ret
; initializeaza variabila digit la 0 si apeleaza functia de afisare
init_digit:
; TODO #2
ldi r16, 0
sts digit,r16
call print_digit
ret
; initializeaza timer 1 pentru a produce o intrerupere la exact o secunda, folosind TIME_LIMIT
; pentru un factor de prescale de 1024, mod clear timer on compare ).
init_timer1:
; TODO #3
; TCCR
ldi r16, 0
out TCCR1A, r16
ldi r16, (1<<WGM12)|(1<<CS12)|(1<<CS10)
out TCCR1B, r16
; OCR
ldi r16, HIGH(TIME_LIMIT)
out OCR1AH, r16
ldi r16, LOW(TIME_LIMIT)
out OCR1AL, r16
;TIMSK
ldi r16,(1<<OCIE1A)
out TIMSK,r16
ret
; handler pentru intreruperea de compare a timer1. trebuie sa schimbe valoarea din variabila
; digit si sa apeleze functia de afisare
cmp_handler:
; TODO #4
push r17
push r16 ; salvam un registru in stiva
in r16, SREG ; citim valoarea din SREG in registrul general r16
push r16 ; punem pe stiva valoarea
lds r16, digit
inc r16
ldi r17,10
cp r16,r17 ;am ajuns la 10 ?
brne dupa_reset ; daca nu e 10, sar peste reset
ldi r16,0
dupa_reset:
sts digit,r16
call print_digit
; -- refacerea continutului initial al registrelor
pop r16 ; scoate din stiva r16
out SREG, r16 ; reface SREG
pop r16
pop r17
reti;
; afiseaza pe 7-segment cifra continuta in variabila digit. citeste digit_table[digit]
; si trimite valoarea in portul B
print_digit:
push r16
push XL
push XH
ldi XL, LOW(digit_table)
ldi XH, HIGH(digit_table)
lds r16, digit
add XL, r16
ldi r16, 0
adc XH, r16
ld r16, X
out PORTB, r16
pop XH
pop XL
pop r16
ret
; construieste tabela digit_table. este un vector cu 10 pozitii. digit_table[i] reprezenta
; valoare care trebuie scrisa in portul B, pentru ca pe 7-segment sa apara cifra i
build_table:
push r16
push XL
push XH
ldi XL, LOW(digit_table)
ldi XH, HIGH(digit_table)
ldi r16, 0b00000001 ; 0
st X+,r16
ldi r16, 0b11001111 ; 1
st X+,r16
ldi r16, 0b00010010 ; 2
st X+,r16
ldi r16, 0b00000110 ; 3
st X+,r16
ldi r16, 0b01001100 ; 4
st X+,r16
ldi r16, 0b00100100 ; 5
st X+,r16
ldi r16, 0b00100000 ; 6
st X+,r16
ldi r16, 0b00001111 ; 7
st X+,r16
ldi r16, 0b00000000 ; 8
st X+,r16
ldi r16, 0b00000100 ; 9
st X,r16
pop XH
pop XL
pop r16
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -