-1
\$\begingroup\$

Currently writing a program for ATmega32 MCU and I'm having issues with LCD not working.

Tested with several ATmega32 MCUs as well as with several HD44780 compatible LCD modules (one of them is DEM 16216 SGH http://www.csd-electronics.de/data/pdf/DEM16216SGH.pdf )

Tested with init method described in datasheet as well as current one. Screen turns blank after init (or shows blocks if contrast is adjusted) and nothing else happens.

ATmega32 is running on internal 1MHz clock
5V power supply
PORTC pins are connected to data ports of LCD (PC0-DB0...PC7-DB7)
E pin connected to PD0, RW - PD1, RS - PD2
All connections have been tested several times and there doesn't seem to be problems.


main.c file

#ifndef F_CPU
#define F_CPU 1000000UL
#endif

#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"

int i = 0;

int main (void)
{
   lcd_init();
   while(1)
   {
      lcd_goto_xy(2, 0);

      lcd_character('H');
      lcd_character('e');
      lcd_character('l');
      lcd_character('l');
      lcd_character('o');
   }
}

lcd.h file

#ifndef  LCD_H
#define  LCD_H

#ifndef F_CPU
#define F_CPU 1000000UL
#endif

#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>

#define  lcd_datadir    DDRC
#define  lcd_data       PORTC
#define  lcd_dataread   PINC
#define  lcd_controldir DDRD
#define  lcd_control    PORTD
#define  lcd_e          PD0
#define  lcd_rw         PD1
#define  lcd_rs         PD2

unsigned char  lcd_row[2] = {0, 40};

void lcd_toggle_e (void) {
   lcd_control |= (1<<lcd_e);
   asm volatile ("NOP");
   asm volatile ("NOP");
   lcd_control &= ~(1<<lcd_e);
}

void lcd_check_if_busy (void) {
   lcd_datadir = 0x00;
   lcd_control &= ~(1<<lcd_rs);
   lcd_control |= (1<<lcd_rw);
   while (lcd_data >= 0x80) {
   }
   lcd_datadir = 0xFF;
}

void lcd_command (unsigned char command) {
   lcd_check_if_busy();
   lcd_control &= ~(1<<lcd_rs);
   lcd_control &= ~(1<<lcd_rw);
   lcd_data = command;
   lcd_toggle_e();
   lcd_data = 0;
}

void lcd_character (unsigned char letter) {
   lcd_check_if_busy();
   lcd_control |= (1<<lcd_rs);
   lcd_control &= ~(1<<lcd_rw);
   lcd_data = letter;
   lcd_toggle_e();
   lcd_data = 0;
}

void lcd_goto_xy (uint8_t x, uint8_t y) {
   lcd_command(0x80 + lcd_row[y] + x);
}


void lcd_init(void) {
   lcd_datadir = 0xFF;
   lcd_controldir |= 0x07;
   lcd_control = 0x00;

   for (int power_up_time = 0; power_up_time<10; power_up_time++) {
      _delay_ms(10);
   }

   lcd_data = 0x30;
   lcd_toggle_e();
   _delay_ms(10);
   lcd_data = 0x30;
   lcd_toggle_e();
   _delay_ms(2);
   lcd_data = 0x30;
   lcd_toggle_e();
   _delay_ms(2);

   lcd_command(38);
   lcd_command(08);
   lcd_command(01);
   lcd_command(06);

   lcd_command(0F); // display, cursor, blink on

}
#endif

Any insight or help is appreciated.

\$\endgroup\$
  • \$\begingroup\$ Are you using a variable resistor between VSS, VDD and V0? \$\endgroup\$ – Damon May 19 '14 at 10:52
  • 1
    \$\begingroup\$ "while (lcd_data >= 0x80)" seems odd to me (arithmetic test instead of bit test)...why not simply "while (lcd_data & 0x80)"? Can you drive an LED to confirm you're actually returning from this routine? \$\endgroup\$ – aja May 19 '14 at 11:58
1
\$\begingroup\$

Try to initalise it in 4-bit mode in this way:

http://www.vidnis.com/2013/10/16x2-lcd-initialization-hitech-c-code.html

Between rising and falling edge of the instruction "E" (Enable) put small delay of ex. 2-3 microseconds.

\$\endgroup\$
  • 1
    \$\begingroup\$ Didn't work with C port, however it worked when mnoved data pins to D port. Reason for this is because I forgot to disable JTAG. \$\endgroup\$ – elent May 19 '14 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.