display lcd 4bits

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Good morning everyone. I am trying to write a code to a 4 bit lcd interface. The first line is normal, however, I can not type in the second line, ie only the small line appears in the lcd.
 If anyone can help from now thank you.
follow the code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

void puls_enable(){
	PORTB |=  (0x01);//ON Enable
	_delay_us(1);
	PORTB &=~ (0x01);//OFF Enable
	_delay_us(45);
}
void lcd_cmd (char cmd)
{
	puls_enable();
	PORTB &=~ (0x02);//RS as a command or instruction
	PORTD = (cmd & 0xF0);
	puls_enable();
	PORTD = ((cmd << 4) & 0xF0);
	puls_enable();
}
void lcd_data(unsigned char data){
	PORTB |= (0x02);//RS as a data or character
	PORTD = (PORTD & 0x0F) | (data & 0xF0);
	puls_enable();
	PORTD = (PORTD & 0x0F) | (data << 4);
	puls_enable();
}
void lcd_int(){
	lcd_cmd(0x02);
	lcd_cmd(0x28);
	lcd_cmd(0x0F);//Display ON, Cursor ON
	lcd_cmd(0x01);//Clear Display
}
void lcd_str(char *str){
	while(*str)
	lcd_data(*str++);
}
int main(void)
{
	DDRB=0xFF;
	DDRD=0xFF;
	lcd_int();

	while(1){
		lcd_cmd(0x80);//Line 1
		lcd_str("AVR:");//Line 2
		lcd_cmd(0xC0);//Line 2
		lcd_str("ATMEGA");//Line 1

	}
}

 

This topic has a solution.

Marcelo

Last Edited: Sun. Dec 24, 2017 - 04:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since this is not an issue with Studio, and there is no mention of which AVR being used, I'll move this to general programming

Has the OP searched the hundreds of prior threads here on this subject?

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
I need a review of my code to see what's wrong since I can not type in the second line of the display

Marcelo

Last Edited: Fri. Dec 22, 2017 - 02:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

your initialisation is suspect and this function is suspect:

void lcd_cmd (char cmd)
{
	puls_enable();//why??
	PORTB &=~ (0x02);//RS as a command or instruction
	PORTD = (cmd & 0xF0);
	puls_enable();
	PORTD = ((cmd << 4) & 0xF0);
	puls_enable();
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

uthacod wrote:
I need a review of my code to see what's wrong since I can not type in the second line of the display

LCDs are S L O W moving animals and your code has no delays in the INIT code, nor do you have any way of knowing that the LCD is ready for another character of data.  I suspect that the LCD can display the first line and misses the second because it is not able to keep up with the AVR

 

If you do a search I have posted several times a small demo project for 4 bit LCD interfacing that will allow you to confirm that your display works properly, and that you have your connections correct...which it looks like you do if the first line works.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Your initialization is not just suspect as previously mentioned, it is wrong.  Have you looked at the flow charts in the HD44780U data sheet?  For a complete explanation of those flow charts follow the LCD Initialization link at http://web.alfredstate.edu/faculty/weimandn .  In the US this page pops right up in a Google search for 'LCD Initialization'.

 

Your first row of characters is displaying because the default initialization, which is in effect since yours doesn't work, sets the device up as a 1-line display.

 

Don

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

I created a boot subroutine according to the datasheet and it did not work

void init(){
 _delay_ms(20);  //delay > 15 ms
 lcd_cmd(0x03);
 _delay_ms(5);   //delay > 4.1 ms
 _delay_us(200); //delay > 100 us
 lcd_cmd(0x02);  //Interface is 4 bits
 lcd_cmd(0x28);
 lcd_cmd(0x08);  //Display off
 lcd_cmd(0x01);  //Display clear
 lcd_cmd(0x0C);  //cursor off
 lcd_cmd(0x80);  //initializes cursor in the first position on the left
}
I have help. DISPLAY LM016L

Marcelo

Last Edited: Fri. Dec 22, 2017 - 03:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What AVR are you using, what clock frequency, and what port(s) are you connecting the LCD to?

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

It appears your lcd_cmd function ALWAYs issues two writes.

When the LCD powers up, it is in 8-bit mode, and will not "understand" that second write.

For initialization, the command 0x3X is to be sent 3 times with timing between them...

After initialization, the two writes are used to transfer the 8-bits, 4-bits at a time.

 

David (aka frog_jr)

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

jgmdesign wrote:

What AVR are you using, what clock frequency, and what port(s) are you connecting the LCD to?

 

JIm

AVR = ATMEGA 328P

PORTD = DATA

PORTB = CONTROL

simulation = isis proteus

Marcelo

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

That initialization sequence is still not correct.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

uthacod wrote:

jgmdesign wrote:

What AVR are you using, what clock frequency, and what port(s) are you connecting the LCD to?

 

JIm

AVR = ATMEGA 328P

PORTD = DATA

PORTB = CONTROL

simulation = isis proteus

What clock frequency?

 

Jim

 

Edit:

And what LCD pins are connected to what port pins?

 

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

frog_jr wrote:
It appears your lcd_cmd function ALWAYs issues two writes.

+1

 

Let's flesh out:

 

The stipulated init sequence is 3 instructions 0x20 (Function Set, 8-bit interface) with specific wait times. After that the Function Set instruction to switch to 4-bit mode, 0x30, can be sent. Since the low nibble of those instructions is not significant it is only the high nibble that needs to be sent to the LCD (onto LCD pins DB7..4). This insignificance of the lower nibble of the basic Function Set instruction is what makes it possible to communicate with an LCD in 8-bit mode having only 4 data lines attached, and switch it to 4-bit mode.

 

This "trick" is the key to understanding a proper init sequence that sets the display into 4-bit mode.

 

Now, the latest init in (post #7) starts out

void init(){
 _delay_ms(20);  //delay > 15 ms
 lcd_cmd(0x03);

Looking at what lcd_cmd() does we can see that this will mean that these two nibbles will be sent to the LCD ( PORTD pins 7..4 to LCD pind DB7..4), one after the other:

0x3

0x0

 

So the init sequence is broken already here.

 

A proper init sequence sends the nibble 0x3 three times on the LCDs pins DB7..4, with stipulated waits. Without using "special tricks" (which obfuscates the code, so let's keep those tricks out of the picture) a 4-bit init needs to have an explicit function for sending of a nibble (in addition to the function(s) for sending a complete byte.

 

So something like this (for all code below: NOT tested, sketchy):

 

void lcd_cmd_high_nibble (char cmd)
{
	PORTB &=~ (0x02);//RS as a command or instruction
	PORTD = (cmd & 0xF0);
	puls_enable();
}

which then allows us to do a proper init sequence:

void init(){
 // The soft reset is a sequence of 3 Function Set instructions 
 // with stipulated timings. It is only the high nibble of these
 // instructions that are significant so therefore we send only
 // the high nibble of the instruction to pins DB7..4 of the LCD
 _delay_ms(20);             //delay > 15 ms
 lcd_cmd_high_nibble(0x30); // Function Set, 8-bit interface
 _delay_ms(5);              //delay > 4.1 ms
 lcd_cmd_high_nibble(0x30); // Function Set, 8-bit interface
 _delay_us(200);            //delay > 100 us
 lcd_cmd_high_nibble(0x30); // Function Set, 8-bit interface
 
 // Still in 8-bit mode, now send the instruction to switch
 // to 4-bit interface
 lcd_cmd_high_nibble(0x20); // Function Set, 4-bit interface

 
 // Only now is the display in 4-bit mode and take 8-bit 
 // commands/data in two consecutive nibbles. Do the rest
 // of the init sequence:
 
 lcd_cmd(0x28);             // Function set, 4-bit interface, 2 lines
 lcd_cmd(0x08);             // Display off
 lcd_cmd(0x01);             // Display clear
 lcd_cmd(0x0C);             // Display on, cursor off, no blink
 lcd_cmd(0x80);             // Cursor home
}

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:
Let's flesh out:
Let's not, a lot of us need to be on diets!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
A proper init sequence sends the nibble 0x3 three times on the LCDs pins DB7..4, with stipulated waits. Without using "special tricks" (which obfuscates the code, so let's keep those tricks out of the picture) a 4-bit init needs to have an explicit function for sending of a nibble (in addition to the function(s) for sending a complete byte.   So something like this (for all code below: NOT tested, sketchy):

Thank you very much. Following this tip I was able to solve the problem by adjusting my code according to the instructions given.

Marcelo

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

You would have found the information in that tip a bit sooner if you had followed the link  in reply #6.

 

Don

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

Guess I can put that demo code I was setting up back in the file folder then.

 

Good to read it's working.  Please tag a post you feel was the answer

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user