Jump to content
krzyk2

LCD 16x2 in 4 bit mode

Recommended Posts

Hi,

I bought a 16x2 LCD from ebay and wanted to use it in 4 bit mode, with no shift register (I'm waiting for them to come).

Maybe it will be useful to someone.

 

The LCD is LMB162ABC-1 which uses ST7066U but it should work on HD44780 drivers.

 

There is a bug in ST7066U documentation regarding 4 bit operation that was very annoying (looked for it about 2 hours). When initializing the 4 bit mode, in documentation it says that DB7/6/5/4 should be set to 0011, but actually DB4 should be set to 0, so nibble should be 0010.

 

The interface is quite simple, just three public functions demonstrated in main.c:

   lcd_init();
   lcd_goto(0,4);
   lcd_show("Hello");
   lcd_goto(1,9);
   lcd_show("world");

 

The connections to the uC:

* RS  - P1.0
* R/W - P2.0
* E   - P1.1
* DB4 - P1.2
* DB5 - P1.3
* DB6 - P1.4
* DB7 - P1.5

 

I didn't use R/W, probably I should connect it to the GND, but maybe I should try to read the busy state instead of using delay functions it would be more robust.

 

BTW. I didn't know that TP1 and TP3 can be used to get 5v from the USB, useful for 3.3v logic, 5v BL LCD :)

lcd_4bit.zip

Share this post


Link to post
Share on other sites
Hi,

I bought a 16x2 LCD from ebay and wanted to use it in 4 bit mode, with no shift register (I'm waiting for them to come).

Maybe it will be useful to someone.

 

The LCD is LMB162ABC-1 which uses ST7066U but it should work on HD44780 drivers.

 

There is a bug in ST7066U documentation regarding 4 bit operation that was very annoying (looked for it about 2 hours). When initializing the 4 bit mode, in documentation it says that DB7/6/5/4 should be set to 0011, but actually DB4 should be set to 0, so nibble should be 0010.

 

The interface is quite simple, just three public functions demonstrated in main.c:

   lcd_init();
   lcd_goto(0,4);
   lcd_show("Hello");
   lcd_goto(1,9);
   lcd_show("world");

 

The connections to the uC:

* RS  - P1.0
* R/W - P2.0
* E   - P1.1
* DB4 - P1.2
* DB5 - P1.3
* DB6 - P1.4
* DB7 - P1.5

 

I didn't use R/W, probably I should connect it to the GND, but maybe I should try to read the busy state instead of using delay functions it would be more robust.

 

BTW. I didn't know that TP1 and TP3 can be used to get 5v from the USB, useful for 3.3v logic, 5v BL LCD :)

 

Ooooh need to try this!!

 

Did not know there was an error in the documentation. Been trying to get my display working in 4 bit mode for almost a full day, without success. Eventually got too frustrated and put it in a drawer for a next session another day.

 

So first thing tomorrow im gonna test this and report back. With a big thanks if it works ofcourse :)

 

Cheers!

MarkoeZ

Share this post


Link to post
Share on other sites

This is how I do it:

void initLCD(void){
for(char t=2; t; t--){
	wrLCD(0x28,0);
	wrLCD(0x0E,0);
	wrLCD(0x01,0);
	wrLCD(0x06,0);
}
}

void wrLCD(char data, bool rs){
P1DIR |= 0x0F;
P2OUT &= ~RW;
(bools & rs) ? (P1OUT |= RS) : (P1OUT &= ~RS);
for(char two=2; two; two--){
	P1OUT &= ~0x0F;			// First clear the bits
	P1OUT |= ((data>>4) & 0x0F);		// then set the ones needed
	P1OUT |= EN;
	if(!(bools & rs)) __delay_cycles(2000);
	P1OUT &= ~EN;
	data <<=4;
}
}

void rdLCD(char* data, bool rs){
*data = 0;
P1DIR &= ~0x0F;
P2OUT |= RW;
(bools & rs) ? (P1OUT |= RS) : (P1OUT &= ~RS);
for(char two=2; two; two--){
	P1OUT |= EN;
	*data |= (P1IN & 0x0F);
	P1OUT &= ~EN;
	*data <<=4;
}
}

void sendStr(char* string) {
while(*string){	// keep going until all chars are sent
	for(char str = 0; (str<32) && *string; str++){
		switch(str & 0x1F){
		case 0x00: wrLCD(0x80, 0); break; // first line
		case 0x10: wrLCD(0xC0, 0); break; // second line
		}
		wrLCD(*string, 1);
		string++;
	}
	__delay_cycles(2000000);	// delay between screens
}
}

And this is how these are used:

initLCD();				// initialization
wrLCD('G',1);			// write one char
char temp=0;			// create temp
rdLCD(&temp,1);		// read the LCD, store the value in temp
sendStr("Hello 43oh!");	// write a string of chars

 

Edit: found a better and faster way of setting the nibble to output data.

Edit2: found a typo...

Share this post


Link to post
Share on other sites
Did not know there was an error in the documentation. Been trying to get my display working in 4 bit mode for almost a full day, without success.

If you're still struggling checking out this page, It helped me out.

http://joshuagalloway.com/lcd.html

 

Warning, there is error in that link you provided. I said so in my header of my HD44780 lib ;) The datasheet from sparkfun seem to be more accurate, but it did help me a little bit... Just don't fully trust it.

Share this post


Link to post
Share on other sites

There is a bug in ST7066U documentation regarding 4 bit operation that was very annoying (looked for it about 2 hours). When initializing the 4 bit mode, in documentation it says that DB7/6/5/4 should be set to 0011, but actually DB4 should be set to 0, so nibble should be 0010.

 

Could you give me the whereabouts of said bug? I have a feeling this is not a mistake. If you are referring to the 4 bit initialisation routine of the lcd you are supposed to send upper nibble 0x30 three times (i.e. 8 bit mode) for reasons I am not 100% sure of ( I assume it helps to bring the module up.)

You are then expected to clock upper nibble 0x20 which will be treated as 8 bit command 0x20 which will then put the lcd into 4 bit mode and you can continue from there :)

Here is a fragment of my lcd lib - I followed the datasheet and referenced http://joshuagalloway.com/lcd.html to get this working and didn't pick up on any mistakes in either.

void lcdInit(void)
{   
   /* Setup LCD pins as output - leave other pins as input */
   LCD_SET_PINS_OUTPUT();
   LCD_SET_PINS_LOW();

   LCD_STARTUP_WAIT();

   /*Set startup sequence to ensure correct initalisation of lcd*/
   /*First*/
   lcdSetUpperNibble(ST7066_START_UP_COMMAND);
   clock();
   TIME430_DELAY_MS(5UL);
   /*Second*/
   lcdSetUpperNibble(ST7066_START_UP_COMMAND);
   clock();
   TIME430_DELAY_US(200UL);
   /*Third*/
   lcdSetUpperNibble(ST7066_START_UP_COMMAND);
   clock();
   TIME430_DELAY_US(200UL);

   /*Set display to 4 bit mode*/
   LCD_SET_PINS_INSTRUCTION_WRITE();
   lcdSetUpperNibble(ST7066_FUNCTION_SET_BITS | ST7066_BIT_MODE_4);
   clock();
   LCD_COMMAND_WAIT();

   /*Set up LCD now that it is in 4 bit mode*/
   LCD_FUNCTION_SET(ST7066_BIT_MODE_4 | ST7066_LINE_MODE_2);
   LCD_CLEAR_DISPLAY();
   LCD_RETURN_HOME();
   LCD_ENTRY_MODE_SET(ST7066_MOVE_CURSOR_RIGHT); 
   LCD_DISPLAY_ON_OFF(ST7066_DISPLAY_ON);
}

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...