Friday, July 24, 2015

HD44780 lcd16x2 - custom character

The HD44780 has character generator RAM (CGRAM) to store user-defined character pattern. There are two font types - 5x8, 5x10. For 5x8 dots, 8 character patterns can be written, and for 5x10 dots, 4 character patterns can be written.

Since 2 lines mode is always preferred, the below setting is for font 5x8.

To understand the process of storing custom character, the correspondence between EPROM Address Data and Character Pattern (5x8 Dots) is needed to be studied.
For each custom character for 5x8 font, 8 lines of address are needed to store one character pattern.
So address, A2, A1, and A0 are the 8 selectable line position of the character pattern.
while data O4, O3, O2, O1, O0 correspond to character pattern data.
Last, the A5, A4, and A3 represent the 8 selectable address to a character.

The relationship between CGRAM Addresses, Character Codes (DDRAM) and Character
Patterns (CGRAM Data) can be better shown at figure below

The CGRAM address bits 0,1,2 are the line pattern position,
The CGRAM address bits 3,4,5 are the custom character position, it is linked with DDRAM location.

The DDRAM address bits 3 (*) indicates no effect which means address 0000 *000 can represent two locations 0000 0000, and 0000 1000. Both locations store the same custom character.

To go to CGRAM address the below instruction is used.

The address bits DB5, DB4, DB3 are custom character position,
while address bits DB2, DB1, DB0 are line pattern position.

When adding a custom character, it is only required to point to custom character position (DB5, DB4, DB3), and leave the line pattern position (DB2, DB1, DB0) equal to zero.
As the first line pattern is written, the HD44780 will automatically point to next location as (DB2, DB1, DB0) will be increased accordingly. So, pointing to next CGRAM location is not needed in next line pattern writing.

(DB5, DB4, DB3) - Custom character position
(DB2, DB1, DB0) - Line pattern position

To create custom character, use the instruction as follow:
rom char battery1[8] = {
        0b01110,
    0b01010,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b11111
    };
rom specific that this data is saved at flash memory.

To save the custom character, use the instruction
HD44780_AddCharacter(0, battery1);


All the custom characters are stored at the specific location as shown at figure below:


HD44780_AddCharacter(0, battery1);
location 0 is upper bits 0000, lower bits 0000.

To write the custom character to lcd display, just simply use the write data to DDRAM such as:
HD44780_WriteData(0x00);

BTW, to display the  character "0", HD44780_WriteData(0x30) and HD44780_WriteData("0") will get the same result.

Finally, the display of custom character - battery. I let the led1 and led2 blinking in forever loop (just for fun).


I keep all the source code at github.





Friday, July 10, 2015

HD44780 lcd16x2 and c18

The HD44780 is a common display used in hobbies project, the tutorials, datasheets, and implementation guide are all over the web. Even with available source code on the web, I am planning to write my driver using PIC18f. Previously, I had modified a source code online for msp430, it is a 4 bits data line communication. This time I am planning to write my own 8 bits data line communication 16x2 lcd driver using c18.

I write and test my code for on-going two months. Nothing work and I have no idea what went wrong as I wrote the code according to data sheet. Maybe the HD44780 has it's variant which make the implementation slightly difference from one and other.

I have to search on-line and read other people source code to understand how the initialisation of lcd is done. After some research, I found that elm-chan website has the most detail guide on implementation and the most accurate one also. For the source code, I found that armandas is the best written source code so far. I do follow some of the way armandas naming and code structure. Also there is simplified but detail datasheet from spickles.

The main problem I faced is the initialisation part, so I am going to start with this. There are two types of initialisation process. First is setup with internal reset, second is initialisation with software. The internal reset procedure is relatively easy, and protostack even shows an initialisation example using solely dip switch. This is pretty amazing as no a single MCU is involved in this.

Second type is the initialisation by instruction.
The initialisation diagram is as follow:

I had highlighted the changes I made.

For the last 4 steps, the long delay is needed as weird character will come out. Usually weird character mean the time needed for the lcd to process data is not enough.
For the third step from last, I found that 0b00001000 is not the correct initialisation. Although most of the datasheet online, and even microchip application note have shown that 0b00001000 is the correct value. Nonetheless, I do encounter some problem when initializing the lcd. Maybe the HD44780 variant is different somehow.

In this configuration, I choose, 8 bits data transmission and 2 lines display.

..............................................................................................................................................

For the 16x2 lcd, a pointer to particular location in lcd is important. The HD44780 in (8 bits, 2 lines configuration) able to store 80 locations. But only the first 16 locations of the 1st line and 2nd line able to be displayed.

The DDRAM address mapping is as follow:

The numbering is at hexadecimal format.
To point to first row, third column, DDRAM is set at 0x02.
To point to second row, third colum, DDRAM is set at 0x42.

The pseudo code is easy
if first row, DDRAM = address_point_by_user;
if second row, DDRAM = address_point_by_user + 0x40;

..............................................................................................................................................

Microchip has two simple rules to follow when apply read and write operation to IO port which are "0" for output and "1" for input and the second rule is "read from port, write to latch".
In order to write to output, the IO direction is set to output and the write operation is written to latch as follow:

#define HD44780_initPinIO() {TRISBbits.RB4=0; TRISBbits.RB5=0; TRISD=0x00;}
#define HD44780_EN_PIN LATBbits.LATB5
#define HD44780_RS_PIN LATBbits.LATB4
#define HD44780_DATA_PORT LATD

..............................................................................................................................................

To keep the coding easy to use and easy to understand, only three functions are included in the hd44780.h which are

void HD44780_Init(void);
void HD44780_WriteString(const rom char *s);
void HD44780_GoToPoint(char row, char col);

HD44780_Init()-must be defined before the two other functions.
HD44780_WriteString(const rom char *s)-write words to display.
HD44780_GoToPoint(char row, char col)-go to particular location of lcd.

Nevertheless, hd44780.c file can be modified to cater the user's need as most functions are hidden in hd44780.c.
..............................................................................................................................................

Simple note:
One pulse               - EN high, delay 50 us, EN low.
RS pin                    - 0 = COMMAND; 1 = DATA.
DDRAM location  - Location at lcd display.
rom                        - c18 keyword to store data in flash.

..............................................................................................................................................

Output:


Most people would prefer the "hello world" message, but I decide to display 4 alphabet at 4 different locations. ^^

The source code can be found at github.