Tutorials - Elettronica

 
 

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

  1. point the requested CGRAM address

  2. perform the byte's writing 

in detail:

  1. Bring to 0 lines RS and RW to prepare the controller to accept commands
     
  2. 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.
     
  3. Switch from command mode to data, bringing the RS pin to 1
     
  4. 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.
     
  5. 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.


 

 

Copyright afg. Tutti i diritti riservati.
Aggiornato il 04/12/12.