ESERCITAZIONE # 12a
Esecuzione
Per la verifica dell' hardware vale quanto detto nell' esercitazione
precedente.
Per il software, il progetto MPLAB è scaricabile
qui.
Una volta assemblato il sorgente e caricata la memoria del PIC, basta lanciare
il programma con
Run e, se tutto è a posto, il display visualizzerà il
messaggio di prompt.
Se questo non succede, dopo aver verificato con cura i collegamenti, provate
a regolare il contrasto: i caratteri dovranno apparire chiaramente.
E' possibile anche il funzionamento step by step, ma, data la complessa
ripetitività delle routines, è meglio utilizzare breakpoint da posizionare nei
punti in cui si vuole interrompere l' esecuzione.
Il programma esegue la stessa sequenza dell' esercitazione precedente, ovvero:
- inizializza I/O per il display
- inizializza il display
- scrive un messaggio, cadenzando la presentazione delle lettere di 0.5
secondi una dall' altra
- attesa di 2 secondi
- pulisce il display e riporta i cursore all' inizio
- attesa di 1 secondo
- ripresa dal punto 3
Osserviamo che il programma è uguale al precedente dell' Es 12 !
La sostituzione del driver, con gli stessi entry point, permette di mantenere
identico il flusso principale.
Una NOTA
C'è qualcuno che commenta:" Ma come, per comandare un display occorrono
così tante righe di sorgente? Altri autori se la cavano con molto
meno...".
Certamente vero, basta semplicemente abolire ogni commento "superfluo"
e il testo sorgente si riduce a ben poco; ecco la versione lite:
;**********************************************************
;* lcd8bf_l018.asm
;* Driver per display LCD a caratteri
;**********************************************************
; bus dati su PORTC
; RS su portB,0
; RW su portB,1
; E su portB,2
;**********************************************************
;----------------------------
LCDIoIni: ; set I/O per LCD
bcf PORTB,2
bcf PORTB,0
bcf PORTB,1
clrf PORTC
clrf TRISC
bcf TRISB,2
bcf TRISB,1
bcf TRISB,0
return
;----------------------------
LCDSwini ; Inizializzazione per istruzioni.
rcall Delay15ms
movlw 0x30 ; comando 30h
movwf PORTC
rcall LCDclk ; primo clock
rcall Delay4ms ; primo ritardo
rcall LCDclk ; secondo clock
rcall Delay100us ; secondo ritardo
rcall LCDclk ; terzo clock
rcall LCDrdbfa ;check per Busy
movlw 0x38 ;8 bit/2 linee/ font 5x7
rcall LCDWrCmd
movlw 0x10 ;display off
rcall LCDWrCmd
movlw 0x01 ;Clear & Home
rcall LCDWrCmd
movlw 0x06 ;cursor move l->r
rcall LCDWrCmd
movlw 0x0E
;display on/cursor off/blink off
rcall LCDWrCmd
return
;----------------------------
LCDwrcmd: ; Trasmette un comando. Comando in WREG
bcf PORTB,0 ; RS = 0 per comando
bra lcwr
LCDwrdat: ; Trasmette un dato. Dato in WREG
bsf PORTB,0 ; RS = 1 per dati
lcwr movwf LCD_portw
bcf PORTB,1 ; RW = 0 per scrittura
rcall LCDclk
; reset LCD bus e controlli
clrf PORTC
bcf PORTB,1
bcf PORTB,0
return
;----------------------------
LCDclk bsf PORTB,2 ; E = 1
nop
nop
bcf PORTB,2 ; E = 0
nop
return
;----------------------------
LCDrdram: ; Leggi RAM dall' LCD
bcf PORTB,0
;RS=0 per la RAM
bra lcdr0
LCDrdbfa: ; Leggi BF + AC dall' LCD
bsf PORTB,0
;RS=1 per BF+AC
lcdr0 setf TRISC ;data port = input
bsf PORTB,1
;RW=1 per leggere
nop ;stabilizzazione
lcdr1 bsf PORTB,2 ;E = 1 - abilita LCD
btfss PORTB,0 ;RS = 1?
bra notbusy
;n - legge RAM
;s - test busy dall' LCD
btfss PORTC, 7 ;se 1 = busy
bra notbusy
;se = 0 busy end
bcf PORTB,2
nop
nop
bra lcdr1
notbusy movf PORTC, w ;salva il dato letto
nop
bcf PORTB,2
nop
nop
; reset LCD bus e controlli
clrf PORTC
bcf PORTB,1
bcf PORTB,0
clrf TRISC
return
;----------------------------
LCDWrCmd: ; Trasmette un comando.
rcall LCDwrcmd
bra LCDrdbfa ; check busy
LCDWrDat: ; Trasmette un dato.
rcall LCDWrDat ; RS = 1 per dati
bra LCDrdbfa
;----------------------------
LCDLine1 ;porta il cursore alla linea
movlw 0x80 ; linea 1
bra LCDWrCmd
LCDLine2
movlw 0xA0 ; linea 2
bra LCDWrCmd
; end of the module
|
E, per alleggerirlo ulteriormente, possiamo eliminare la strutturazione,
tutti i commenti, la forma in subroutine e scrivere le istruzioni direttamente
nel main...
E poi ? Il testo risulta certo più corto, ma è comprensibile ? E'
sensato un procedere del genere ?
Dato che:
- La versione "completa" di commenti e costanti non impiega più
tempo ad essere compilata di quella ridotta.
-
Inoltre, trattandosi di un driver, nel sorgente del programma in cui verrà
usato apparirà solamente come una linea di #include. Basta
un comando NOLIST all' inizio del driver per impedirne la stampa nel listato
ottenuto dall' assembler, che risulterà leggero al massimo.
- E una versione completa di commenti e descrizioni esaustive delle funzioni e
delle procedure fornisce LO STESSO codice della versione priva di commenti, non
un bit in più !!!
Il driver, una volta scritto e
collaudato, non richiede più di essere nè scritto, nè letto, nè collaudato
ulteriormente: va semplicemente utilizzato richiamando i suoi entry point,
ovvero le funzioni, macro o subroutine, che svolgono un dato compito.
Le versioni lite non sono per niente conformi all' idea che si sta proponendo,
ovvero quella di una programmazione quanto possibile strutturata e modulare, con
macro componenti facili da utilizzare e sorgenti semplici da gestire.
E questa semplificazione di uso richiede una maggiore complicazione nei vari
moduli.
Anche solo se non trasformiamo tutti gli assoluti in label, ci troveremo in
difficoltà serie una volta che si renda necessaria una modifica.
Ad esempio,
nel listato qui sopra, si è rinunciato ad associare i port con label. Il
risultato è che se si devono usare altri pin, occorre modificare l' intero
listato. Una serie di definizioni label= assoluti permette invece di cambiare le
assegnazioni agendo solo ed esclusivamente nelle definizioni.
E le molte linee delle assegnazioni e delle label producono lo steso codice di
una versione priva di label e assegnazioni, ma, rispetto a questa, sono
infinitamente più maneggevoli, modulari, modificabili, comprensibili !!!
Un esempio per tutti: per capire cosa faccia un movlw 0xA0 ,
occorre consultare il foglio dati; l' assegnazione di una tabella di comandi=label
esplicativa rende tutto più semplice.
Ovviamente ognuno potrà scegliere la forma e lo stile che più ritiene
adeguata durante la scrittura dei sorgenti.
Il problema non è la forma, ovvero usare *** al posto di
---- o label maiuscole
al posto di minuscole, nè quanti commenti inserire, ma è quello di
- usare una forma e uno stile che siano chiari e
- il numero di commenti necessari
a chiarire cosa facciano le istruzioni e
- realizzare una programmazione che non
sia fine a se stessa, funzionale solamente all' applicazione contingente, ma che
renda il proprio lavoro, tempo e sforzi impegnati, tale da poter essere
fruttuoso anche in futuro.
|