Help getting started with first LCD

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

Hey everyone,

I'm having a bit of trouble getting started with this 16x2 LCD (Seiko L1672). It uses the KS0066 interface and I've come up with the following code from what I was able to gather around the forums.

#include 
#include 
#define F_CPU 100000UL    // default speed for delay.h (1Mhz)
#include 
    
int main(void) {    
    // Let LCD Boot up
    _delay_ms(4000);

    // Enable PB0, 1, and 2 for output (RS, RW, EN)
    DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2);

    // Enable PD0 - PD7 (D0 - D7 on LCD)
    DDRD = 0xFF;
    PORTD = 0x00;

    // Let LCD boot up
    _delay_ms(400);

    // Set RS to high
    PORTB = (1 << PB0);
    _delay_ms(40);

    // Set EN to high
    PORTB |= (1 << PB2);
    _delay_ms(40);

    // Turn Display ON
    PORTD = 0x0F;
    _delay_ms(40);          // datasheet specified at least 40us

    // Set EN to low
    PORTB &= ~(1 << PB2);

    while(1) {

    }   

    return 0;
}

I have RS, RW, and EN connected to PB0, 1 and 2 and the D0 - D7 lines connected to PD0 - PD7. The display comes on showing the first line full of squares (the same way it does when you just connect vcc, vlc, and gnd). Unfortunately, I can't seem to get a cursor - the datasheet specifies the command 0b00001111 to turn on the display and set the blinking cursor. I've added extra long delays just for testing. Can anyone point me in the right direction?

I'm using an ATMega16 with avr-gcc and I've attached the only datasheet I could find.

Any help would be great!

Thanks =]

Attachment(s): 

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

Check out my recent post at:

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

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

Hey Carl - thanks for the code example. I attempted to change it a little bit to match your setup but I'm getting the same results (just 1 line of black squares).

Here is the modified code

#include 

/*
 * Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the below copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. Livingston Electronics makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
 *
 *
 * 8 BIT LCD control program
 * Written by Carl W. Livingston
 * Modified in a attempt to get working by some other guy
 * Copyright Carl W. Livingston
 * microcarl@roadrunner.com
 * AVR Freaks member - microcarl
 * January 02, 2007
 * */ 

/*   //// From the LCD perspective \\\\
      LCD:R/W <-- PORTD:4
      LCD:RS <-- PORTD:5
      LCD:E <-- PORTD:6
      N/A <-> PORTD:7

      LCD:R/W <-- PORTD:4
      LCD:RS <-- PORTD:5
      LCD:E <-- PORTD:6
      LCD:Vee <-- CONTRAST
      LCD:DB0 <-- PORTB:0
      LCD:DB1 <-- PORTB:1
      LCD:DB2 <-- PORTB:2
      LCD:DB3 <-- PORTB:3
      LCD:DB4 <-- 4.7K Ohm <-- PORTx:4
      LCD:DB5 <-- 4.7K Ohm <-- PORTx:5
      LCD:DB6 <-- 4.7K Ohm <-- PORTx:6
      LCD:DB7 <-- 4.7K Ohm <-- PORTx:7

//// From the I/O PORTD perspective \\\\
      PORTD:4 --> LCD:R/W
      PORTD:5 --> LCD:RS
      PORTD:6 --> LCD:E
      PORTD:7 <-> N/A   
   
      PORTB:0 --> LCD:DB0
      PORTB:1 --> LCD:DB1
      PORTB:2 --> LCD:DB2
      PORTB:3 --> LCD:DB3
      PORTB:4 --> 4.7K Ohm --> LCD:DB4
      PORTB:5 --> 4.7K Ohm --> LCD:DB5
      PORTB:6 --> 4.7K Ohm --> LCD:DB6
      PORTB:7 --> 4.7K Ohm --> LCD:DB7
*/

/*************************************************************/
/*************************************************************/
// If you want to use a different I/O port for LCD control & data,
// do it here!!!
#define LCD_DATA_OUT PORTB
#define LCD_DATA_IN PINB
#define LCD_DATA_DDR DDRB

#define LCD_CONTROL_OUT PORTD
#define LCD_CONTROL_IN PIND
#define LCD_CONTROL_DDR DDRD

// Define LCD Read/Write as PORTx, 0x10;
#define LCD_RW 4
// Define LCD Register Select as PORTx, 0x20; 
#define LCD_RS 5
// Define LCD Enable as PORTx, 0x40; 
#define LCD_E 6
/*************************************************************/
/*************************************************************/

// LCD busy status bit
#define LCD_BUSY 7
// LED control bit
#define LED 1
// BAUD rate control bits
#define J_1 2
#define J_2 3
#define CGRAM 6 

// Turn on power to the display, no cursor
#define   PWR_ON   0x0C
// Set 8 data bits
#define   DATA_8   0x30
// Set 8 data bits, 4 display lines
#define   LINE_8x4   0x38
// Clear display command      
#define CLR_DSP 0x01
// Character generator RAM command
#define REG_MODE 0xFE

#define NULL 0x00

void LCD_Delay (unsigned int);
void LCD_PutCmd (char);
void LCD_PutChar (char);
char LCD_BusyWait (void);
void IO_INIT (void);
void LCD_INIT (void);

int main (void) {
          // Initialize the Mega16 I/O
          IO_INIT ();
          // Initialize the HD44780 LCD controller
          LCD_INIT ();
   
          while (1) {
              LCD_PutChar('b');
          }         
}

// Clock cycle = 67nS @ 14.7456MHz   
// Delay resolution ~ 1uS @ 14.7456MHz
void LCD_Delay (unsigned int d) {
               while (d-- != 0)
               ;
               asm("nop"); // Make the delay time a bit closer to the predicted delay time.
                           // Experimentally setup with an Oscilloscope.
}

void LCD_PutCmd (char Cmd) {
    LCD_CONTROL_OUT &= ~(1<<LCD_RS);
    LCD_BusyWait();
    LCD_DATA_OUT = Cmd;   
    asm ("nop");   
    LCD_CONTROL_OUT |= (1<<LCD_E);
    asm ("nop"); // PWeh must be 230nS minimum
    asm ("nop"); // nop = 67nS @ 14.7456MHz   
    asm ("nop");
    asm ("nop"); // Here, E = 271nS @ 14.7456MHz   
    LCD_CONTROL_OUT &= ~(1<<LCD_E);
    asm ("nop");
    LCD_CONTROL_OUT |= (1<<LCD_RS);
}

void LCD_PutChar (char c) {
    LCD_CONTROL_OUT &= ~(1<<LCD_RS);
    LCD_BusyWait();
    LCD_CONTROL_OUT |= (1<<LCD_RS);
    LCD_DATA_OUT = c;
    asm ("nop");         
    LCD_CONTROL_OUT |= (1<<LCD_E);
    asm ("nop"); // PWeh must be 230nS minimum
    asm ("nop"); // nop = 67nS @ 14.7456MHz   
    asm ("nop");
    asm ("nop"); // Here, E = 271nS @ 14.7456MHz
    LCD_CONTROL_OUT &= ~(1<<LCD_E);
}

char LCD_BusyWait (void) {
    unsigned char LCDStatus;
    LCD_DATA_DDR = 0x00; // Set LCD data port to inputs
    LCD_CONTROL_OUT |= (1<<LCD_RW);
    asm ("nop");
    do {
       LCD_CONTROL_OUT |= (1<<LCD_E);   
      asm ("nop"); // PWeh must be 230nS minimum
      asm ("nop"); // nop = 67nS @ 14.7456MHz   
      asm ("nop");    
      asm ("nop"); // Here, E = 271nS @ 14.7456MHz
      LCDStatus = LCD_DATA_IN;
      LCD_CONTROL_OUT &= ~(1<<LCD_E);
    } while ((LCDStatus & (1<<LCD_BUSY)) == (1<<LCD_BUSY));
    LCD_CONTROL_OUT &= ~(1<<LCD_RW);   
    LCD_DATA_DDR |= 0xFF; // Set LCD data port to outputs      
    return (LCDStatus);
}         

void IO_INIT (void) {
    LCD_Delay (60000); // Wait for the LCD display to boot up
    // Set J_2:J_1 PULL-UPS active
    LCD_CONTROL_OUT = (1<<J_2) | (1<<J_1);
    // Set LCD_control J_2:J_1 to inputs   
    LCD_CONTROL_DDR = 0xF2;
    LCD_CONTROL_OUT |= (1<<LCD_RS); // Set LCD_RS HIGH   
    // Delay resolution ~ 1uS @ 14.7456MHz         
    LCD_Delay (15000); // Need 15mS delay for LCD to power up

    // Initialize the AVR controller I/O
    LCD_DATA_DDR = 0xFF; // Set LCD_DATA_OUT as all outputs
    LCD_DATA_OUT = 0x00; // Set LCD_DATA_OUT to logic low
}

void LCD_INIT (void) {
    // Initialize the LCD controller
    LCD_PutCmd (LINE_8x4); // Set 8 bit data, 4 display lines
    LCD_PutCmd (CLR_DSP); // Power up the display
    LCD_PutCmd (PWR_ON); // Power up the display
    LCD_Delay (30000);
    LCD_BusyWait();
}

I'm missing a basic step here, I just can't figure it out. Any help would be great.

Thanks!

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

Contrast adjustment?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"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

JohanEkdahl wrote:
Contrast adjustment?

Sorry, didn't mention that - I have VLC connected to a 10K pot, I've adjusted up and down but still no cursor.

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

The line of black boxes indicate that the LCD hasn't been initialized properly.

You obviously have some sort of hardware error - Fosc other then what you think, or a wiring error.

The code that I gave you works as, several AVRFreaks members have used the My_LCD Serial Backpack and the code independently in their own projects. The code has been tested on about 20 different HD44780 LCD controller clones, as well. Only one HD44780 clone controller (an odd ball Optrex clone) model gave me problems, and that issue was corrected.

I'd be looking that you are running the controller at the Fosc that you think you are and, I'd also be checking for wiring errors.

One other thing...

If you are running the cMega16 controller faster the 14.7456MHz, the timing delays won't be long enough.

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:
The line of black boxes indicate that the LCD hasn't been initialized properly.

You obviously have some sort of hardware error - Fosc other then what you think, or a wiring error.

The code that I gave you works as, several AVRFreaks members have used the My_LCD Serial Backpack and the code independently in their own projects. The code has been tested on about 20 different HD44780 LCD controller clones, as well. Only one HD44780 clone controller (an odd ball Optrex clone) model gave me problems, and that issue was corrected.

I'd be looking that you are running the controller at the Fosc that you think you are and, I'd also be checking for wiring errors.

One other thing...

If you are running the cMega16 controller faster the 14.7456MHz, the timing delays won't be long enough.

Hey Carl - I'm sure you're code works so no need to defend it. I'm just trying to debug this... I've double checked the wiring - what does Fosc mean? Also, I set the speed on the mega16 to just 1mhz. Is there a way to manually test the LCD to see if it actually works?

Thanks again guys

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

Here's three things to do:

1) As Carl hints at, double check your wirings. Also check for shorts and broken connections like.

2) As a diagnostic, lower the frequency the AVR runs at to a ridicolously low value, eg 1 MHz or even lower. This is for trying to reveal timing problems where the AVR outruns the display modules controller.

3) Sleep on it...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"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

If you have the black boxes shown and you can make them fade in and out by the contrast pot then that part of your hardware is correct.

If the black boxes remain after you try the initialization then that is not working correctly.

Pete

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

uidzer0 wrote:
...what does Fosc mean? Also, I set the speed on the mega16 to just 1mhz.

Well, if you were referring to the data-sheet you would see in the USART section that Fosc is the frequency at which the micro-controller is operating. We have been looking at the data-sheet, for both the Mega16 and the LCD, right?

uidzer0 wrote:
Is there a way to manually test the LCD to see if it actually works?

Actually, this is how I initially learned to control the HD44780 LCD displays - toggle switches and a lot of focus.

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:

Actually, this is how I initially learned to control the HD44780 LCD displays - toggle switches and a lot of focus.

Ok, I'll take this approach - just so I know that I understand this properly. To send a command I need to first set RS High, then send the command, then set E High, then set E to low?

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

uidzer0 wrote:
Ok, I'll take this approach - just so I know that I understand this properly. To send a command I need to first set RS High, then send the command, then set E High, then set E to low?
No! Bring RS and R/W low, wait about 50nS and the the LCD will accept a command, put the command data on the buss, bring E high for at least 270 nS, then bring E low. wait about 50nS and bring RS and R/W high

The same for sending ASCII text, except RS stays high R/W goes low and E toggles as in the above. The LCD will accept ASCII text.

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

Well manually initializing didn't seem to do the trick... I'm going to try to get another lcd and give that a shot. I managed to find a couple other datasheets for this thing and all of them are different, ugh. Thanks for the help guys.

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

uidzer0 wrote:
Well manually initializing didn't seem to do the trick... I'm going to try to get another lcd and give that a shot. I managed to find a couple other datasheets for this thing and all of them are different, ugh. Thanks for the help guys.

The waveform relationships between RS, R/W, E & DB7:DB0 will be the exact same thing, from HD44780 clone data-sheet to HD44780 clone data-sheet. What varies will be slight time delays from when RS & R/W change state, to when E rises to when data is accepted by DB7:DB0 the length of E, to when E falls and finally to when RS & R/W change state.

Compare the waveforms between data-sheets, and you find that they all look identical, that they all have the same terminology, and they all share only slight timing variances.

Once you understand the timing relationships among RS, R/W, E and DB7:DB0, it's a simple matter.

As far as manual testing the LCD with toggles switches goes, if you didn't debounce the E control line, I doubt that you will get the LCD to act properly, as the E control line is the most critical of the control lines, and the most temperamental.

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