Caratteri CGRAM nei display
LCD
a matrice
|
Come scrivere in CGRAM.
Scrivere in CGRAM fa capo allo stesso protocollo generale utilizzato dal controller
per la scrittura in RAM, ovvero occorre:
-
puntare l' indirizzo sull'area CGRAM richiesta
-
effettuare la scrittura del byte
In dettaglio:
- Portare a 0 le linee RS e RW per preparare il controller ad accettare
comandi
- Selezionare l'indirizzo CGRAM voluto inviando un byte compreso tra 40h e
7Fh (64 e 127 decimali), corrispondenti alle celle 0-63 della CGRAM.
- Commutare la modalità da comandi a dati, portando il pin RS a 1
- Inviare il byte che si vuole scrivere a quel dato indirizzo di CGRAM. Il controller
automaticamente incrementa il contatore di indirizzi in modo
da non dover effettuare questa manovra manualmente per una possibile
successiva scrittura.
- Se la stringa da scrivere comprende più bytes, basta ripetere il passo
precedente
Si dovrà, ovviamente, far coincidere l' inizio di un simbolo con l' inizio
di un blocco di celle di CGRAM.
E' possibile scrivere:
- tutti e 8 i simboli disponibili, trasferendo 64 bytes consecutivi a
partire dall' indirizzo CGRAM 00h.
- più simboli, posizionando il contatore di indirizzi di CGRAM nella
posizione di inizio del primo simbolo che si trasferisce e scrivendo
gruppi di 8 bytes
- un solo simbolo, posizionando il contatore di indirizzi di CGRAM nella
posizione di inizio del simbolo e trasferendo un gruppo di 8 bytes
- una parte di un simbolo, scrivendo uno o più bytes agli indirizzi
voluti.
Dal punto di vista delle istruzioni ecco, ad esempio, una procedura per
scrivere una tabella di 64 bytes (tutti e 8 i simboli disponibili) nella CGRAM (Assembly PIC18F):
LCDCGADR
0 ;
set CGRAM address to 0
call LCDLd8CGram ;
write 8 chars (64 bytes)to CGRAM
dove:
;*************************************************************
; LCDCGADR - Call a specified CGRam address
; Use : LCDCGADR xx with xx any valid CGRam address
; if out of range, error
;*************************************************************
LCDCGADR macro CGRamAdr
Local value = CGRamAdr | b'01000000'
; mask command
#if (CGRamAdr > b'00111111')
ERROR "CGRAM Address over range in LCDCGAdr"
#else
movlw value
call LCDWrCmd
; write address to CGRAM
#endif
endm
e
;********************************************************************
; LCDLd8CGram - Subroutine
; Move 8 user-defined chars to the CGRAM
; Chars are stored on LCDSCtable 8 x 8bytes = 64 bytes
;********************************************************************
LCDLd8CGram
; set pointer to table in program memory
#if PROGMEMSIZE > 32 ; only if prog. memory >32K
movlw UPPER LCDSCtable ; bits 16 - 21 of target
movwf TBLPTRU
; to pointer UPPER
#endif
movlw low LCDSCtable
movwf TBLPTRL
movlw high LCDSCtable
movwf TBLPTRH
;entry point for an external table setup
llcg0:
clrf LCDtemp
; start from row 0
movf LCDtemp, w
; row counter in W
iorlw b'01000000'
; convert to CG address
call LCDWrCmd
; send CGRamAddress
llcg1 tblrd *+
; read table entry into TABLAT
movf TABLAT,w
; move row value to WREG
call LCDWrDat
; write to LCD
incf LCDtemp, f
; rowcounter + 1
btfss LCDtemp, 6
; cntr >64 if bit 6 = 1
bra llcg1
; n - pick up next row
return
Come detto precedentemente, tra una scrittura e la
successiva non occorre riposizionare il contatore di indirizzi, che viene
automaticamente aggiornato dal controller.
La LCDSCtable potrà avere questo
aspetto:
LCDSCTable
; 8 chars for CGRAM - 5x7
; arrow up
db 04,0x0E,0x15,04,04,04,04,00
;0x04 ; . . # . .
;0x0E ; . # # # .
;0x15, ; # . # . #
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x00 ; . . . . . cursor row
; arrow down
db 04,04,04,04,0x15,0x0E,04,00
;0x04 ; . . # . .
;0x04 ; . . # . .
;0x0E ; . . # . .
;0x15 ; # . # . #
;0x0E, ; . # # # .
;0x04 ; . . # . .
;0x00 ; . . . . . cursor row
; arrow right
db 00,04,02,0x1F,02,04,00,00
;0x00, ; . . . . .
;0x04 ; . . # . .
;0x02 ; . . . #
;0x1F ; # # # # #
;0x02 ; . . . # .
;0x04, ; . . # . .
;0x00 ; . . . . .
;0x00 ; . . . . . cursor row
; arrow left
db 00,04,08,0x1F,08,04,00,00
;0x00, ; . . . . .
;0x04 ; . . # . .
;0x0F ; . # . . .
;0x1F ; # # # # #
;0x0F ; . # . . .
;0x04 ; . . # . .
;0x00 ; . . . . .
;0x00 ; . . . . . cursor row
; right turn
04,02,0x1F,0x12,0x14,0x10,0x10,00
;0x04 ; . . # . .
;0x02 ; . . . # .
;0x1F ; # # # # #
;0x12 ; # . . # .
;0x14 ; # . # . .
;0x10 ; # . . . .
;0x10 ; # . . . .
;0x00 ; . . . . .
; left turn
db 04,08,0x1F,09,05,01,01,00
;0x04 ; . . # . .
;0x02 ; . # . . .
;0x1F ; # # # # #
;0x12 ; . # . . #
;0x14 ; . . # . #
;0x10 ; . . . . #
;0x10 ; . . . . #
;0x00 ; . . . . .
; arrow big up
db 04,0x0E,0x1F,0x15,04,04,04,04
;0x04 ; . . # . .
;0x0E ; . # # # .
;0x1F, ; # # # # #
;0x15, ; # . # . #.
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x04 ; . . # . . cursor row
; arrow big down
db 04,04,04,04,0x15,0x1F,0x0E,04
;0x04 ; . . # . .
;0x04 ; . . # . .
;0x04 ; . . # . .
;0x04 ; . . # . .
;0x15 ; # . # . #
;0x1F, ; # # # # #
;0x0E ; . # # # .
;0x00 ; . # . . cursor row
Se volessimo caricare un solo carattere, basterà puntare la CGRAM alla
cella voluta, indi scrivere gli 8 bytes consecutivi. Ad esempio, per il sesto simbolo:
LCDCGADR 0x28
;
set CGRAM address to symbol 6
call LCDLdCGram
; write 8 bytes to CGRAM
dove
;********************************************************************
; LCDLdCGRAM - Subroutine
; Move 1 user-defined chars to the a CGRAM location
; Chars are stored in a table called by SETTABLE macro
;********************************************************************
LCDLdCGRAM:
; set pointer to table in program memory
#if PROGMEMSIZE > 32 ; only if prog. memory >32K
movlw UPPER LCDSctable
; bits 16 - 21 of target
movwf TBLPTRU
; to pointer UPPER
#endif
movlw low LCDSctable
movwf TBLPTRL
movlw high LCDSctable
movwf TBLPTRH
movlw 8
; set counter
movwf LCDtemp
; for 8 bytes
llcg1 tblrd *+ ; read table entry into TABLAT
movf TABLAT,w
; move row value to WREG
call LCDWrDat
; write to LCD
decfsz LCDtemp, f ; rowcounter + 1
bra llcg1
; n - pick up next row
return
La LCDSctable sarà composta da 8 soli bytes.
Ad esempio
LCDSctable:
; 1 char. 5x7 for CGRAM
; plug
db 0x0A,0x0A,0x1F,0x11,0x0E,04,04,00
;0x0A, ; . # . # .
;0x0A, ; . # . # .
;0x1F, ; # # # # #
;0x11, ; # . . . #
;0x0E, ; . # # # .
;0x04, ; . . # . .
;0x04, ; . . # . .
;0x00 ; . . . . . cursor row
Anche qui, tra un byte ed il successivo, il controller provvede
automaticamente all' aggiornamento del contatore di indirizzi.
E' possibile scrivere anche solo una parte di un simbolo,
puntando l' indirizzo di CGRAM alla cella voluta e sovra scrivendone il
contenuto con il nuovo byte.
Scrittura di indirizzi e scrittura di dati.
Da osservare che, negli esempi sopra riportati, sono utilizzate due diverse
routines per scrivere l' indirizzo (LCDWrCmd)
e i dati in CGRAM (LCDWrDat).
Infatti l' indirizzo è inviato come un comando, mentre i successivi
dati sono inviati come dati; la differenza è stabilita dal pin RS.
Comando |
Controllo |
|
Dato |
Funzione |
Write data to
CGRAM |
RS |
RW |
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
Invia un dato alla CGRAM |
1 |
0 |
|
dato alla
CGRAM |
Comando |
Controllo |
|
Dato |
Funzione |
Write address to
CGRAM |
RS |
RW |
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
Fissa un indirizzo della CGRAM per la
successiva scrittura o lettura |
0 |
0 |
|
0 |
1 |
indirizzo
della CGRAM |
Ogni operazione di scrittura in CGRAM richiede da 37 a 100 us per byte a
seconda delle caratteristiche del controller. Quindi è possibile scrivere e
sovrascrivere dinamicamente la CGRAM per ottenere effetti di movimento sul
display.
|