LCD module second line not working

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All,

I know this has been beaten to death, but I'm really stuck. Please be kind! :oops:

I'm using a ATMEGA32A connected to a Lumex LCM-S01602DTR LCD module. I can write to the first line of the display, but nothing to the second line. This module is a 16X2 LCD. I've looked at the HD44780 datasheet and searched the web for answers. I believe I'm correctly initializing the module. I even tried writing 96 characters to the module and still nothing will display on the second line. I've used a scope to probe all the lines and everything seems okay.

Here's my code snippet:


#include 
#include 
#include 

/**********************************************************
PORT Definitions
----------------
PA0 = LCD_D0
PA1 = LCD_D1
PA2 = LCD_D2
PA3 = LCD_D3
PA4 = LCD_D4
PA5 = LCD_D5
PA6 = LCD_D6
PA7 = LCD_D7

PB0 = N/C
PB1 = LCD_E
PB2 = LCD_RS
PB3 = LCD_RW
PB4 = N/C

***********************************************************/

void lcd_e_high(void) {
  PORTB |= 0b00000010;
}

void lcd_e_low(void) {
  PORTB &= ~0b00000010;
}

void lcd_rs_high(void) {
  PORTB |= 0b00000100;
}

void lcd_rs_low(void) {
  PORTB &= ~0b00000100;
}

void lcd_rw_high(void) {
  PORTB |= 0b00001000;
}

void lcd_rw_low(void) {
  PORTB &= ~0b00001000;
}

void lcd_write_cmd(uint8_t x) {
  lcd_rs_low();
  lcd_rw_low();
  PORTA = x;

  _delay_us(1);
  lcd_e_high();

  _delay_us(1);
  lcd_e_low();

  _delay_us(1);
  lcd_rw_high();

  _delay_us(1);
}

void lcd_write_data(uint8_t x) {
  lcd_rs_high();
  lcd_rw_low();
  PORTA = x;

  _delay_us(1);
  lcd_e_high();

  _delay_us(1);
  lcd_e_low();

  _delay_us(1);
  lcd_rw_high();

  _delay_us(40);
}

void lcd_clear_display(void) {
  lcd_write_cmd(0b00000001);
  _delay_ms(5);
}

void lcd_return_home(void) {
  lcd_write_cmd(0b00000010);
  _delay_ms(2);
}

void lcd_entry_mode_set(uint8_t ID, uint8_t S) {
  lcd_write_cmd( (0b00000100) | (ID<<1) | (S) );
  _delay_us(40);
}

void lcd_display_on_off_control(uint8_t D, uint8_t C, uint8_t B) {
  lcd_write_cmd( (0b00001000) | (D<<2) | (C<<1) | (B) );
  _delay_us(40);
}

void lcd_cursor_or_display_shift(uint8_t SC, uint8_t RL) {
  lcd_write_cmd( (0b00010000) | (SC<<3) | (RL<<2) );
  _delay_us(40);
}

void lcd_function_set(uint8_t DL, uint8_t N, uint8_t F) {
  lcd_write_cmd( (0b00100000) | (DL<<4) | (N<<3) | (F<<2) );
  _delay_us(40);
}

void lcd_set_cgram_address(uint8_t ACG) {
  lcd_write_cmd( (0b01000000) | (ACG) );
  _delay_us(120);
}

void lcd_set_ddram_address(uint8_t ADD) {
  lcd_write_cmd( (0b10000000) | (ADD) );
  _delay_us(120);
}

void lcd_init(void) {
  _delay_ms(50);
  lcd_write_cmd(0b00110000);  // interface is 8 bits

  _delay_ms(5);
  lcd_write_cmd(0b00110000);  // interface is 8 bits

  _delay_us(200);
  lcd_write_cmd(0b00110000);  // interface is 8 bits

  lcd_function_set(1, 1, 0);  // 8-bits, 2-lines, 5x8 dots

  lcd_display_on_off_control(0, 0, 0);  // display off, cursor off, blink off

  lcd_clear_display();  // clear display

  lcd_entry_mode_set(1, 0);  // increment DDRAM address, no shift

  lcd_display_on_off_control(1, 0, 0);  // display on, cursor off, blink off

}

////////////////////////////////////////////////////////////
// displayString
////////////////////////////////////////////////////////////
void displayString ( char *c ) {

  int8_t n = 0;

  while( (n<16) && (c[n]!='\0') ) {
    lcd_write_data( c[n] );
    n++;
  }
}

int16_t main() {

    ////////////////////////////////////////////////////////////
  // setup device
  ////////////////////////////////////////////////////////////
  PORTsetup();
  TIMERsetup();
  sei();  // enable interrupts

  ////////////////////////////////////////////////////////////
  // display version
  ////////////////////////////////////////////////////////////
  lcd_init();
  displayString(VERSION);
  lcd_set_ddram_address(0x40);
  displayString( "Searching..." );

[snip]
}

I must be doing some things right otherwise, I wouldn't be able to display anything. But, obviously something is wrong.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not all 2nd lines start at 0x40. Try writing a for() loop that deposits characters into display RAM for a whole range of addresses and when something appears you should be able to work back to which address to use for line 2.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Not all 2nd lines start at 0x40. Try writing a for() loop that deposits characters into display RAM for a whole range of addresses and when something appears you should be able to work back to which address to use for line 2.

I tried that and it still didn't work.

I did something like this:

int i;
for(i=0; i<96; i++) {
  lcd_write_data( 0x55 );
}

This should write 96 'U' characters to the display. I see them on the first line, still nothing on the second line.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So you decided to stop at 95/0x5f because...?

unsigned char i;
for(i=0x20; i<0xff; i++) {
  lcd_write_data( i&0x7f ); // limit to normal displayable characters
} 

...which still has a gap perhaps.

Or just to get something...

unsigned char i;
for(i=0x20; i<0xff; i++) {
  lcd_write_data( (i&0x0f)+'A' ); // limit to normal displayable characters
} 

It is strange, though. The so-called datasheet doesn't even give the controller type or the memory addresses.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

_delay_us(200);
  lcd_write_cmd(0b00110000);  // interface is 8 bits

  lcd_function_set(1, 1, 0);  // 8-bits, 2-lines, 5x8 dots

There is not enough time between these two commands?
Everywhere else you do delay for 40us or more.
So it just ignores the command and stays in 8-bit mode with 1 line only.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Eagle Eyes!

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
There is not enough time between these two commands?
Everywhere else you do delay for 40us or more.
So it just ignores the command and stays in 8-bit mode with 1 line only.

Actually he is carefully following the data sheet which does not call for a delay after that mode change command. I think that omission (in the data sheet) is a mistake and I generally use 100uS, the same as for the previous reset command.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
Quote:

_delay_us(200);
  lcd_write_cmd(0b00110000);  // interface is 8 bits

  lcd_function_set(1, 1, 0);  // 8-bits, 2-lines, 5x8 dots

There is not enough time between these two commands?
Everywhere else you do delay for 40us or more.
So it just ignores the command and stays in 8-bit mode with 1 line only.

Dude, you nailed it. :D Thank you. Thank you. I made the mistake of not adding enough delay for the lcd_write_cmd function.

Here's the updated version:

void lcd_write_cmd(uint8_t x) {
  lcd_rs_low();
  lcd_rw_low();
  PORTA = x;

  _delay_us(1);
  lcd_e_high();

  _delay_us(1);
  lcd_e_low();

  _delay_us(1);
  lcd_rw_high();

  _delay_us(40);  // <--this was only 1us!
}

You're right. The module must have been ignoring this command. Now, it works! :D :D :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:

Actually he is carefully following the data sheet which does not call for a delay after that mode change command. I think that omission (in the data sheet) is a mistake and I generally use 100uS, the same as for the previous reset command.

Don

Huh? The command always has an execution time of about 40us, no matter what. Every LCD datasheet says this and HD44780 controller datasheet too, in the command list.

The part where the manual initializations are, have extra delays due to very good reason in the first commands, but the other initialization commands do not call for extra delays, so the normal delays are expected even it does not explicitly say to include them.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
floresta1212 wrote:

Actually he is carefully following the data sheet which does not call for a delay after that mode change command. I think that omission (in the data sheet) is a mistake and I generally use 100uS, the same as for the previous reset command.

Don

Huh? The command always has an execution time of about 40us, no matter what. Every LCD datasheet says this and HD44780 controller datasheet too, in the command list.

The part where the manual initializations are, have extra delays due to very good reason in the first commands, but the other initialization commands do not call for extra delays, so the normal delays are expected even it does not explicitly say to include them.


But we ARE talking about the initialization phase. Specifically we are talking about the command that changes the device from the 8-bit mode to the 4-bit mode which is most assuredly part of the initialization.

By the way - I think we both agree that he left out a required delay. I am merely stating that he probably left it out because the data sheet (mistakenly) left it out.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

because the data sheet (mistakenly) left it out.

You mean the datasheet that doesn't even tell what kind of controller is being used?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:

But we ARE talking about the initialization phase. Specifically we are talking about the command that changes the device from the 8-bit mode to the 4-bit mode which is most assuredly part of the initialization.

By the way - I think we both agree that he left out a required delay. I am merely stating that he probably left it out because the data sheet (mistakenly) left it out.

Don

Yes we do agree.

The datasheet I have open here is from http://lcd-linux.sourceforge.net/pdfdocs/hd44780.pdf. What datasheet you have?

If you would like to still continue, I don't get what delay is supposed to be missing - all the initialization commands expect the required execution time which is not explicitly stated, plus the extra delays that are explicitly stated.

Regarding figures 23 and 24 that is.

Only thing missing is the execution time of Clear Display command in Table 6.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
You mean the datasheet that doesn't even tell what kind of controller is being used?
I am talking about the datasheet for the HD44780U which IS the controller. The page number may vary but the flowchart on my copy is Figure 24 for the 4-bit Interface.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am talking about the datasheet for the HD44780U which IS the controller.

How did you determine that? Do you happen to have one of the modules and the controller isn't covered with a black blob?

Now I'm curious, and back to the Lumex Web site. I didn't see the controller mentioned on the page for the particular model where there is a link to the "datasheet". Perhaps in a product selector table? ... Can't find it.

Next you are going to say that they are all created equal. But I was just taken to task about that in a thread a few weeks back about using the timing/delay vs. the busy method for character LCD interfacing.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes we do mostly agree. What I find ambiguous is the fact that the box next to the third 0011 command says that the BF cannot be checked before this instruction. This implies that the BF can be checked after that instruction.

Now look at the box next to the 0010 command. It says that the BF can be checked AFTER the following instructions which would imply that the BF cannot be checked before those instructions.

So for the period after the third 0011 reset and before the 0010 mode change we have one implication that the BF can be checked and another implication that it cannot be checked.

I tend to agree with the second choice because this is not a normal function set instruction any more than the two previous 0011 instructions were. For this reason I don't think there should be any expectation that the delay for a normal Function set would be appropriate.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
How did you determine that? Do you happen to have one of the modules and the controller isn't covered with a black blob?
Yes I do. I am old and so are my LCD displays. You can look at the flowchart on virtually any datasheet and it will be essentially the same if not identical to the one we are discussing.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Next you are going to say that they are all created equal. But I was just taken to task about that in a thread a few weeks back about using the timing/delay vs. the busy method for character LCD interfacing.
I missed this part. We are talking about the never-never land between where you have to use specific delays and where you can use the BF or a time delay. Every data sheet that I have seen is ambiguous about this point, probably since they all derive from the mother of all data sheets, the one we are discussing.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The reason BF cannot be checked in those flowcharts is simple.

Let us take an example where AVR uses 4-bit interface to LCD.

Now the AVR must set the LCD to 4-bit interface after power-on, and all works happily. Now what happens when you push the reset button?

Your AVR does not know if the display is in 8-bit mode or 4-bit mode. And if in 4-bit mode, is it expecting the first nibble or the second nibble. Therefore, you must first set it into known state, which is 8-bit mode, before setting it back to 4-bit mode.

If the LCD is in 8-bit mode after power-up, all it sees is three commands requesting to set 8-bit mode, although lower bits of the nibble is garbage, so after the fourth 8-bit command the display is in 4-bit mode so the fifth command is first 4-bit command to set both high and low nybble correctly.

If the LCD is in 4-bit mode, expecting high nybble, first and second commands it sees as high and low nibble telling it to go into 8-bit mode, following the third command to go into 8-bit mode. Now fourth and fifth command again are same as after power-up.

If the LCD is in 4-bit mode, expecting low nybble, the first command is unknown so its execution time is unknown. Then second and third command are the two nybbles of a 4-bit command, telling the display to go into 8-bit mode. Fourth and fifth are then again same as previously.

So this is why busy flag cannot be read - you don't know what state the LCD is in, you have to blindly configure it to the bus length you are using.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael:

There's one more factor that you should consider. I don't think it conflicts with anything you have said and you may be able to work it into your reasoning as well. Look at the note that accompanies the explanation of the Function Set instruction a few pages after Table 6.

Quote:
Note: Perform the function at the head of the program before executing any instructions (except for the read busy flag and address instruction). From this point, the function set instruction cannot be executed unless the interface data length is changed.

This essentially says that the Function Set instruction should only be implemented once. When you send it several times, as is done during the initialization sequence, it is a clear indication to the controller that something other than a real function set is intended. No matter what mode the controller happens to be in, and no matter whether it is expecting a high or low nibble when you start, this sequence will be interpreted as more than one sequential 'Function Set' and therefore illegal.

There is still the question of where you can start reading the BF. You definitely cannot use it before the third 0011 and you definitely can use it after the real Function Set in either mode and also after the 0010 mode change to the 4-bit mode. There is still the question of whether the BF can legitimately be used after the third 0011 instruction. I wouldn't count on it and I would stick with a delay longer than 40 uS as well.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow. It looks like I started quite a thread. :shock:

I searched and searched and couldn't find which controller is used. I assumed it was THE standard HD44780 compatible one. But, Lumex isn't talking!

I did miss the needed delay in the lcd_write_cmd function. In the init routine, I did add the extra delays needed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I assumed it was THE standard HD44780 compatible one.
That's a good assumption when you don't know for sure.

Quote:
In the init routine, I did add the extra delays needed.
How much did you add, and where?

Your 'Function set' is obviously the problem so either the bits are wrong or the timing is off. You might want to temporarily simplify things by just setting the desired bits (without shifting) and use a longer time delay before and after the instruction and see what happens.

Quote:
I even tried writing 96 characters to the module and still nothing will display on the second line.
This is a good technique, but use exactly 80 characters and make sure they are all printable.

What are the delays for at the end of 'lcd_write_cmd' and 'lcd_write_data' and why are they different?

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:
Jepael:

There's one more factor that you should consider. I don't think it conflicts with anything you have said and you may be able to work it into your reasoning as well. Look at the note that accompanies the explanation of the Function Set instruction a few pages after Table 6.

Quote:
Note: Perform the function at the head of the program before executing any instructions (except for the read busy flag and address instruction). From this point, the function set instruction cannot be executed unless the interface data length is changed.

This essentially says that the Function Set instruction should only be implemented once. When you send it several times, as is done during the initialization sequence, it is a clear indication to the controller that something other than a real function set is intended. No matter what mode the controller happens to be in, and no matter whether it is expecting a high or low nibble when you start, this sequence will be interpreted as more than one sequential 'Function Set' and therefore illegal.

There is still the question of where you can start reading the BF. You definitely cannot use it before the third 0011 and you definitely can use it after the real Function Set in either mode and also after the 0010 mode change to the 4-bit mode. There is still the question of whether the BF can legitimately be used after the third 0011 instruction. I wouldn't count on it and I would stick with a delay longer than 40 uS as well.

Don

Hey that is a good note about function set. But I don't see sending multiple Function Set commands as being illegal, the LCD may just ignore Function Set commands if DL does not change. I think I have occasionally wondered why the display won't change the font, it may be due to this.

But if further Function Set instructions are sent with same DL bit, the initialization sequences could not work. For example, there are multiple occasions where Function Set is called many times in a row to get into correct bus mode (8-bit or 4-bit), and only the final Function Set has also the correct N and F bits, while DL bit does not change. Now that is weird, and I don't have a clue how this all fits in.

I'll have to think about the Busy Flag stuff a bit more, I have never actually used it so I have no first hand knowledge. Or if I did, not from that many different LCD controllers, I am not sure if I even currently have any displays with a real HD44780 controller.

Anyway, thank you for the discussion, maybe we should continue this in General Electronics, as this is already off-topic :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:
That's a good assumption when you don't know for sure.

How much did you add, and where?

Your 'Function set' is obviously the problem so either the bits are wrong or the timing is off. You might want to temporarily simplify things by just setting the desired bits (without shifting) and use a longer time delay before and after the instruction and see what happens.

This is a good technique, but use exactly 80 characters and make sure they are all printable.

What are the delays for at the end of 'lcd_write_cmd' and 'lcd_write_data' and why are they different?

Don

If you look at my original code in the lcd_init routine, you'll see I have delays added between the first three calls. What I missed was in the lcd_write_cmd routine. I had only a 1us delay. This needed to be 40us. The delays for lcd_write_cmd and lcd_write_data should be the same and now they are.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The delays for lcd_write_cmd and lcd_write_data should be the same and now they are.
I'm sorry - I missed where you said that the first time!

Don