Timing error of 16x2 LCD on ATMEGA1284P

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

Hello all,

 

I have been trying to fix the timing issue ( I hope it is timing issue) on a 16x2 lcd connected to my ATMEGA1284P chip. I made a custom PCB using the ATMEGA1284P chip as the MCU. 

 

The header files: I am using Peter Fleury's lcd.h and lcd.c at Peter Fleury's page

 

THE PROBLEM: The 16x2 LCD always has a solid black square on row 1 and blank on row 2. I have researched and a lot of people tied  this issue to timing. I have tried to set the delay after init to something high but i still run in the lcd failing to initialize. Here is my timing setup on the header file. I place an oscope on the E pin and I see there is a signal that went high then low, so it looks like it tried to initialize. I can't seem to figure out why, all the physical connection looks good, tested using a multimeter for continuity.

 

I am a student, anyone have any clue on why is it so hard to initialize this 16x2 LCD, the pin connection seems straight forward, the only thing i got to work is the contrast potentiometer...

 

I have attached my lcd.h, lcd.c, and main.c files

 

#ifndef LCD_DELAY_BOOTUP
#define LCD_DELAY_BOOTUP   20000     /**< delay in micro seconds after power-on  */
#endif
#ifndef LCD_DELAY_INIT
#define LCD_DELAY_INIT      5000      /**< delay in micro seconds after initialization command sent  */
#endif
#ifndef LCD_DELAY_INIT_REP
#define LCD_DELAY_INIT_REP    64      /**< delay in micro seconds after initialization command repeated */
#endif
#ifndef LCD_DELAY_INIT_4BIT
#define LCD_DELAY_INIT_4BIT   64      /**< delay in micro seconds after setting 4-bit mode */
#endif
#ifndef LCD_DELAY_BUSY_FLAG
#define LCD_DELAY_BUSY_FLAG    4      /**< time in micro seconds the address counter is updated after busy flag is cleared */
#endif
#ifndef LCD_DELAY_ENABLE_PULSE
#define LCD_DELAY_ENABLE_PULSE 1      /**< enable signal pulse width in micro seconds */
#endif

 

The physical connections are all on PORTC, with pin assignments are as follow (snippet setup from the header file):

 

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

#if LCD_IO_MODE

#ifndef LCD_PORT
#define LCD_PORT         PORTC        /**< port for the LCD lines   */

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

 I have tested each pin on PORTC by blinking an LED, they work as expected.

 

Here is my main.c code:

 

#define F_CPU 8000000UL
#include <avr/io.h>
#include "lcd.h"
#include <util/delay.h>

void adc_init()
{
		//AREF = AVcc
	ADMUX = (1<<REFS0);

	//ADC Enable and prescaler of 128
	//16MHZ/128 = 125KHZ

	ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

uint16_t adc_read(uint8_t ch)
{
	//select adc channel 0-7
	//AND with 111 will keep value of ch between 0 and 7
	ch &=0b00000111;

	ADMUX = (ADMUX & 0xF8) | ch;

	//start single conversion by writing "1" to ADSC

	ADCSRA |= (1<<ADSC);

	//wait for conversion to complete

	while(ADCSRA & (1<<ADSC));

	return(ADC);
}

int main(void)
{
	lcd_init(LCD_DISP_ON_CURSOR_BLINK); //initialize 16x2 lcd
	uint16_t sensor1;

	lcd_putc("a"); //test print
	DDRB = 0b11111111; // connect LED to PD0
	adc_init();
	_delay_ms(50);

    while (1)
    {

		sensor1 = adc_read(0); //read adc on PORTA pin PA0
		if (sensor1)
		{
			PORTB = 0b00000001;

		}

		else
		{

			PORTB = 0b00000000;
		}

    }
}

 

Attachment(s): 

This topic has a solution.
Last Edited: Tue. May 14, 2019 - 01:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have chosen to put your LCD on PORTC which is used by JTAG.

 

Add these two lines to the start of main()

MCUCR = (1<<JTD);   //disable JTAG in software
MCUCR = (1<<JTD);

David.

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

Hello,

 

I disable JTAG in software as per your recommendation, still getting the error where it fails to initialize, anywhere else you can see there is a problem with these 16x2 lcd? I have attached a picturefail to initialize

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


Have you absolutely proved your connection by testing between the uC pin and the pins right on the LCD PCB?

 

The reason I ask is that this section of your board...

 

 

...seems to show that you are using PC4 to PC7 to connect to your LCD data lines.

 

Perhaps a posting schematic, or clear PCB layout, would help.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define F_CPU 8000000UL

The above line says your AVR is running at 8MHz, if it is not, then all of the delays that depend on that value are wrong.   It is common to find that the AVR is not running at the expected speed due to the fuse setting CLK/8 fuse is set by default, if this has not been changed, then your AVR is running at 1MHz and so will be 8 times slower than expected.  This will cause your LCD init to fail.

Verify your fuse settings, or post them here and we can verify they are correct.

 

Jim

 

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

share.robinhood.com/jamesc3274

 

 

 

Last Edited: Tue. May 14, 2019 - 12:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No,  1MHz will NOT make it fail.

 

Looking at your photo.  PC4-PC7 seems to be connected to LCD_D4 .. LCD_D7.

I would guess that PC0 is connected to LCD_RS.    Only you can trace the pcb or preferably study the schematic.

 

So according to my crystal ball:

#ifndef LCD_DATA0_PIN
#define LCD_DATA0_PIN    4            /**< pin for 4bit data bit 0  */
#endif
#ifndef LCD_DATA1_PIN
#define LCD_DATA1_PIN    5            /**< pin for 4bit data bit 1  */
#endif
#ifndef LCD_DATA2_PIN
#define LCD_DATA2_PIN    6            /**< pin for 4bit data bit 2  */
#endif
#ifndef LCD_DATA3_PIN
#define LCD_DATA3_PIN    7            /**< pin for 4bit data bit 3  */
#endif
#ifndef LCD_RS_PORT
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#endif
#ifndef LCD_RS_PIN
#define LCD_RS_PIN       0            /**< pin  for RS line         */
#endif
#ifndef LCD_RW_PORT
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#endif
#ifndef LCD_RW_PIN
#define LCD_RW_PIN       1            /**< pin  for RW line         */
#endif
#ifndef LCD_E_PORT
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#endif
#ifndef LCD_E_PIN
#define LCD_E_PIN        2            /**< pin  for Enable line     */
#endif

I strongly recommend that you put F_CPU in your AS7.0 Project Symbols.

This means that  main.c and lcd.c see the same value.

 

David.

 

p.s.   No I don't know why they call LCD_DB4 "LCD_DATA0_PIN".   Surely "LCD_DATA4_PIN" would be more intuitive.

Last Edited: Tue. May 14, 2019 - 01:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OMG, you are right!!

 

I wired PC0-PC2 to RW/RS/and E

 

and PC4-PC7 to DB4-db7

 

BUT IN THE HEADER FILE I LABELED WRONG....DOHHHHHHHH

 

IT WORKS ALL  FINE NOW.....THANK YOU!!!!

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

Nice catch David!

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

share.robinhood.com/jamesc3274

 

 

 

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

Brian spotted it before I did.

 

As a pedantic point:

1. Studio4 forced you to configure F_CPU as a project-wide Symbol.

2. AS7.0 could simply put F_CPU=1MHz into the ProjectTemplate under "All Configurations"

 

Punters who put F_CPU into individual files would soon get fed up with the Warnings.

And they would correct the "default" value.

 

David.