A character LCD does not display - AtMega32

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

I am writing the character 'H' on an 16X2 character LCD in 8-bit mode, but it does not write for some reason.

The connection and simulation are as follows:

 

Connection and Simulation of an 16X2 LCD with AtMega32

 

As you can see, the ASCII number 0x48 appears on PortB and on the Data pins of the LCD, but nothing appears on the LCD screen.

This is my code :


 #define F_CPU 12000000UL
 #include "util/delay.h"
 #include "MCAL/GPIO.h"

 int main(void)
 {

	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_ms(15);

	GPIO_writePinVal(PORTA_ID, P1, GPIO_LOW);
	GPIO_writePinVal(PORTA_ID, P2, GPIO_LOW);

	uint8 command = EIGHT_BIT;

	GPIO_writePortVal(GPIO_PORTB, command);

	GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = DISP_ON_CURSOR_OFF;

	GPIO_writePortVal(GPIO_PORTB, command);

	GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = CLR_SCR;

	GPIO_writePortVal(GPIO_PORTB, command);

	GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_ms(2);

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

	command = LINE1_POS1;

	GPIO_writePortVal(GPIO_PORTB, command);

	GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = CURSOR_INC;

	GPIO_writePortVal(GPIO_PORTB, command);

	GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);
	_delay_us(100);

	while(1)
	{
		uint8 data = 'H';

		GPIO_writePinVal(PORTA_ID, P1, GPIO_HIGH);
		GPIO_writePinVal(PORTA_ID, P2, GPIO_LOW);

		GPIO_writePortVal(PORTB_ID, data);

		GPIO_writePinVal(PORTA_ID, P3, GPIO_HIGH);
		_delay_us(1);
		GPIO_writePinVal(PORTA_ID, P3, GPIO_LOW);

		_delay_us(100);

	}

	return 0;
 }

 

And the symbolic constants of the commands like DISP_ON_CURSOR_OFF are :

#define    CLR_SCR                 0x01
#define    CURSOR_HOME             0x02
#define    CURSOR_DEC              0x04
#define    CURSOR_INC              0x06
#define    DISP_RSHIFT             0x05
#define    DISP_LSHIFT             0x07
#define    DISP_OFF_CURSOR_OFF     0x08
#define    DISP_OFF_CURSOR_ON      0x0A
#define    DISP_ON_CURSOR_OFF      0x0C
#define    DISP_ON_CURSOR_BLINK    0x0E
#define    CURSOR_LSHIFT           0x10
#define    CURSOR_RSHIFT           0x14
#define    DISP_ENT_LSHIFT         0x18
#define    DISP_ENT_RSHIFT         0x1C
#define    CURSOR_LINE1            0x80
#define    CURSOR_LINE2            0xC0
#define    FOUR_BIT                0x28
#define    EIGHT_BIT               0x38

#define    LINE1_POS1               0x80
#define    LINE2_POS1               0xC0
#define    LINE3_POS1               0x94
#define    LINE4_POS1               0xD4  

 

Please forget about the details of the functions like 'GPIO_writePinVal' and 'GPIO_writePortVal' they work very well I am certain.

'GPIO_writePinVal' takes a port ID for either port A, B, C, or D , takes the pin number eg. P4 for pin no. 4 and takes a boolean value eg. GPIO_HIGH for logic 1,

then it writes the boolean value on the given pin of the PORTx register of the given port.

'GPIO_writePortVal' takes a port ID and an 8-bit value then writes the given 8-bit value into the PORTx register of the given port.

 

I think that there is something missing, any help can have an impact.

This topic has a solution.
Last Edited: Mon. Aug 5, 2019 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where do you set up the direction of your ports (inputs vs outputs)?  Maybe these functions do that for you.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

Compared to your AVR, LCD screens are SSSLLLLOOOOWWW, give it plenty of time to do it's internal init before you begin to talk to it!

Begin your program with a 1/2 sec delay and see  if that helps!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

Get the data sheet for any 16x2 LCD (assuming Hitachi based) and follow the initialization instructions for 8-bit data width.

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

Actually this type of LCD defaults to 8 bit mode, but you do have to wait for its internal init to complete before writing to it!

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

The 8-bit mode worked after some effort. But when I use the 4-bit mode it does not work.

This is the connection for 4-bit mode :

 

Connection and Simulation of an 16X2 LCD with AtMega32 , 4-bit mode

 

 

And this is the code :

#define F_CPU 12000000UL
 #include "HAL/LCD.h"
 #include "util/delay.h"

 int main(void)
 {

	GPIO_setPortDir(PORTA_ID, GPIO_OUTPUT);         //To make Port A an output Port
	GPIO_setPortDir(PORTB_ID, GPIO_OUTPUT);         //To make Port B an output Port

	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	//TIM_delay(15);
	_delay_ms(500);

	GPIO_writePinVal(PORTB_ID, P1, GPIO_LOW);
	GPIO_writePinVal(PORTB_ID, P2, GPIO_LOW);

        /************************* Commands ***********************************/

	uint8 command = FOUR_BIT;
	uint8 temp = command & 0x0F;      //Low nibble
	command = command & 0xF0;         //High nibble

	GPIO_writePinVal(PORTA_ID, P4, (command & 0x10) >> 4);
	GPIO_writePinVal(PORTA_ID, P5, (command & 0x20) >> 5);
	GPIO_writePinVal(PORTA_ID, P6, (command & 0x40) >> 6);
	GPIO_writePinVal(PORTA_ID, P7, (command & 0x80) >> 7);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
	GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
	GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
	GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = DISP_ON_CURSOR_OFF;
	temp = command & 0x0F;      //Low nibble
	command = command & 0xF0;   //High nibble

	GPIO_writePinVal(PORTA_ID, P4, (command & 0x10) >> 4);
	GPIO_writePinVal(PORTA_ID, P5, (command & 0x20) >> 5);
	GPIO_writePinVal(PORTA_ID, P6, (command & 0x40) >> 6);
	GPIO_writePinVal(PORTA_ID, P7, (command & 0x80) >> 7);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
	GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
	GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
	GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	//TIM_delay(2);

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

	command = CLR_SCR;
	temp = command & 0x0F;      //Low nibble
	command = command & 0xF0;   //High nibble

	GPIO_writePinVal(PORTA_ID, P4, (command & 0x10) >> 4);
	GPIO_writePinVal(PORTA_ID, P5, (command & 0x20) >> 5);
	GPIO_writePinVal(PORTA_ID, P6, (command & 0x40) >> 6);
	GPIO_writePinVal(PORTA_ID, P7, (command & 0x80) >> 7);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
	GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
	GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
	GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = LINE1_POS1;
	temp = command & 0x0F;      //Low nibble
	command = command & 0xF0;   //High nibble

	GPIO_writePinVal(PORTA_ID, P4, (command & 0x10) >> 4);
	GPIO_writePinVal(PORTA_ID, P5, (command & 0x20) >> 5);
	GPIO_writePinVal(PORTA_ID, P6, (command & 0x40) >> 6);
	GPIO_writePinVal(PORTA_ID, P7, (command & 0x80) >> 7);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
	GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
	GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
	GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

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

	command = CURSOR_INC;
	temp = command & 0x0F;      //Low nibble
	command = command & 0xF0;   //High nibble

	GPIO_writePinVal(PORTA_ID, P4, (command & 0x10) >> 4);
	GPIO_writePinVal(PORTA_ID, P5, (command & 0x20) >> 5);
	GPIO_writePinVal(PORTA_ID, P6, (command & 0x40) >> 6);
	GPIO_writePinVal(PORTA_ID, P7, (command & 0x80) >> 7);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
	GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
	GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
	GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

	GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
	_delay_us(1);
	GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
	_delay_us(100);

	while(1)
	{
		GPIO_writePinVal(PORTB_ID, P1, GPIO_HIGH);
		GPIO_writePinVal(PORTB_ID, P2, GPIO_LOW);

		uint8 data = 'H';
		temp = data & 0x0F;      //Low nibble
		data = data & 0xF0;      //High nibble

		GPIO_writePinVal(PORTA_ID, P4, (data & 0x10) >> 4);
		GPIO_writePinVal(PORTA_ID, P5, (data & 0x20) >> 5);
		GPIO_writePinVal(PORTA_ID, P6, (data & 0x40) >> 6);
		GPIO_writePinVal(PORTA_ID, P7, (data & 0x80) >> 7);

		GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
		_delay_us(1);
		GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);
		_delay_us(100);

		GPIO_writePinVal(PORTA_ID, P4, (temp & 0x01) >> 0);
		GPIO_writePinVal(PORTA_ID, P5, (temp & 0x02) >> 1);
		GPIO_writePinVal(PORTA_ID, P6, (temp & 0x04) >> 2);
		GPIO_writePinVal(PORTA_ID, P7, (temp & 0x08) >> 3);

		GPIO_writePinVal(PORTB_ID, P3, GPIO_HIGH);
		_delay_us(1);
		GPIO_writePinVal(PORTB_ID, P3, GPIO_LOW);

		_delay_us(100);
	}

	return 0;
 }

 

There is something wrong, can anyone see it?

Last Edited: Sat. Aug 3, 2019 - 09:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is VEE really connected to V+?? It's normally very close to ground but yours may be different.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:

Is VEE really connected to V+?? It's normally very close to ground but yours may be different.

 

VEE is connected to VCC, please tell me if the image of the connection is confusing to change it.

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

Show us the datasheet for you LCD, it will tell you there, it is usually connected to a pot (10K?) so that you can adjust the contrast.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The datasheet of my LCD is attached to this post.

Attachment(s): 

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

So what does it show on page 6??

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

John,

 

The OP is only do a simulation which may NOT care too much about the real world that you and I live in. cheeky

Ross McKenzie ValuSoft Melbourne Australia

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

I connected the circuit in hardware, use PortA pins 4, 5, 6, and 7 for data and Port B pins 1, 2, and 3 for control.

I used a potentiometer for VEE, and the LCD shows only squares of dots.

(Notice that the LCD was working in 8-bit mode with VCC connected to VCC)

I single-stepped the code in Atmel Studio 7 and all the registers have the proper data on them.

 

This is the new connection with a potentiometer and Port C for data.

 

 

Last Edited: Sat. Aug 3, 2019 - 10:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Had I seen that I would not care at all either. blush

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

4bit mode has a very specific timing requirement And command sequence to init it.
Check your data sheet for specifics. See page 13!
Jim

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Sat. Aug 3, 2019 - 11:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see you added  

GPIO_setPortDir(PORTA_ID, GPIO_OUTPUT);         //To make Port A an output Port
	GPIO_setPortDir(PORTB_ID, GPIO_OUTPUT);         //To make Port B an output Port

As mentioned, setting up the ports before using them is important!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

Most AVRFreaks would use peter fluery's LCD library as it just works, and go on with solving the real issue of the project.

http://homepage.hispeed.ch/peter...

 

Jim

PS same for serial USART and I2C as well!

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

The problem is solved and everything works well, I should have included the 0x33 and 0x32 commands before including the 0x28 command that sets the 4-bit mode.

As indicated in the datasheet page 13.

It is my first time to interface something other than the Arduino with an LCD, so I didn't know that the datasheet of an LCD is that important.

Thank you all. 

Last Edited: Mon. Aug 5, 2019 - 04:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

Most AVRFreaks would use peter fluery's LCD library as it just works, and go on with solving the real issue of the project.

http://homepage.hispeed.ch/peter...

 

Jim

PS same for serial USART and I2C as well!

 

 

 

Thanks for the library, but my job scope is implementing the libraries and drivers myself. Then writing codes based on my libraries for a project. 

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

AhmedH wrote:
Thanks for the library, but my job scope is implementing the libraries and drivers myself. Then writing codes based on my libraries for a project. 

No harm in looking at how he solved the problem!!!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

 

 

Thanks for the library, but my job scope is implementing the libraries and drivers myself. Then writing codes based on my libraries for a project. 

When I need to think outside of the box, I need to climb out first.   surprise

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

ki0bk wrote:

 

No harm in looking at how he solved the problem!!!

 

Jim

 

 

 

It was all about using the following in the initialization stage for the LCD

                GPIO_writePinVal(lcdPortID, lcdPins[2], GPIO_LOW);
                /* Making the E pin LOW */
		TIM_delay(500);
		/*The delay that is required before initialization of the LCD*/
		/* 500 milliseconds delay */

		LCD_command(lcdPortID, lcdPins, 0x33);        //This command is required in case of operating in 4-bit mode
		LCD_command(lcdPortID, lcdPins, 0x32);        //This command also is required in case of operating in 4-bit mode
		LCD_command(lcdPortID, lcdPins, FOUR_BIT);
		LCD_command(lcdPortID, lcdPins, DISP_ON_CURSOR_OFF);
		LCD_command(lcdPortID, lcdPins, CLR_SCR);
		LCD_command(lcdPortID, lcdPins, LINE1_POS1);
		LCD_command(lcdPortID, lcdPins, CURSOR_INC);

 

The 'LCD_command' function takes a command and sends it to the LCD, and generates the required delay for commands and produces the High-to-Low pulse for the E pin.

Last Edited: Tue. Aug 6, 2019 - 03:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

 

 

Thanks for the library, but my job scope is implementing the libraries and drivers myself. Then writing codes based on my libraries for a project. 

When I need to think outside of the box, I need to climb out first.   surprise

 

I prepare for a job in the embedded systems field, that requires writing libraries and drivers, and writing project codes too.

It is not for training or entertainment.

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

Your initialisation still is not correct for 4 bit mode.