|
Introduciamo l'uso degli interrupt e del timer.
Il testo dell'esercizio è il seguente:
Scrivere un programma Assembler per 8051 che faccia ruotare verso sinistra un LED rosso
all'incirca 20 volte al secondo.
La rotazione dei LED deve essere effettuata in interruzione.
NOTE:
- Il timer produce al minimo 112,5 interruzioni al secondo in modo 0,
14,1 in modo 1 e 3600 in modo 2. Dato che i nostri LED devono
ruotare 20 volte al secondo, il solo modo che consente questa frequenza di rotazione è il
modo 1, che però è difficile da gestire. In alternativa, potremo usare il
modo 2, non ruotando i LED ad ogni interruzione. Useremo un registro per
contare le interruzioni e decidere quando ruotare i LED.
- I LED sono connessi all'alimentazione positiva, quindi un livello logico
0 sull'uscita accende il LED, mentre un livello 1 lo spegne.
- I bottoni sono connessi a massa, quindi quando un bottone è premuto
leggeremo 0 sul corrispondente ingresso, mentre leggeremo 0 se è
rilasciato.
- I LED sono disposti dal bit 0 al bit 7, quindi una rotazione a destra
sposta la configurazione a sinistra.
- Per ulteriroi informazioni sulla programmazione del PPI della scheda GPC-F2, fare
riferimento alla pagina Hardware e mappa di memoria
della scheda del Manuale d'uso del programma PCMon.
Una possibile soluzione è la seguente:
; ledrossi.asm
; Gruppo 08: Tizio & Caio 09/10/2001
;
; Pgm che fa ruotare i led rossi sulla scheda usando il timer settato in modo 2
;
; I LED rossi sono connessi alla porta A del PPI.
; Il port A del PPI e' all'indirizzo 0FA00H nella memoria XDATA.
; Il port di Controllo del PPI e' all'indirizzo 0FA03H nella memoria XDATA.
; La programmazione del PPI sara' la seguente:
; 1xxx xxxx Programmo port
; x00x xxxx Port A -> modo 0
; xxx0 xxxx Port A -> output
; xxxx 0xxx Port C Hi -> input
; xxxx x0xx Port B -> modo 0
; xxxx xx1x Port B -> input
; xxxx xxx0 Port C Lo -> output
; ---------
; 1000 0010
;
;
; Definisco alcune costanti utili:
.equ PPIPORTA, 0FA00h ; Port A del PPI
.equ PPICTL, 0FA03h ; Port di controllo del PPI
.equ DIVISIONE, 192 ; Numero di interupt prima di rotazione
.org 8050h ; Locazione del RESET
ljmp main
.org 805bh ; Locazione dell' ISR del Timer
ljmp led
main:
; Programmo port, Port A -> modo 0, Port A -> output, Port C Hi -> out,
; Port B -> modo 0, Port B -> input, Port C Lo -> output
mov a,#10000010b
mov dptr,#PPICTL
movx @dptr,a ; Programmo il PPI
mov a,tmod ; Leggo la programmazione corrente del timer
anl a,#11110000b ; Elimino la vecchia programmazione del timer 0
; 0xxx Gate (disabilitato controllo esterno)
; x0xx C/T -> Timer
; xx10 Modo 2 (8 bit auto reload)
; ----
; 0010
add a,#00000010b ; Timer 0 in modo 2
mov tmod,a ; Programmo il timer
mov th0,#16 ; Valore di ricarica del timer 0 (interrupt ogni 240 cicli)
mov dptr,#PPIPORTA ; Punta ai LED rossi
mov a,#11111110b ; LED piu' a sinistra acceso
mov r1,#DIVISIONE ; Imposta numero di interrupt prima di rotazione
setb ea ; Abilita globalmente le interruzioni
setb et0 ; Abilita l'interruzione del timer 0
setb tr0 ; Fa' partire il timer 0
;
; Il resto del lavoro lo fa' la rutine di interruzione.
; occorre solo restare in attesa, con un loop infinito
;
la:
sjmp la
;---------------------------------------
; ISR del timer (routine di risposta alle interruzioni)
;
; Timer impostato a 16 - > ogni 240 cilci arriva (3840 volte al secondo)
; La rotazione sarebbe troppo veloce, quindi non ruoto ad ogni interrupt.
; Conto 192 intrrupt prima di ruotare (quindi ruota 20 volte al secondo)
led:
djnz r1,fineled ; Non sono ancora passati i 192 interrupt
;
mov r1,#DIVISIONE ; Remposta numero di interrupt prima di rotazione
rr a ; Ruota la configurazione
movx @dptr,a ; e la manda sui LED
fineled:
reti
.end
|
Il sorgente del programma è giokino.asm ed il file
assemblato, pronto per l'esecuzione è giokino.obj.
Per provare il programma, lo si deve caricare in
PCMon, assemblare e far
funzionare. Può funzionare anche in emulazione
[Home Page dell'ITIS "Fermi"]
[Indice Quarta]
[Precedente]
[Successivo]
© Ing. Stefano Salvi - Released under GPL licence
|