Tutorial for HD44780-LCD and similar.
Following an easy, universal and code saving example.

1.
There are different ways to control the LCD. You can use the 8bit mode with busy testing or the 4bit mode with busy waiting.

On busy waiting a character need about 50Âµs to be transmitted. But nobody was able to read a character within 50Âµs.
E.g. a digital meter display only up to 5 measurements per second, which was good readable. So a 200ms update rate was also an ergonomic value for our display.
Then e.g. for a 2*16 LCD this result in a CPU load of:
50Âµs * 32 / 200ms = 0.8%.
So the 4bit mode with busy waiting may cause no remarkable CPU load.
But it need only 6 IO-pins, so there is no reason to waste 5 IO-pins more on using the 8bit mode with busy testing.

Thus we need the following 6 LCD-lines connected to the AVR:
DB7, DB6, DB5, DB4, RS and E.
The RW-line must be connected to GND. Forget not the contrast input connected according to the datasheet of your LCD. On some LCD it can be connected to GND, but some others may need a negative voltage on it!
The DB3, DB2, DB1 and DB0 lines may be connected to GND.

2.
The next point was, that the LCD should use any 6 IO-pins, even if not on the same 8bit port. Since it make the pcb easier and allow still to use special functions (UART, I2C, timer, ...) of certain IO-pins.
To do so, we need a simple way to define single IO-pins.
This can be done easily with the following macro:

3.
Now we can start to do the code.
On looking on the HD44780 datasheet, we can see, that we must send a nibble (4bit) and then pulse the E-line high and low. This was the basic step on all sending and thus we write our first function for it.
We input a byte, where are only the upper 4 bits are used and set the 4 IO-lines to the LCD accordingly. Then the E-line was pulsed for about 1Âµs:

Now we are ready to intialize the LCD. At first we must set the 6 IO-pins as outputs. Then we should follow the order for initialization of the 4bit mode according to the data sheet. Why should we try to set the 8bit mode first?
After a clean power on reset the LCD should be in the 8bit mode. But after slowly rising power or a reset by another source (manual knob, watchdog), the state was unknown.
So the only chance to turn the LCD into a known state, was to set the 8bit mode first. Since this may fail, if the LCD was in the 4bit mode and awaiting the second nibble, it must be tried two times.

Some additional functions:
lcd_puts(): display a string until zero byte
ldc_xy(): set the cursor to x (column), y (line)
ldc_blank: overwrite a piece of the LCD with blanks

Why lcd_xy was implemented as macro?
Since typically the position was known at compile time, it's code saving, if the command was already calculated at compile time also.

Why no clear command?
On using the clear command you see always an annoying flicker until the text was written again. Thus it looks many more professional, if you omit this command and simple overwrite the old text with the new text.

In the data sheet there is no delay specified after the third 0x30 of the initialization sequence or for the following 0x20. I believe that this omission is an editorial error in the flowchart since it would be unusual for a processor to be able to deal with these two instructions in zero time while all the others have some specified minimum time requirement. I generally play it safe and use 100uS as specified for the preceding 0x30.

Have you tried your cursor positioning technique on any of the 4 line displays?

hi i use this lib for atmega128rfa1...when i program exactly your file and program atmega128rfa1 it is work fine:)...
but! when i used it in the wsndemo application(bitcloud) avr studio give me this error:
./include/main.h:12:1: warning: "F_CPU" redefined
please guide me what can i do to solve this problem.thanks

Huh?!? In general, or in the specific case of using dannis code? He states as an explicit requirement that the case of pins being on different ports should be handled.

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]

There are two methods for determining whether or not the LCD is ready for the next command. One is to delay long enough to know that the LCD has had time to process whatever it was doing. The other is to poll the LCDs busy flag. Busy testing refers to the second method.

dist= distance. I wish to display value of distance. but i know lcd_puts, puts out only character, in this case probably the character of distance's value. Instead of the chracter, I want to display the actual value in numbers of dist. May someone enlighten me on how to do this?
thank you very much.

If you want to print a human readable number, you have to convert it to a string. Them you can output the string. Note that your string buffer must have enough room to hold the biggest number and its terminating NUL.

You can use itoa(), utoa(), ftoa(), dtostrf(), ... and other non-standard functions.
There should always be sprintf() but many AVR compilers default to a 'small' sprintf() that may not handle floats or precision.

As this has RS=0 it is a "command" rather than data. So send it using lcd_command(). That is:

lcd_command(0x01);

I guess you may want to:

#define CLEAR_DISPLAY 0x01

nexaen wrote:

How to clear a specific row of screen?

The HD44780 doesn't have a command to do this specifically so just lcd_goto() the start of the line in question then print a string of 16 or 20 (or however many) spaces to over-write everything already on that line.

If your library has got lcd_puts() I bet that it has lcd_clear() of some description.
I strongly advise that you use the library function rather than send the low level command.
.
If you are determined to use lcd_command(0x01), add a delay_ms(2) to ensure that it has enough time.
.
Mind you, if you just want to clear one line: just gotoxy() , puts(" "), gotoxy() back to the start.
This will be quicker and do what you actually want.

Just have a look at e.g. his init code in the first post. See where he's doing

lcd_command( 0x01 ); // display clear

?

If you want to hide that behind a function name, just go ahead. :-)

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]

Keep your questions in your thread, and provide a link to this tutorial.

Keep in mind your breadboard wiring is a mess based on that video you posted, so you might want to check your connections. Also what port(s) is danni using? This was an issue with you as well due to your bootloader needing the TX and RX pins.

JIm

EDIT:

I modified DAnni's code to operate using the same pins I used for my example in your other thread and it worked right out of the gate. I have attached it to this post, and will place another copy in your other thread. The HEX file is in the debug folder.