Standard LCD modules come with built-in Character MAP stored in LCD ROM memory. There are plenty of characters for your needs, but you may still need some special ones like backslashes or some symbols in different languages. This LCD has a reserved RAM area for storing eight 5×7 dot matrix character patterns.
In the table above, this area is in the first column with addresses starting from 0 to 7 (from 0b00000000 to 0b00000111). This means that you can define any characters in these 8 fields as you like and use them by calling them by addresses from 0 to 7.
To define one character, you will need to write eight bytes in a row to CGRAM memory
For 0 character address (DDRAM=0):
So for the first character creation procedure would be:
The cycle of 8 iterations:
Send command to LCD with CGRAM address from 40h to 47h;
Send bytes to selected CGRAM address
Because characters are 5×7 dots. You only need to modify the first five bits of each byte. Other areas filled with zeros(Marked blue in the picture).
For the other 7 characters, the procedure is the same. Continue on the next 8 CGRAM addresses 48h-4Fh. The last CGRAM address for the eighth character is l 78h.
So you can create an array of 64bytes and write them all at once to CGRAM. Then you can read separate characters using DDRAM addresses from 0 to 7.
Before load your custom character to CGRAM, you need to store these chunks of 8 bytes.
The best way to store is program memory (FLASH).
const uint8_t squareR[] PROGMEM=
{
0b00011110,
0b00000010,
0b00000010,
0b00000010,
0b00000010,
0b00000011,
0b00000000,
0b00000000
};
Construction const uint8_t squareR[] PROGMEM means that data is stored in FLASH at address squareR. For this to work you must include #include “avr/pgmspace.h” library.
Then reading from program memory is ease pgm_read_byte(squareR[0] ):
Sending to custom character to LCD would look like:
void LCDdefinechar(const uint8_t *pc,uint8_t char_code){
uint8_t a, pcc;
uint16_t i;
a=(char_code<<3)|0x40;//calculate CGRAM address respectively to DDRAM address
for (i=0; i<8; i++){ //eight bytes for one character
pcc=pgm_read_byte(&pc[i]);//reads byte from program memory
LCDwritebyte(a++,pcc); //writes byte to CGRAM at address a
}
Function LCDwritebyte () is simple. Send command with CGRAM address to LCD and after send a byte.
void LCDwritebyte(uint8_t a, uint8_t pc)
{
LCDsendCommand(a);
LCDsendChar(pc);
}
Displaying first custom character stored in DDRAM address 0 is simple:
LCDsendChar(0);
Realization of functions
LCDsendCommand(a);
LCDsendChar(pc);
It depends on how you connect your LCD. I have developed simple routines for a 3-wire LCD connection. You may download them from here: LCD Custom char with WinAVR. This is a part of the project AVR-controlled generator, which is still in the development stage.
hoi