Dot matrix LCD : the CGRAM
|
How to write in CGRAM.
Write to CGRAM is headed in the same general protocol used by the controller to write data to RAM, or you need to
-
point the requested CGRAM address
-
perform the byte's writing
in detail:
- Bring to 0 lines RS and RW to prepare the controller to accept commands
- Select the address you want to send a byte CGRAM between 40h and 7Fh (64 to 127 decimal), corresponding to the cells of 0-63
CGRAM.
- Switch from command mode to data, bringing the RS pin to 1
- Send the byte to be written to the given address CGRAM. The controller automatically increments the address counter in order to avoid having to perform this maneuver manually for a possible subsequent
writing.
- If the string contains more bytes to be written, just repeat the previous step
It will, of course, match the 'beginning of a symbol with the' beginning of a block of cells of
CGRAM.
you can write:
- all 8 symbols available, transferring 64 consecutive bytes starting from 'CGRAM address 00h.
more symbols, placing the address counter CGRAM in the start position of the first symbol that moves and writing groups of 8 bytes
- one symbol, placing the address counter CGRAM in the start position of the symbol and transferring a group of 8 bytes
- a part of a symbol, writing one or more bytes to the addresses taken.
From the point of view of the instructions here, for example, a procedure to write a table of 64 bytes (all 8 symbols available) in CGRAM (Assembly PIC18F):
LCDCGADR
0 ;
set CGRAM address to 0
call LCDLd8CGram ;
write 8 chars (64 bytes)to CGRAM
with
;*************************************************************
; 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
and
;********************************************************************
; 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
As mentioned previously, between a writing and next there is no need to reposition the address counter, which is automatically updated by the
controller.
LCDSCtable may be:
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
If we want to load a single character, just point the CGRAM to the desired cell, then write the 8 consecutive bytes. For example, for the sixth symbol:
LCDCGADR 0x28
;
set CGRAM address to symbol 6
call LCDLdCGram
; write 8 bytes to CGRAM
with
;********************************************************************
; 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
LCDSctable include 8 bits only. For
example:
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
Even here, between one byte and the next, the controller automatically provides all 'update of the address
counter.
it is also possible to write only a part of a symbol, pointing 's address CGRAM to the cell and over-writing the desired content with the new byte.
Writing addresses and writing data.
To be observed that, in the above examples, are used two different routines to write the
address (LCDWrCmd) and the data in CGRAM (LCDWrDat).
In fact, the address is sent as a command, while the subsequent data is sent as data, the difference is determined by the RS pin.
For write data to RAM:
Command |
Control |
|
Data |
Function |
Write data to
CGRAM |
RS |
RW |
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
Send a data to CGRAM |
1 |
0 |
|
data
to CGRAM |
For write address to RAM:
Command |
Control |
|
Data |
Function |
Write address to
CGRAM |
RS |
RW |
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
Calla an address of CGRAM for read or
write |
0 |
0 |
|
0 |
1 |
CGRAM
address |
Each write operation in CGRAM requires 37 to 100 us for bytes depending on the characteristics of the controller. So you can write and overwrite dynamically CGRAM for motion effects on the display.
|