Hello Friends!
I am working with the HD44780 LCD display with the MC9S12DG128 and I was wondering if anyone might know where I may be able to find a set of initialization code for this LCD in 'C'? Thank you so very much for your time and I wish you a most wondrous day.
Sincerely,
Jon
Here is code for 4 bit mode.. it is written for the JM but you should be able to get what you need. Teak the delays for you clock speed....
/* * LCD - Writes to LCD * * This assumes an HD44780 or compatible LCD. 4 bit interface * It's been tested on several, and some LCDs seem to need more delay time * If you get garbage characters, try increasing the delay. * PTA0 = RS (data/command) (Pin 4 on LCD module) * PTA1 = EN (Write pulse) (Pin 6, also called E) * PTA2 = Data 4 (Pin 11) * PTA3 = Data 5 (Pin 12) * PTA4 = Data 6 (Pin 13) * PTA5 = Data 7 (Pin 14) * Pins 1 & 5 should be 0V on the LCD module * Pin 5 is R/W and we only use W so ground it * Pin 3 should go to ground thru a 1K resistor * Pin 15 is the positive side of the back light LED and can be connected to +5 * Pin 16 is the ground side of the back light LED, and should go to ground thru a * 100OHM or higher resistor. You could also hook up a PWM signal here. * (note: The resistor can be on either side of the LED. You MUST have a resistor) * thru a transistor for variable back light. * * jdonelson 12/10 */// Delay constants for 48MHz clock.// Set to work with CF, too long for 08.#define ENBIT (0x02)#define DELAY40US (104)#define DELAY4_1MS (10761)#define DELAY100US (262)#define LCDWIDTH (16)#define EN_DELAY (90)static int lcd_width = 0;static int lcd_lines = 0;static void lcd_delay(word count); void InitLCD(int width); static void LCDWrite8BitMode(byte data);void LCDWriteByte(byte data, byte rs);void LCDWriteLine(char *string, byte line);void LCDClear(void);void SetCursorLCD( byte pos);/* * */static void lcd_delay(word count) { word i = 0; for( i = 0; i < count ; ++i) { asm { nop nop nop nop nop nop nop nop nop } }}int LCDGetWidth(void){ return lcd_width;}/* * */void LCDInit(int width,int lines) { int i; lcd_width = width; lcd_lines = lines; // Set bits to output // PTA0 = RS (0=cmd,1=data) PTA1=EN lo-high-lo to write // PTA2-5 =Data bits 4-7 PTADD |= 0x3F; // Enable pull ups. PTAPE |= 0x3F; // Write all low; PTAD &= ~0x3f; // Need to do this in case still powering up. // Should be 20MS for( i = 0 ; i < 250 ; ++i) lcd_delay(DELAY100US); // See HD44780 spec. It tells you to do this... LCDWrite8BitMode(0x30); // tell it once lcd_delay(DELAY4_1MS); LCDWrite8BitMode(0x30); // tell it twice lcd_delay(DELAY4_1MS); LCDWrite8BitMode(0x30); // tell it thrice lcd_delay(DELAY4_1MS); // This sets 4 bit mode, but you can't write the low nibble yet. LCDWrite8BitMode(0x20); lcd_delay(DELAY4_1MS); // Now it's set to 4 bit mode. // 0 0 1 DL | N F X X // N = 2/1 line, DL = 8/4 bit F=5x10/5x8 LCDWriteByte(0x28, 0); // last function set: 4-bit mode, 2 lines, 5x8 matrix lcd_delay(DELAY4_1MS); // 0 0 0 0 | 1 D C B // D= Display on off, C = Cursor, B-Blink LCDWriteByte(0x0c, 0); // display on, cursor off, blink off lcd_delay(DELAY4_1MS); LCDWriteByte(0x01, 0); // display clear lcd_delay(DELAY4_1MS); // 0 0 0 0 | 0 1 I/D S // I/D = Increment/Decrement S = Shift LCDWriteByte(0x06, 0); // cursor auto-increment, disable display shift lcd_delay(DELAY4_1MS); for( i = 0 ; i < lines ; ++i) { LCDWriteLine("",(byte) i); } }//// Used to write while LCD is still in 8 bit mode.//static void LCDWrite8BitMode(byte data) { byte shifted; // Shift the high nibble into proper place shifted =(byte) (data >> 2); // Pulse EN line PTAD = shifted; // raise the strobe PTAD |= ENBIT; // We need thighs because we are too fast. lcd_delay(EN_DELAY); // Lower the strobe PTAD &= ~ENBIT; // Delay for command to complete. lcd_delay(DELAY40US);} //// Write 8 bits, 4 bits at a time.//void LCDWriteByte(byte data, byte rs) { byte high, low; // Need to do 2x 4 bit writes // Extract the high nibble and the lo nibble and // shift them into proper bit positions. // 'or' in the command/data flag. high =(byte) (((data & 0xf0) >> 2) | (rs & 0x01)) ; // Write, sets EN=0 PTAD = high; // Raise EN bit to strobe data. PTAD |= ENBIT; lcd_delay(EN_DELAY); // Clear EN bit PTAD &= ~ENBIT; // Now do lo nibble. low = (byte) (((data & 0x0f) << 2) | (rs & 0x01)) ; PTAD = low; PTAD |= ENBIT; lcd_delay(EN_DELAY); PTAD &= ~ENBIT; // Delay for command to complete. lcd_delay(DELAY40US);} void LCDWriteLine(char *string, byte line) { byte i=0; byte cmd=0; // Set up which line to write on. // Set "Cursor Address" command. // 1 A A A | A A A A // AAAAAAA can be 00H to 27H // for the first line, and 40H to 67H for the second line. switch(line) { case 0: cmd = 0x80; break; case 1: cmd = 0xc0; break; case 2: cmd = 0x94; break; case 3: cmd = 0xD4; default: ; } LCDWriteByte( cmd, 0); // write as command // Clear the line first for( i = 0 ; i < lcd_width ; ++i) LCDWriteByte( ' ', 1); LCDWriteByte( cmd, 0); // write as command // Send out the whole line... for( i = 0; string[i] && i < lcd_width; i++) { if( string[i] == '\r' || string[i] == '\n') continue; LCDWriteByte( string[i], 1); }}void LCDWriteBuffer(char *string, int count, byte line) { byte i=0; byte cmd=0; // Set up which line to write on. // Set "Cursor Address" command. // 1 A A A | A A A A // AAAAAAA can be 00H to 27H // for the first line, and 40H to 67H for the second line. switch(line) { case 0: cmd = 0x80; break; case 1: cmd = 0xc0; break; case 2: cmd = 0x94; break; case 3: cmd = 0xD4; default: ; } LCDWriteByte( cmd, 0); // write as command // Clear the line first for( i = 0 ; i < lcd_width ; ++i) LCDWriteByte( ' ', 1); LCDWriteByte( cmd, 0); // write as command // Send out the whole line... for( i = 0; i < count && i < lcd_width; i++) { if( string[i] == '\r' || string[i] == '\n') continue; LCDWriteByte( string[i], 1); }} void SetCursorLCD( byte pos){ LCDWriteByte( pos | 0x80, 0);}
Hello,
I would have one criticism of the attached code. The LCD connections occupy PTA0 to PTA5 in the example. This leaves PTA6 and PTA7 that may be used for other purposes. However, the sample code does not preserve the previous state of these bits but always writes a zero.
This problem can be avoided by first clearing bit 0 to 5, and then or-ing the required new state of these bits. The following modified code sample shows this process.
Additionally, the naming of the function LCDWrite8bitMode() seems a little confused to me, since only the upper nybble is actually being written (the LCD inputs for the lower nybble are actually unconnected or grounded). I prefer the alternative function name LCDWriteInit() that is used only during initialisation of the display.
/**********************************************************************/ // Used for LCD initialisation, prior to 4-bit mode currentvoid LCDWriteInit( byte data) { byte shifted; PTAD &= 0xC0; // Clear bits 0-5 PTAD |= (byte)(data >> 2); // Align data nibble to proper location PTAD |= ENBIT; // Raise EN line lcd_delay( EN_DELAY); PTAD &= ~ENBIT; // Lower EN line lcd_delay( DELAY40US); // Delay for command completion} /**********************************************************************/ // Write command/data byte// rs = 0 for command byte, otherwise data bytevoid LCDWriteByte( byte data, byte rs) { byte high, low; // Two nybbles must be separately written // High nybble: PTAD &= 0xC0; // Clear bits 0-5 if (rs) PTAD |= 0x01; // Set RS line PTAD |= (byte)((data & 0xf0) >> 2); // High nybble PTAD |= ENBIT; // Raise EN line lcd_delay( EN_DELAY); PTAD &= ~ENBIT; // Lower EN line // Low nybble: PTAD &= 0xC1; // Clear bits 1-5 (RS unchanged) PTAD |= (byte)((data & 0x0F) << 2); // Low nybble PTAD |= ENBIT; // Raise EN line lcd_delay( EN_DELAY); PTAD &= ~ENBIT; // Lower EN line lcd_delay( DELAY40US); // Delay for command completion}
Regards,
Mac
While it's generally not a bad idea to do this in general, bits A6/A7 are not pinned on the 64 pin JM, which this code was orginally written for. So it was not really an ovesight, though perhaps not the best method
It's called LCDWrite8bitMode() because the chip is still in 8 bit mode and it is actually writing 8 bit commands, so I found it to be clear. I supppose LCDSet4bitMode would have been even better.
Hello
I am trying to run this on a QG8 and a HD44780 but am unable to get it up.
I am using PTA3,PTA2,PTA1,PTA0 as data pins and PTB7 = RS , PTB6 = EN
I dont understand if i am missing the initialisation or data?
Can someone help?
Thanks and regards
EDIT : have changed the delay for 8MHz bus
Hello,
The code will obviously need to be modified to reflect that different pins on PTA are used for the data, and the RS and EN control signals originate from a different port. Perhaps you should post the modified code.
Regards,
Mac
Hi Jim
Apology to Jon for hijacking his thread.
I am interested in using this initialisation for a HD44780 module.
Forgive me if i sound very amateurish..
I included this file as LCD.c in my project and from main i init the LCD and when i add the
LCDWriteLine(char *string,byte line) inside my main ,my compiler posts a syntax error.
I declared a char string[ ] = {"test"} ; (is that right?)
Can you please educate me with the correct syntax of LCDWriteLine in main() ?
will be much appreciated
Thanks and regards
Thank you so much Jim! I greatly appreciate it. I am going to work with it and see if I can get it to work.