LCD module and AVR

Go To Last Post
91 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I have a LCD module which uses the ks0066u driver.

I have a tutorial for LCD modules that is for the Hitachi HD44780.

I'm trying to drive the LCD module with a AVR but the first commands i'm trying are not doing a thing.

My question is that if the commands for the HD44780 driver are the same for the ks0066u driver.

Thx,

Best regards,

Nuno

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

Yes, ks0066u is compatible with HD44780. I just heard in my LCD topic today. http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=44813

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

I have taken an overview of ks0066u & seems that they are the same. Your first inclination should be that it works and believe that it will work.

Be a bit elaborative on your post. This is a wonderful forum. You will get the answer

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

Oops a bit late

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

Maybe you should read my topic, see my previous reply.

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

Quote:

Yes, ks0066u is compatible with HD44780.

Careful! Although 44780 clones probably are identical in most aspects differences might occur. Look especially for differences in timing constraints and (IIRC) slight differences in the init sequence.

My two favourite 44780 documents can be found here:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=116409#116409(PDFs in ZIP files)

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

Hi,

If you are talking about "how to intelligent lcds" then is what i have.

I doing precisly the first things that they sugest to do in the experimental rig, even before using a micro processor.

But i'm trying to do this with a micro.

#include 
#include 
#define F_CPU 10000000
#include 

int main( void ) {
	
	DDRC = 0xFF;
	DDRD = 0xFF;

	PORTC = 0x00;
	PORTD = 0x38;

	PORTC = 4;
	return 0;
}

I'm trying to have a flashing cursor with underline

I have the LCD data lines connected to the PORTD bits and the other 3 connected to the first 3 bits of PORTC.

But nothing happens in the LCD.

The only thing i got its the same i got when i power it up... The second full of total black dots.

I have a 2x16 LCD.

Do you guys think this is because of the timings that i'm not using?

Cheers,

Nuno

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

The good thing is that the LCD seems to be OK. The bad thing is that what do you have is exactly what appears when initialization is not correct. Also need to adjust the contrast.

More bad news: I had played a lot with other kind of LCD (mainly graphical), but not too much with alphanumeric ones. But what I could say is that the later ones, altough more usually standard and attached to the HD44780 'standard' lack in a big point: the timming is usually critical and the intialization, although always the same parameters, quite complex (about the same than graphic LCD's, but with the timming issue) and dependant on the timming, that often is different.

Better take a look to others code, and check with different timmings/delays.

Guillem.

Guillem.
"Common sense is the least common of the senses" Anonymous.

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

There are lots of example codes out there that you can have a look at!
If you want to write it all from scratch that's fine, but the timings ARE critical, you cannot write too slow to the display though, so you can always use trial and error. (You can use a dip-switch to write to it by hand actually)

Another thing, unless you are actually going to read data from the display (i've never used it), you can tie the R/W pin of the LCD to ground and save a I/O pin on the micro.

There is also the possibility to use 4-bit mode, that way you can save another 4 pins on the micro, i think most people use their HD44780's in 4 bit mode! That way you can do it all with just one port! But for starters the 8-bit mode is by far the easiest way to communicate with the LCD. :)

Brian

- Brian

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

Hi,

Where can i get the codevision lcd functions?

Cheers,

Nuno

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

With the Codevision compiler/toolchain maybe? Google puts http://www.codevision.be/ up as the very first hit when I search for Codevision. From there I downloaded the evaluation version.

From what I see the LCD functions are delivered as binaries only - no source code. The code snippet above looks like AVR-GCC, and if that is the compiler you are using then no CV binary will help you.

My suggestion is to read up on a proper init sequence, and for that you need a data sheet for the KS0066U. When I Google for that the very first hit points to a PDF which seems to be the thing On p 26-27 the proper init sequences are described.

Assuming that the init sequences for a 44780 and a KS066U are similar I'd say that the code in the post above is not a proper init sequence. Many display controllers will init without a proper init sequence, but for that to happend certain requirements exist for the electrical characteristics of the power-up sequence. Again, you should turn to the proper data sheet to determine how to acheieve this, if at all possible.

And finally: You should learn how to make use of the search functionality here. Init of LCDs has been discussed many many times. This is just one example (that might give you some clues/hints): http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=209301#209301. A thorough search should reveal more threads similar to that one.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

Hi,

I have the proper datasheet but it only confuses me more.

In the initialization it tell to:

1 - Display clear instruction: write 0x20 to all DDRAM.

DDRAM is the data bits?

2 - Set function instruction:
DL = High
N = Low
F = Low

What is DL, N and F?

I was expecting to hear about RS,R/W,E

and the remaing steps i have the same problem in understand what this letter mean.

In the tutorial i told me about, that is the one i got in the hand experimental prototype it says to put data lines with the value "0x0F" and make RS switch 0 to receive command.
And then to put E high. Well, i'm supposed to see a flashing cursor...

I gave a lot of time because when we do this by hand its completly different:

#include 
#include 
#define F_CPU 10000000
#include 

int main( void ) {
	
	DDRC = 0xFF;
	DDRD = 0xFF;

	PORTC = 0x00;
	PORTD = 0x0F;

	_delay_ms(500);

	PORTC = 0x04;

	while(1);

	return 0;
}

You are right! I'll do some search around.

Thx,

Nuno

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

The following code is for the HD44780 based LCD. It is using 8 bit mode and R/W is forced low all of the time as, it depends on fixed delays and not the READY status flag of the display.

The initialization is a bit off-standard from the HD44780 datasheet but, I've never had an LCD not work properly because of this in more then 12 years. The timing of the RS & E to the presentation of the DATA are as per the HD44780 datasheet. The delays will have to be increased if a crystal greater the 8.000 MHz is used on the target microcontroller. Though, if a lower frequency crystal is used, all delays can remain the same.

For the record, this particulay rendition of LCD code is a result of some preliminary work that I was involved with when Johan was working on his LCD display tutorial. This code is different enough that, it should not impenge on the code that Johan has been developing.

For you that think this code is un-orthodox, it might be, but, it has been working flawlessly and I stand by it as it applies to the ImageCraft ICCAVR v7.xx C compiler.

No guarantees of proper operation are offered for the other standard C complier flavors that are out there.

// My_LCD.c

// Compiler: ImageCraft ICCAVR v7.xx
// Crystal: 8.000 MHz
// Data: PORTA
// Control: PORTB
// RS = PORTB, bit 0, 0x01
// RW = PORTB, bit 1, 0x02
// E = PORTB, bit 2, 0x04

#include 

// Define LCD Register Select as PORTB, 0x01;
#define LCD_RS 0
// Define LCD Read/Write as PORTB, 0x02;  
#define LCD_RW 1
// Define LCD Enable as PORTB, 0x04;  
#define LCD_E 2   

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define	PWR_CMD	0x0C
// SET FOUR LINE, 8 DATA BIT MODE		
#define	DL_CMD	0x38
// CLEAR DISPLAY COMMAND		
#define CLR_DSP 0x01

#define LINE1 0x80
#define LINE2 0xC0
#define LINE3 0x94
#define LINE4 0xD4

#define NULL 0x00

const char BANNER_1[] = {"Having Fun"};
const char BANNER_2[] = {"With LCD's"};
const char BANNER_3[] = {"By"};
const char BANNER_4[] = {"Carl W. Livingston"};

void LCD_Delay (unsigned long int d);
void LCD_IO_INIT (void);
void LCD_INIT (void);
void LCD_PutCmd (char);
void LCD_PutChar (char); 
void LCD_PutString (const char *);

void main (void)
{
 	LCD_IO_INIT ();
	LCD_INIT ();
	
	while(1)
	{
	    // Add other LCD related program operations here...
	}			
}

void LCD_Delay (unsigned long int d)
{
    unsigned long int n;
    for (n = 0; n < d; n++);
} 

void LCD_IO_INIT (void)
{
    DDRA = 0xFF; // PORTA is the LCD DATA LINES
    PORTA = 0x00;
    DDRB |= 0x07; // PORTB is the LCD CONTROL LINES
    PORTB |= 0x05; // LCD_E = HIGH, LCD_RW = LOW, LCD_RS = HIGH
    LCD_Delay (500); // Wait for the up LCD to power up			
}

void LCD_INIT (void)
{
    LCD_PutCmd (PWR_CMD); // Power up the display
    LCD_PutCmd (DL_CMD);  // Set to 4 lines, 8 bit, no cursor
    LCD_PutCmd (CLR_DSP); // Clear the display
    LCD_Delay (500); // Wait for the LCD to boot up	
	
	LCD_PutCmd (LINE1+5);
	LCD_PutString (BANNER_1);
	LCD_PutCmd (LINE2+5);
	LCD_PutString (BANNER_2);
	LCD_PutCmd (LINE3+9);
	LCD_PutString (BANNER_3);
	LCD_PutCmd (LINE4+1);
	LCD_PutString (BANNER_4);	
}
  
void LCD_PutCmd (char c) 
{
  PORTB &= ~(1<<LCD_RS);
  LCD_Delay (5); // Wait for the proper setup time to respond to the RS control line  
  LCD_PutChar(c);
  LCD_Delay (5); // Wait for the proper setup time to respond to the command being applied 
  PORTB |= (1<<LCD_RS);
}

void LCD_PutChar (char c) 
{
    PORTB |= (1<<LCD_E);
    LCD_Delay (5); // Wait for the proper setup time to respond to the E pulse	
    PORTA = c;
    LCD_Delay (5); // Wait for the proper setup time to respond to the character being applied
    PORTB &= ~(1<<LCD_E);
}
 
void LCD_PutString (const char *p) 
{
    char n = NULL; // Pointer position counter.
    while (p[n] != NULL) // Keep sending data until the NULL character is found.
  	    LCD_PutChar(p[n++]);
}

Edit:

What would be really nice is, if those who use WinAVR, GCC, IAR (or whatever other C compiler is out there) could test this code and maybe a version of the code could be devised that works for every flavor compiler out there.

That would give a "Base-Line" starting point of code that works for the "Newbe" and he/she could take it on their own from there.

I think that was the objective of Johan's tutorial but, I think he has been swamped with work and other matters right now.

Anyway... It was just a thought.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Hi,

I have tested your code! Unfortunatly the result is the same i was having... this is... nothing!

I have a 2x16 lcd module and when i turn it up the only thing that happens its the first line blank and the second with black squares for all of it.

I'm using WinAVR with atmega 48 running at 1 Mhz (its internal frequency divided by 8).

Nuno

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

The gcc delay_ms routine poops out above 240ms. They should call it delay_0to240_ms. You are trying to get it to delay 500 ms and it obviously isnt doing what you want.

Imagecraft compiler user

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

bobgardner wrote:
The gcc delay_ms routine poops out above 240ms. They should call it delay_0to240_ms. You are trying to get it to delay 500 ms and it obviously isnt doing what you want.

Hey Bob, If you have an HD44780 based LCD display, can you possibly see if the code I posted at least initializes on err, your development system? Especially since you have the ImageCraft ICCAVR v7.xx compiler.

I've had no problems from this code and I don't know why it wouldn't work. It seems to me to be quite generic. It doesn't use any built in functions and, the delay function ought to go out to about 4 billion counts.

In addition, by moving the data buss and control pins, Iv'e had this code running on the AT90s2313, Tiny2313, Mega8, Mega88, Mega16, Mega32, Mega64 and Mega128.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Hello Sinusoidal. You say your mega48 is running at 1mhz, but the winavr example you posted shows 10mhz. That one little extra zero puts the timing off by a factor of 10. Your init problem seems to be timing related. Perhaps I have found your problem? Happy New Year!

Imagecraft compiler user

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

bobgardner wrote:
Hello Sinusoidal. You say your mega48 is running at 1mhz, but the winavr example you posted shows 10mhz. That one little extra zero puts the timing off by a factor of 10. Your init problem seems to be timing related. Perhaps I have found your problem? Happy New Year!

In fact you were right, my frequency was wrong. I have corrected it but unfortunatly i couldnt see any positive results... :cry:

I had to change the ports name in the code posted by microcarl. My control bits port is PORTC and my data bits port is PORTD.

I also changed the frequency to 8 mhz, without the divider.

The actual code is:

#include 
#include 
#define F_CPU 8000000
#include  

// Define LCD Register Select as PORTC, 0x01;
#define LCD_RS 0
// Define LCD Read/Write as PORTC, 0x02; 
#define LCD_RW 1
// Define LCD Enable as PORTC, 0x04; 
#define LCD_E 2   

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define   PWR_CMD   0x0C
// SET FOUR LINE, 8 DATA BIT MODE      
#define   DL_CMD   0x38
// CLEAR DISPLAY COMMAND      
#define CLR_DSP 0x01

#define LINE1 0x80
#define LINE2 0xC0
#define LINE3 0x94
#define LINE4 0xD4

#define NULL 0x00

const char BANNER_1[] = {"Having Fun"};
const char BANNER_2[] = {"With LCD's"};
const char BANNER_3[] = {"By"};
const char BANNER_4[] = {"Carl W. Livingston"};

void LCD_Delay (unsigned long int d);
void LCD_IO_INIT (void);
void LCD_INIT (void);
void LCD_PutCmd (char);
void LCD_PutChar (char);
void LCD_PutString (const char *);

void main (void)
{
    LCD_IO_INIT ();
   LCD_INIT ();
   
   while(1)
   {
       // Add other LCD related program operations here...
   }         
}

void LCD_Delay (unsigned long int d)
{
    unsigned long int n;
    for (n = 0; n < d; n++);
}

void LCD_IO_INIT (void)
{
    DDRD = 0xFF; // PORTD is the LCD DATA LINES
    PORTD = 0x00;
    DDRC |= 0x07; // PORTD is the LCD CONTROL LINES
    PORTC |= 0x05; // LCD_E = HIGH, LCD_RW = LOW, LCD_RS = HIGH
    LCD_Delay (500); // Wait for the up LCD to power up         
}

void LCD_INIT (void)
{
    LCD_PutCmd (PWR_CMD); // Power up the display
    LCD_PutCmd (DL_CMD);  // Set to 4 lines, 8 bit, no cursor
    LCD_PutCmd (CLR_DSP); // Clear the display
    LCD_Delay (500); // Wait for the LCD to boot up   
   
   LCD_PutCmd (LINE1+5);
   LCD_PutString (BANNER_1);
   LCD_PutCmd (LINE2+5);
   LCD_PutString (BANNER_2);
   LCD_PutCmd (LINE3+9);
   LCD_PutString (BANNER_3);
   LCD_PutCmd (LINE4+1);
   LCD_PutString (BANNER_4);   
}
 
void LCD_PutCmd (char c)
{
  PORTC &= ~(1<<LCD_RS);
  LCD_Delay (5); // Wait for the display to respone to the E pulse 
  LCD_PutChar(c);
  LCD_Delay (5); // Wait for the display to respone to the E pulse 
  PORTC |= (1<<LCD_RS);
}

void LCD_PutChar (char c)
{
    PORTC |= (1<<LCD_E);
    LCD_Delay (5); // Wait for the display to respone to the E pulse   
    PORTD = c;
    LCD_Delay (5); // Wait for the display to respone to the E pulse
    PORTC &= ~(1<<LCD_E);
}
 
void LCD_PutString (const char *p)
{
    char n = NULL; // Pointer position counter.
    while (p[n] != NULL) // Keep sending data until the NULL character is found.
         LCD_PutChar(p[n++]);
}

Nuno

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

sinosoidal wrote:
In fact you were right, my frequency was wrong. I have corrected it but unfortunatly i couldnt see any positive results... :cry:

I had to change the ports name in the code posted by microcarl. My control bits port is PORTC and my data bits port is PORTD.

I also changed the frequency to 8 mhz, without the divider.

Nuno

So the question is???

Does my code work????????

Also, you include the following:

#include  
#include  
#define F_CPU 8000000 
#include  

As you are using no intrrupts:

#include  

and, as the LCD_Delay() is an integral part of my code:

#include 

Are these includes actually needed?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

I thought you said you had a 16 x 2 display. That code is for a 4 line display. Which do you have? One quick question... can you tell me how many wires run to port d? (you have a choice of 4 or 8)

Imagecraft compiler user

Last Edited: Tue. Dec 26, 2006 - 06:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
I thought you said you had a 16 x 2 display. That code is for a 4 line display. Which do you have?

He probably won't see the 2nd and 4th lines as, they will be hidden untill the display is scrolled left or right.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

No, your code does nothing in my circuit and lcd module.

I have a 16x2 display.

I have all the 8 pins of PORTD connected to lcd module.

The other includes are not necessary but i know that they arent doing nothing. They were just taken from my other project.

Cheers,

Nuno

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

@Microcarl
What wiring you need for your code?

PORTb 1 - 3 to RS, RW and E?

PORTA 0 -> DB0
PORTA 1 -> DB1
..
PORTA 7 -> DB7

That is all(and the power supply offcourse)?

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

naffets wrote:
@Microcarl
What wiring you need for your code?

PORTb 1 - 3 to RS, RW and E?

PORTA 0 -> DB0
PORTA 1 -> DB1
..
PORTA 7 -> DB7

That is all(and the power supply offcourse)?

PIN 1 = GND = 5 V COMON
PIN 2 = Vcc = +5 VDC
PIN 3 = Vee = CONTRAST POT SLIDER

PIN 4 = PORTB:0 = RS
PIN 5 = PORTB:1 = R/W
PIN 6 = PORTB:2 = E

PIN 7 = PORTA:0 = DB0
.
.
.
PIN 14 = PORTA:7 = DB7

This is what is currently working on my proto-board.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Hi again,

I've been out of this since i have a lot of work by now.

Although, today i was trying again to put it working.

I've looked to several codes around.

But they all give me nothing.

I decided to give a new closer look to your code carl.

I needed to change some stuff as i only have 2 lines and my avr mega 88 doesnt have a port A

So i replaced all the PORTA and DDRA occurences by PORTD and DDRD.

I also replaced all the occurences of PORTB and DDRB to PORTC and DDRC.

About my LCD, it is not driven by hitachi. It is controlled by ks0066.

I choose the following addresses for the 2 lines:

#define LINE1 0x00
#define LINE2 0x40

Based on the "how to use inteligent LCD modules tutorial". I assume it's the same.

I have his datasheet:

http://www.datasheets.org.uk/dat...

I'm trying to make the initialization using the information on page 26:

The first thing i dont understand its fosc condition: 270khz.

Do i need to have that frequency in my chip? (i assume not)

In your code carl, there is no delay between these initialization operations. Is this a problem?

I also had to change two commands you have:

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define PWR_CMD 0x3F // now corresponds to function set
// SET 2 LINE, 8 DATA BIT MODE
#define DL_CMD 0x0F // now correspondes to display on/off control

Well, i tried to gather all the information i remembered.

And thanks for all the support give until now.

Many thx and happy new year

Nuno

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

sinosoidal wrote:
Hi again,

I decided to give a new closer look to your code carl.

Nuno

Let me refer you to this latest post.

http://www.avrfreaks.net/index.p...

I don't have a Mega88 so I couldn't test the code for that controller. I did test the code on a Mega168 and it worked fine so, the code should work for the Mega88 as, the Mega88 is the little brother to the Mega168.

I've been working on this for the past two days and have added quite a bit to it.

Let me know how it works out...

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Quote:

The first thing i dont understand its fosc condition: 270khz.
Do i need to have that frequency in my chip? (i assume not)

No, your assumption is correct. What the data sheet is talking about is the frequency of the oscillator for the LCD controller (HD44780, KS0066, whatever...). Assume its 270 KHz and move on.

Bob wrote:

You say your mega48 is running at 1mhz, but the winavr example you posted shows 10mhz. That one little extra zero puts the timing off by a factor of 10. Your init problem seems to be timing related. Perhaps I have found your problem?

No, Bob. If the compiler generates delays based on a stated frequency of 10 MHz but the chip is actually running at 1 MHz then the delays will be 10 times longer than expected, not the other way around.

This is in fact a good thing. My first advice to avoid breaking timing constraints for a LCD module is to slow down the clock to "a ridicolously low value". The above manouvre will accomplish the same thing (although it might not have been intended).

Happy new year, everyone!

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

sinosoidal wrote:

I choose the following addresses for the 2 lines:

#define LINE1 0x00
#define LINE2 0x40

Based on the "how to use inteligent LCD modules tutorial". I assume it's the same.

That's where you have gone wrong. According to the LCD datasheet, the MSB should be set for the LCD to accept the command as DDRAM address. This is done correctly by using #define LINE1 0x80 in Microcarl's code.

I have tried Microcarl's LCD code on Tiny2313 and it works just fine.

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

eblc1388 wrote:
sinosoidal wrote:

I choose the following addresses for the 2 lines:

#define LINE1 0x00
#define LINE2 0x40

Based on the "how to use inteligent LCD modules tutorial". I assume it's the same.

That's where you have gone wrong. According to the LCD datasheet, the MSB should be set for the LCD to accept the command as DDRAM address. This is done correctly by using #define LINE1 0x80 in Microcarl's code.

I have tried Microcarl's LCD code on Tiny2313 and it works just fine.

Thank you very much!

I was beginning to think I was missing something very important.

Thank you for the confirmation that my program works correctly in another environment!!!

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Hi again folks,

I'm getting crazy with this LCD module.

It is harder to work with it than learn to work with a AVR.

:(

I'm posting all the code i'm using right now.

Basicly it's carls code with some modifications because my hardware is atmega 88 and doesnt have PORTA. I also changed PORTB to PORTC.

In my hardware i use R/W always down to 0.

I also messed with the following defines:

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define PWR_CMD 0x3F
// SET 2 LINE, 8 DATA BIT MODE
#define DL_CMD 0x0F
// CLEAR DISPLAY COMMAND
#define CLR_DSP 0x01

Which based on what i understand from my datasheet they were not right... Well.. at this point i know nothing.... Grrr!!

#define F_CPU 80000000

// Data: PORTD
// Control: PORTC
// RS = PORTC, bit 0, 0x01
// RW = PORTC, bit 1, 0x02
// E = PORTC, bit 2, 0x04

#include 
#include 

// Define LCD Register Select as PORTC, 0x01;
#define LCD_RS 0
// Define LCD Read/Write as PORTC, 0x02; 
#define LCD_RW 1
// Define LCD Enable as PORTC, 0x04; 
#define LCD_E 2   

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define   PWR_CMD   0x3F
// SET 2 LINE, 8 DATA BIT MODE      
#define   DL_CMD   0x0F
// CLEAR DISPLAY COMMAND      
#define CLR_DSP 0x01

#define LINE1 0x80
#define LINE2 0x80


#define NULL 0x00

const char BANNER_1[] = {"Having Fun"};
const char BANNER_2[] = {"With LCD's"};

void LCD_Delay (unsigned long int d);
void LCD_IO_INIT (void);
void LCD_INIT (void);
void LCD_PutCmd (char);
void LCD_PutChar (char);
void LCD_PutString (const char *);

void main (void) {
   LCD_IO_INIT ();
   LCD_INIT ();
   
   while(1)
   {
       // Add other LCD related program operations here...
   }         
}

void LCD_Delay (unsigned long int d)
{
    unsigned long int n;
    for (n = 0; n < d; n++);
}

void LCD_IO_INIT (void)
{
    DDRD = 0xFF; // PORTD is the LCD DATA LINES
    PORTD = 0x00;
    DDRC |= 0x07; // PORTC is the LCD CONTROL LINES
    PORTC |= 0x05; // LCD_E = HIGH, LCD_RW = LOW, LCD_RS = HIGH
    LCD_Delay (500); // Wait for the up LCD to power up         
}

void LCD_INIT (void)
{
    LCD_PutCmd (PWR_CMD); // Power up the display
    LCD_PutCmd (DL_CMD);  // Set to 2 lines, 8 bit, no cursor
    LCD_PutCmd (CLR_DSP); // Clear the display
    LCD_Delay (500); // Wait for the LCD to boot up   
   
   LCD_PutCmd (LINE1+5);
   LCD_PutString (BANNER_1);
   LCD_PutCmd (LINE2+5);
   LCD_PutString (BANNER_2);
}
 
void LCD_PutCmd (char c)
{
  PORTC &= ~(1<<LCD_RS);
  LCD_Delay (5); // Wait for the proper setup time to respond to the RS control line 
  LCD_PutChar(c);
  LCD_Delay (5); // Wait for the proper setup time to respond to the command being applied
  PORTC |= (1<<LCD_RS);
}

void LCD_PutChar (char c)
{
    PORTC |= (1<<LCD_E);
    LCD_Delay (5); // Wait for the proper setup time to respond to the E pulse   
    PORTD = c;
    LCD_Delay (5); // Wait for the proper setup time to respond to the character being applied
    PORTC &= ~(1<<LCD_E);
}
 
void LCD_PutString (const char *p)
{
    char n = NULL; // Pointer position counter.
    while (p[n] != NULL) // Keep sending data until the NULL character is found.
         LCD_PutChar(p[n++]);
}

I'm using again 8 Mhz.

This is a screenshot of the bread board just for you guys check that i'm making the right connections or even discover something that is wrong.

http://www.imaginando.net/goodies/shot.jpg

I hope this helps you guys finding me the problem i have! ....

Best regards,

Nuno

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

80 Mhz is a real fast AVR

Imagecraft compiler user

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

bobgardner wrote:
80 Mhz is a real fast AVR

Yes, you were right. That was completly wrong, but i still dont have good news! :cry:

Thx

Nuno

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

The first thing I'd like to rule out is that this is not a timing problem. So: At what clock speed is your mega88 actually running?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

Your program has gcc style include paths. I thought you were using the imagecraft compiler? If you have both compilers installed, maybe your problem has something to do with trying to compile the gcc includes with imagecraft? There should be an #include up there for imagecraft, and no avr/io and no util/delay etc.

Imagecraft compiler user

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

bobgardner wrote:
Your program has gcc style include paths. I thought you were using the imagecraft compiler? If you have both compilers installed, maybe your problem has something to do with trying to compile the gcc includes with imagecraft? There should be an #include up there for imagecraft, and no avr/io and no util/delay etc.

No. I'm actually using WinAVR, only!

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

sinosoidal wrote:
Basicly it's carls code with some modifications because my hardware is atmega 88 and doesnt have PORTA. I also changed PORTB to PORTC.

In my hardware i use R/W always down to 0.

I also messed with the following defines:

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define   PWR_CMD   0x3F
// SET 2 LINE, 8 DATA BIT MODE      
#define   DL_CMD   0x0F
// CLEAR DISPLAY COMMAND      
#define CLR_DSP 0x01

Which based on what i understand from my datasheet they were not right... Well.. at this point i know nothing.... Grrr!!Nuno

Well, the code that I posted has been verified as to be working code by two independant sources.

Either:
1. You are doing something wrong in the translation from one compiler to another.

2. You have a wiring error.

3. You have a deffective display.

I guess, like Bob, I am confused about exactly which compiler you are using.

Also, I think you need to re-visit the PWR_CMD, DL_CMD & CLR_DSP assignments as, I have been using these assignments for years and have never had the problems you are having, getting a text based LCD to work.

Also, I think a lengthy read of the datasheet of the LCD and a good understanding of the timing required, and a good understanding of the initialization process, will shed some light on some possable issues.

Over a three or four day span, I have re-written my original code at least three times, using different timing, initialization and bit lengths. All of the different code versions worked with several LCDs by several manufacturers. I have about 50 to 60 hours testing the compatability between these different LCD manufacturers. The only display that has given any issues at all was the Hyundi, which seemed slightly more sensitive to critically tight timing settings. But it still worked and only mis-placed a character occasionally.

What I can say, is that this whole thing has caused me to look at getting seriuos about a project that I have been wanting to do for a long, long time.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

microcarl wrote:
sinosoidal wrote:
Basicly it's carls code with some modifications because my hardware is atmega 88 and doesnt have PORTA. I also changed PORTB to PORTC.

In my hardware i use R/W always down to 0.

I also messed with the following defines:

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define   PWR_CMD   0x3F
// SET 2 LINE, 8 DATA BIT MODE      
#define   DL_CMD   0x0F
// CLEAR DISPLAY COMMAND      
#define CLR_DSP 0x01

Which based on what i understand from my datasheet they were not right... Well.. at this point i know nothing.... Grrr!!Nuno

Well, the code that I posted has been verified as to be working code by two independant sources.

Either:
1. You are doing something wrong in the translation from one compiler to another.

2. You have a wiring error.

3. You have a deffective display.

I guess, like Bob, I am confused about exactly which compiler you are using.

Also, I think you need to re-visit the PWR_CMD, DL_CMD & CLR_DSP assignments as, I have been using these assignments for years and have never had the problems you are having, getting a text based LCD to work.

Also, I think a lengthy read of the datasheet of the LCD and a good understanding of the timing required, and a good understanding of the initialization process, will shed some light on some possable issues.

Over a three or four day span, I have re-written my original code at least three times, using different timing, initialization and bit lengths. All of the different code versions worked with several LCDs by several manufacturers. I have about 50 to 60 hours testing the compatability between these different LCD manufacturers. The only display that has given any issues at all was the Hyundi, which seemed slightly more sensitive to critically tight timing settings. But it still worked and only mis-placed a character occasionally.

What I can say, is that this whole thing has caused me to look at getting seriuos about a project that I have been wanting to do for a long, long time.

And i belive your code!

Something must be wrong...

I guess i will take everything how and do the wiring again. Just from the scratch.

I'll give some feedback later

Cheers,

Nuno

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

sinosoidal wrote:
Basicly it's carls code with some modifications because my hardware is atmega 88 and doesnt have PORTA. I also changed PORTB to PORTC.

In my hardware i use R/W always down to 0.

I also messed with the following defines:

// TURN ON POWER TO THE DISPLAY, NO CURSOR
#define   PWR_CMD   0x3F
// SET 2 LINE, 8 DATA BIT MODE      
#define   DL_CMD   0x0F
// CLEAR DISPLAY COMMAND      
#define CLR_DSP 0x01

Which based on what i understand from my datasheet they were not right... Well.. at this point i know nothing.... Grrr!!Nuno


DL_CMD should be set according to the number of lines on the display but, PWR_CMD is incorrect.

// TURN ON POWER TO THE DISPLAY, NO CURSOR 
#define   PWR_CMD   0x0C 
// SET 8 DATA BIT MODE        
#define   DL_CMD   0x30 
// CLEAR DISPLAY COMMAND        
#define CLR_DSP 0x01

sinosoidal wrote:

#define F_CPU 80000000


Shouldn't this be:

#define F_CPU 8000000

sinosoidal wrote:

#define LINE1 0x80
#define LINE2 0x80

Line 2 starting address is incorrect.

#define LINE1 0x80 
#define LINE2 0xC0 
void LCD_PutCmd (char c)
{
  PORTC &= ~(1<<LCD_RS);
  LCD_Delay (5); // Wait for the proper setup time to respond to the RS control line 
  LCD_PutChar(c);
  LCD_Delay (5); // Wait for the proper setup time to respond to the command being applied
  PORTC |= (1<<LCD_RS);
}

Try the following, as an experiment

void LCD_PutCmd (char c)
{
  PORTC &= ~(1<<LCD_RS);
  LCD_Delay (200); // Wait for the proper setup time to respond to the RS control line 
  LCD_PutChar(c);
  LCD_Delay (200); // Wait for the proper setup time to respond to the command being applied
  PORTC |= (1<<LCD_RS);
  LCD_Delay (200); 
}

Also try the following...

void LCD_PutChar (char c)
{
    PORTC |= (1<<LCD_E);
    LCD_Delay (5); // Wait for the proper setup time to respond to the E pulse   
    PORTD = c;
    LCD_Delay (5); // Wait for the proper setup time to respond to the character being applied
    PORTC &= ~(1<<LCD_E);
    LCD_Delay (5); // Wait for the proper setup time 
}

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Nope... It didnt work!

I still have to unwire everything and make it again.

Explain me just one thing.

In my datasheet (ks0066 datasheet), in the initialization part (page 26) i have the following sequence:

1 - Power On
2 - Wait for more than 30 ms after rises to 4.5. (i'm using 5 volts directly on this pin, since 4.5 doesnt even light up the display)
3 - Function set (which define 1 ou 2 line mode and sets display on) is like this

000011NFXX where N can be 0 for 1 line mode and 1 for 2 line mode. And F=0 makes display off and 1 display one.

This is related with your PWR_CMD?

Thx,

Nuno

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

000011NFXX has 10 bit positions. You have 2 extra 00s in the front by accident?

Imagecraft compiler user

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

Yes, bob. He's probably reading right out of the data sheet where the first two columns are the RS and R/W signals. So the instruction proper is 0011NFXX.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

Yes, i forgot to mention that!

Sorry!

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

I took off every connection and made all the wiring up again. Nothing different!

My module has the reference GDM1602A

The one page datahseet can be found here:

http://www.datasheetarchive.com/datasheet.php?article=1547161

Can you guys see here anything that helps?

:S

Thx for all the help you guys gave me until now.

This is getting sick for me! :(

Best regards,

Nuno

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

Its a timing thing. Does the mega88 have a clkdiv fuse to run it at 8mhz or 1mhz? You THINK it is running at 8, but seems like it should still work even if it is running at 1. Does the mega88 have JTAG? Is it on portc? Do you need to turn the jtag fuse off to get portc to work like an output port? Can you edit, compile, burn and run ANY other program using this avr and your compiler setup that shows ANY correct behavior on the cpu, like flash an led on and off once each second, and it really flashes once per second and not once per 8 seconds?

Imagecraft compiler user

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

bobgardner wrote:
Its a timing thing. Does the mega88 have a clkdiv fuse to run it at 8mhz or 1mhz? You THINK it is running at 8, but seems like it should still work even if it is running at 1.

Running at 1MHz is far more tollerable then running at 8MHz. You can have the display running with an 8MHz machine and drop down to 1MHz with any problems at all but, you can't have the display timing critically set to run with a 1MHz machine and jump up to 8MHz and expect the LCD display to operate correctly, without re-adjusting all of the appropriate timing.

bobgardner wrote:
Can you edit, compile, burn and run ANY other program using this avr...

Good point! Will it even program to simply flash an LED on & off?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Yes, i can compile and program right.

I tried the LED program and you guys are right. It's a timing thing.

I will need your help here.

I'm running the following program to do the led test:

#include 
#define F_CPU 1000000
#include 

void my_delay_ms(uint16_t delay_count) {
   uint16_t i;

   for (i=0; i

I'm using the divider to have a frequency clock of 1 Mhz and i was expecting the led to light 1 second and then stay 1 second turned off.

In portb 0 its blinking very fast. in the other B ports it doesnt blink.

If i take the divider the blinking of portb0 is even greater but it doesnt change, changing the delay... :S

I have tried this in both mega88 and mega168?

What is happening here?

Any clue?

Best regards,

Nuno

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

Hey guys,

I wont believe this....

The problem with the led test was that i was always progamming the chip with a hex file that was not related with that project, and with the lcd project as well....

I though that it was the problem since the begining.

Unfortunetly i wasnt. I have the same behaviour.

I even tried to clean the code again and past again Carl's code.

Well... I now have sure that i'm programming the right file.

I'm suspect to talk now! :S

Nuno

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

1. You will not get the result you expect with _delay_ms(1000) unless you run your AVR with a clock that is substantially lower than 1 MHz. You need to read up on the avr-libc documentation, and on _delay_ms(). There is a limitation on how long delays it can generate. I can't remember the limits of hand and I could look it up for you, but you might as well do it yourself.

2. When you say "take the divider" I assume you are referring to the CKDIV8 fuse. If you change the CKDIV8 fuse, but do not change the F_CPU defined constant then the blinking frequency will change, as _delay_ms() depends on this define.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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

Hey!

I finally have good news!

After all the problem was in flashing with the correct file!

Dahhhh

You could post a news with the title "The lamest freak!"

ehehehhe

With the rewiring i forgot to plug R/W to the ground.

The output i have in the lcd with carl's code is:

"vnso"

I believe this is related to the fact i have a 2x16 lcd module and the code is for a 4 line.

Need help to understand the display chaacter address codes

Thx a lot!

Best regards,

Nuno

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

I have been playing a little bit with the LCD and i have a thing to ask you, Carl:

   LCD_PutCmd (LINE1+5);
   LCD_PutString (BANNER_1);

Why do you have LINE1+5 in the PutCmd function?

The output i'm having right now is:

__________H_____
_nuF_gniva______

This is the BANNER "Having Fun".

I'm doing the initialization using my datasheet values:

#define PWR_CMD 0x3C
#define DL_CMD 0x0F

Thx,

Nuno

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

sinosoidal wrote:
I have been playing a little bit with the LCD and i have a thing to ask you, Carl:

   LCD_PutCmd (LINE1+5);
   LCD_PutString (BANNER_1);

Why do you have LINE1+5 in the PutCmd function?

The output i'm having right now is:

__________H_____
_nuF_gniva______

This is the BANNER "Having Fun".

I'm doing the initialization using my datasheet values:

#define PWR_CMD 0x3C
#define DL_CMD 0x0F

Thx,

Nuno

Because I use primarily a 4x20 display.

The very first character in LINE1 is defined as 0x80 - the left most display position on line 1. This will be the same for every common text based LCD module, no mater how many lines it has.

LINE2 is defined as 0xC0. This too is that same for every text based display I have ever used.

I have tested the exact same setup with a 2x16 character display and:
"Having"
"Fun"
is still displayed correctly on the smaller display but, shifted to the right by 5 character positions - without and code changes.

Just change the PutCmd() variable from:

LCD_PutCmd (LINE1+5);
LCD_PutString (BANNER_1);

to

LCD_PutCmd (LINE1);
LCD_PutString (BANNER_1);

sinosoidal wrote:
I'm doing the initialization using my datasheet values:

#define PWR_CMD 0x3C
#define DL_CMD 0x0F

I am currently at work and don't have a datasheet available so, I don't know what the different bit positions represent and can't presume how the display is being set up. What I do know is that, the PWR_CMD & DL_CMD that I posted are what I'm using.

Now, with the DL_CMD, if you are using a two line display and a blinking cursor and what ever the other options there are, that's not really an issue.

However, the PWR_CMD value could be an issue. I just don't have enough information to determine what your values actually mean at the moment. I'll look them up tonight, after I get home - about 0:30, Jan 07, 2007.

Edit:

One thing you can do is to print just one character, followed be a space characer, such as
"H " on only one line - over and over. See what happens.

Then print:
"Ha " over and over.

Provide some detailed feedback as to the exact text position from each test. This might lead to clues as to whether its a command timing issue ot a character printing issue.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

Pages