LCD problem

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

Hi all,
When i try to add lcd_init(); to my code like this:

#include "lcd.h"
int main(void){
	lcd_init(16);
	
}

then i get this error in the gcc compiler:
C:\WinAVR\avr\include/main.c:3333: undefined reference to `lcd_init'

The lcd.h file i use is from pfleury, but i don't know what i'm doing wrong..
Anyone that can help me with this? It's my first attempt to an lcd-display. Thanks

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

Add the lcd.c to the SRC= line in your Makefile

Cliff

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

Oops :) i didn't know that.
Thanks

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

I still have a problem with it, i can't get a character on the display, the only thing i see on the display is black boxes, but only one row of the two.
The LCD is connected, only with 4 pins (4 pin i/o mode), and i'm using the lcd.h file from pfleury.

this is my code:

int main(void){
	lcd_init(16);
	lcd_home();
	lcd_puts("Hello");
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

4 data bits, rd/wr, register select, and Enable. Thats 7 pins, right? Have the data bits on the hi 4 bits of the port or the lo 4 bits? Isn't there some user configurable defines in the h file for 4 bit or 8 bit? a define for the port being used? You edit all that stuff right I hope?

Imagecraft compiler user

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

Dennis,

Just out of interest, where does your program go after that call to lcd_puts() ? - see FAQ#2 below!!

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

Yes i think so..
I tried connecting the 4 databits of the avr to the high 4 databits of the lcd, also i tried the low 4 databits of the lcd, and i tried switching the order.
I'm using a AC-162D-YI lcd, that's an lcd with a ks0066 chip i think, in the header file there is this:

#define LCD_CONTROLLER_KS0073 1 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */

But that's for ks0073, i don't know if that makes difference..

still blocks in the first line of the display..

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

clawson wrote:
Dennis,

Just out of interest, where does your program go after that call to lcd_puts() ? - see FAQ#2 below!!

Yes i know, but that was for just trying it out

This is my main for the moment:

int main(void){
    DDRA = 0b00001111;
    TCCR0 = 0x05; // Normal operation of Timer1, No PWM, Timer1 clock is F_CPU/1024 -> counts to 7200 per second, timer only counts to 255
	TCCR1A = 0x00; // Normal operation of Timer1, No PWM
    TCCR1B = 0x05; // Timer1 clock is F_CPU/1024 -> counts to 7200 per second
	USART_Initialize();
    SREG |= ( 1 << SREG_I ); // Enable global interrupt
	PORTA = 0x0F;
	DDRC = 0xFF;
	lcd_init(16);
	lcd_clrscr();
	lcd_puts("GPWPL Coder");
	while (1){ // Loop forever
		if ( Receiver_Completed_Sentence == true ){
			Busy_Copying = true;
			Receiver_Chars_Received--;
			PORTA &= ~( 1 << PA1 );
            Receiver_Copy_Sentence();
			Receiver_Completed_Sentence = false;
			Converter_Ready_To_Convert = true;
		}
		if ( Converter_Ready_To_Convert == true ){
			Convert_Sentence();
			Converter_Ready_To_Convert = false;
		}
		if ( Converter_Completed_Sentence == true ){
			if ( Busy_Transmitting == false ){
				Copy_Sentence();
				PORTA |= ( 1 << PA1 );
				Converter_Completed_Sentence = false;
			}
		}
		if ( Transmitter_Completed_Sentence == true ){
			Busy_Transmitting = true;
			Transmitter_Completed_Sentence = false;
			PORTA &= ~( 1 << PA0 );
			Transmitter_Last_Transmitted_Char = 0;
			UDR1 = Transmitter_Buffer[Transmitter_Last_Transmitted_Char];
		}
	}
}

I was thinking isn't it weird only one row of the lcd has blocks?

Thankx for the help, but i'm getting really desperate :?

Last Edited: Thu. Apr 12, 2007 - 01:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah but, assuming you are compiling with GCC 4.1.1 then what your previously posted code was actually doing was:

   lcd_init(16); 
   lcd_home(); 
   lcd_puts("Hello"); 

   lcd_init(16); 
   lcd_home(); 
   lcd_puts("Hello"); 

   lcd_init(16); 
   lcd_home(); 
   lcd_puts("Hello"); 

   lcd_init(16); 
   lcd_home(); 
   lcd_puts("Hello"); 

And the reinitalisation may well have been obliterating any "Hello" you HAD managed to output. So if that really was your test program then I probably wouldn't have expected it to work (unless the init function is protected against being called a second time)

You might try again with an added "while(1);" at the end?

Cliff

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

Actually that wasn't the complete main, just a part i copied, maybe a lesson for the future i should copy the whole code :)

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

This question is a tiny bit off thread, but maybe your guys will allow me to ask if you know of a reference guide for programming LCD modules?
I am using a LUMEX 16x2 display driven by a Mega32, AVRGCC. I have written a driver which works, but it could be better. I need to know more about screen control. LUMEX does not have a detailed data sheet, just a couple of drawings and a brief, generic data sheet. I have looked at the Hitachi H44780 data sheet, but while the instruction set is similar, there are lots of differences between it and the LUMEX. Do all the manufacturers of these devices use the same instruction set? Thanks.

Jim Lake

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

Well the Pete Fleury support lib that Dennis is trying to use is one good example of HD44780 code in action. Plus there has ben TONS of prior traffic about HD44780 here on 'Freaks but the broken search engine means you have to Google for "HD44780 site:avrfreaks.net" which currently hits 258 pages.

Cliff

Pete Fleury stuff at http://homepage.hispeed.ch/peter...

Also see http://hubbard.engr.scu.edu/avr/... as I think the "KS0108/HD61202" mentioned there is yet another clone

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

Quote:
I tried connecting the 4 databits of the avr to the high 4 databits of the lcd, also i tried the low 4 databits of the lcd, and i tried switching the order.

But which port are you trying to use and which port did you tell the code to use. Also, the same goes for the port and pins that you are attaching the 3 control lines to.

Regards,
Steve A.

The Board helps those that help themselves.

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

this is the code in lcd.h, i changed it so that it would work with my board:

#define XTAL 7372800

#define LCD_CONTROLLER_KS0073 1

#define LCD_LINES           2     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */

#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */

#define LCD_PORT         PORTC        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    3            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    2            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    1            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    0            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       6            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        4            /**< pin  for Enable line     */

I think this is all ok, since i have a "KS0066 or equivalent" lcd display, at least that's in the datasheet.

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

I might have dreamt this but I think the Pete Fleury code uses _delay_ms(). In which case it'll be vital that the code is not built with -O0 optimisation. Can you confirm that you are using something sensible like -Os ? (if you are using a Makefile you're probably OK as it'll have an "OPT = s" but if you are using Studio as an IDE it defaults to -O0)

Oh and the obvious question is whether the data lines really are on bits 0..3 of PORTC, RS on pin 6, RW on pin 5 and E on pin 4 ??

Cliff

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

Seems odd to hook the data bits up backwards... I'd hook data bit 0 on the avr to data bit 0 on the lcd controller. Maybe the jtag needs turning off... add this line twice MCUCSR=0x80; during init to disable jtag in portc.

Imagecraft compiler user

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

How have you connected pin #3 on the LCD to set the LCD contrast level?

If you don't have it connected to some voltage between 0.5 and 1.0 volts, this explains the blocks on screen.

- Jani

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

The blocks went away when i disabled jtag, but still not getting characters on the display.
The contrast is good i think, since i could see the blocks on the screen.. and I use avr-gcc in OPT = s

Thankx for the help already!

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

Either the black blocks mean your contrast is good, or the black blocks mean that your contrast is turned on to the maximum and you can't see the characters as they are all black, except when the display is turned off with the software command, when the blocks are gone.

So just to be sure, please answer what have you connected to the contrast voltage pin (#3)?

- Jani

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

dennis84 wrote:

I'm using a AC-162D-YI lcd, that's an lcd with a ks0066 chip i think, in the header file there is this:

#define LCD_CONTROLLER_KS0073 1 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */

But that's for ks0073, i don't know if that makes difference..

Actually, by reading the datasheets of course, I think your KS0066 display controller is actually closer to being HD44780 than being KS0073.

But I don't know what the code does, so it might work with both types, if you don't use KS0073 specific features.

- Jani

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

The contrast voltage was at 0 volts, now i've put it to 0,66 volts. I doulbe checked all of my connections but i don't understand it. i tried switching the LCD_DATAx_PORT parameters in the lcd.h file, tried changing the LCD_CONTROLLER_KS0073 parameter, nothing seems to work.
The lcd display isn't broken either, i tested it on another board too.

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

It's working now, i'm really thankfull to all of you.

I don't know what i did to make it work

This was my code for testing and it worked

int main(void){
	lcd_init(LCD_DISP_ON_BLINK);
	lcd_clrscr();
	lcd_puts("LCD Test Line 1\n");
	lcd_puts("Line 2");
	lcd_gotoxy(7,1);
	lcd_putc(':');
	while(1){
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I still have a problem..
I work with UART, i can receive, transmit etc. but when i add the three lines for the lcd to my code, the avr doesn't transmit anymore, he does receive and all the other things..

int main(void){
    DDRA = 0b00001111;
	PORTA = 0x0F;
    TCCR0 = 0x05; // Normal operation of Timer1, No PWM, Timer1 clock is F_CPU/1024 -> per seconde telt hij tot 7200, maar deze timer kan maar tot 255 tellen
	TCCR1A = 0x00; // Normal operation of Timer1, No PWM
    TCCR1B = 0x05; // Timer1 clock is F_CPU/1024 -> per seconde telt hij tot 7200
	USART_Initialize();
	lcd_init(LCD_DISP_ON);
	lcd_clrscr();
	lcd_puts("  $GPWPL Coder");
	SREG |= ( 1 << SREG_I );
	while(1){
	}
}

I didn't put in the code that's in the while loop

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

It's only when i put in this line:

lcd_puts("  $GPWPL Coder");

Maybe it uses to much of memory or? i don't know.

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

Well since your program just falls into a while(1) this would seem to imply that your UART stuff is interrupt driven. If it stops when you make a call to lcd_puts() then my first thought would be that the lcd_puts() contains a cli() without a balancing sei(). In fact what it should really do is take a copy of SREG, then cli() then restore SREG back again which won't just enable interrupts every time but will put the state the back the way it was before the cli()

Cliff

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

Yes, my UART is interrupt driven.
I don't understand it, because i put the lcd_puts(); in the beginning of my code, even before global interrupt is enabled. And when i add lcd_puts to my code it won't transmit anymore. Maybe it has something to do with my code being too big? Or is a hex file of 40,6 kB not too much for a atmega162? I don't know.

ps:
I double checked it all again at 2:56 midnight ;) and it still works only when i leave lcd_puts(" $GPWPL Coder\n"); out of my main.

main looks like this:

int main(void){
    DDRA = 0b00001111;
	PORTA = 0x0F;
    TCCR0 = 0x05;
	TCCR1A = 0x00;
    TCCR1B = 0x05;
	//TCCR3A = 0x00;
    //TCCR3B = 0x05;
	//TCCR2 = 0x07;
	lcd_init(LCD_DISP_ON);
	lcd_clrscr();
	//lcd_puts("  $GPWPL Coder\n");
	USART_Initialize();
	SREG |= ( 1 << SREG_I ); // Enable global interrupt
	while(1){
		if( Receiver_Completed_Sentence == true ){
			Busy_Copying = true;
			Receiver_Chars_Received--;
			PORTA &= ~( 1 << PA1 );
            Receiver_Copy_Sentence();
			Receiver_Completed_Sentence = false;
			Converter_Ready_To_Convert = true;
		}
		if( Converter_Ready_To_Convert == true ){
			Convert_Sentence();
			Converter_Ready_To_Convert = false;
		}
		if( Converter_Completed_Sentence == true ){
			if( Busy_Transmitting == false ){
				Copy_Sentence();
				PORTA |= ( 1 << PA1 );
				Converter_Completed_Sentence = false;
			}
		}
		if( Transmitter_Completed_Sentence == true ){
			Busy_Transmitting = true;
			Transmitter_Completed_Sentence = false;
			PORTA &= ~( 1 << PA0 );
			Transmitter_Last_Transmitted_Char = 0;
			UDR1 = Transmitter_Buffer[Transmitter_Last_Transmitted_Char];
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whats the last rom address in the map file? 16K of rom would have at least a 32k hex file...

Imagecraft compiler user

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

Actually i'm a real noob at avr programming, so i included the hex file.

Attachment(s): 

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

I guess it has something to do with memory space, because when i change Max_Receiver_Length from 332 to 200 it all works correctly..

#define Max_Receiver_Length 200
volatile char Receiver_Buffer[Max_Receiver_Length];
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like rom is almost full....last addr about 0x39xx out of 0x3fff... the address is char 3,4,5 and 6 in the hex file (1st 2 chars are a byte count).

Imagecraft compiler user

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

The answer is not to tie the lower 4 bits of the LCD interface to ground unless you are using a system which you sometimes see where the R/W is tied to ground and the code doesnt test the busy flag.Leave the lower 4 bits floating and it will then work.If you tie them to ground with R/w not tied to ground then they can go into output mode and withoout current limiting resistors the interface will go 'POP'

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

Just out of interest what happens if you simpy add a call to sei() after the call to lcd_puts(). If this then works then it IS because there's an unbalanced cli() inside lcd_puts()

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

I don't think that was the problem since i changed "char Receiver_Buffer[332];" to "char Receiver_Buffer[180];" in my declaration and it worked, i guess it was just not enough memory space in the atmega.

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

If I remember rightly this is a Mega162 you are working with? If so then it has just 1K of SRAM so your [332] array ate almost a third of the memory in one hit. One thing that comes to mind is whether you are storing any text strings that go to the UART or the LCD in RAM or code flash. If you are not already using PSTR() and PROGMEM for them then you ought to have a read of Dean's tutorial about PROGMEM in the Tutorial Forum. This may free enough RAM for a [332] buffer but you might want to be rethinking your system design if you really need to be using buffers that big on a 1K processor!!

Cliff