ATmega328P - Scrolling text on Hitachi HD44780 (16x2) LCD

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

Hi, I'm having difficulty getting text to scroll on the Hitachi HD44780 LCD (in 1-line mode).

I've placed the Hitachi's shift (left) command within an infinite loop

but no luck getting the text to move.  Any ideas?

 

Here's the code (haven't added functions yet):

 

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

#define RS_PIN 0
#define E_PIN 1

#define DISPLAY_ON_NO_CURSOR 0x0C
#define DISPLAY_ON_CURSOR_BLINK 0x0F
#define CLEAR_DISP 0x01

#define CONTROL_PORT PORTB
#define CONTROL_PORT_DIR DDRB

#define DATA_PORT PORTD
#define DATA_PORT_DIR DDRD

int main(void)
{
    //********************* OUTPUT PINS **********************
    CONTROL_PORT_DIR |= (1<<RS_PIN);
    CONTROL_PORT_DIR |= (1<<E_PIN);
    DATA_PORT_DIR = 0xFF;

    _delay_ms(20); //Delay to give LCD time to boot up

    //********************** DISPLAY ON ***********************

    CONTROL_PORT &= ~(1<<RS_PIN); //Command mode - RS set low

    DATA_PORT = DISPLAY_ON_NO_CURSOR;
    _delay_ms(1); //Delay to let data settle on pins

    //Latch data. Falling edge-triggered clock
    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    //***************** CLEAR AND RESET CURSOR *****************

    DATA_PORT = CLEAR_DISP;
    _delay_ms(2);

    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    //********************* PUT INTO DATA MODE *****************

    CONTROL_PORT |= (1<<RS_PIN);

    //********************* SEND CHARACTERS *****************

    DATA_PORT = 'S';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    DATA_PORT = 'C';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    DATA_PORT = 'R';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    DATA_PORT = 'O';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN);
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN);

    DATA_PORT = 'L';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN); //E pin high
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN); //E pin low

    DATA_PORT = 'L';
    _delay_ms(1);

    CONTROL_PORT |= (1<<E_PIN); //E pin high
    _delay_ms(1);
    CONTROL_PORT &= ~(1<<E_PIN); //E pin low

    while(1)

    {
        DATA_PORT = 0x1C;
        _delay_ms(1000);

        CONTROL_PORT |= (1<<E_PIN); //E pin high
        _delay_ms(1);
        CONTROL_PORT &= ~(1<<E_PIN); //E pin low
    }

}

 

Last Edited: Tue. Jan 2, 2018 - 06:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're not switching to "command mode" before sending the scroll instruction.

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

The command mode thing is probably right. You don't need a full millisecond for the enable pin, a microsecond will do. Also, you appear to be delaying 2ms after setting the data port to clear, but that's wrong; you should be delaying 2ms after sending the clear command, which is to say, after pulsing the enable pin. I think there's a corresponding _delay_us().

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

JohanEkdahl wrote:

You're not switching to "command mode" before sending the scroll instruction.

 

Many thanks JohanEkdahl, I didn't spot that..  It works! :)

 

Changed code to:

 

CONTROL_PORT &= ~(1<<RS_PIN); //Command mode - RS set low

	while(1)
	{
		DATA_PORT = 0x1C;
		_delay_ms(500);

		CONTROL_PORT |= (1<<E_PIN); //E pin high
		_delay_ms(1);
		CONTROL_PORT &= ~(1<<E_PIN); //E pin low
		_delay_ms(1);
	}

I'd like to get the text to reappear on the left side of the LCD as soon as it disappears from the right.

Could you suggest how I could get last 'L' character to appear on the left side of the screen, once the

'S' character has gone off the screen to the right?

 

 

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

the_real_seebs wrote:

The command mode thing is probably right. You don't need a full millisecond for the enable pin, a microsecond will do. Also, you appear to be delaying 2ms after setting the data port to clear, but that's wrong; you should be delaying 2ms after sending the clear command, which is to say, after pulsing the enable pin. I think there's a corresponding _delay_us().

 

Thanks the_real_seebs, I'll get that sorted.

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

the_real_seebs wrote:

The command mode thing is probably right. You don't need a full millisecond for the enable pin, a microsecond will do. Also, you appear to be delaying 2ms after setting the data port to clear, but that's wrong; you should be delaying 2ms after sending the clear command, which is to say, after pulsing the enable pin. I think there's a corresponding _delay_us().

 

Putting a delay of 1us for all of the enable pin commands

 

CONTROL_PORT |= (1<<E_PIN);
_delay_us(1);
CONTROL_PORT &= ~(1<<E_PIN);

causes the leftmost character 'S' to disappear from the screen.

 

Do you mean I should put a 2ms delay as follows:

 

    DATA_PORT = CLEAR_DISP;

    CONTROL_PORT |= (1<<E_PIN);
    _delay_us(1);
    CONTROL_PORT &= ~(1<<E_PIN);
    _delay_ms(2);

 

 

 

 

 

 

Last Edited: Tue. Jan 2, 2018 - 06:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In these "modern" times I would not trust the scroll function to be implemented (properly) in a HD44780 clone.

But because those displays only hold a very limited amount of data you can easily write the scroll funcion in your uC firmware yourself.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

I'd like to get the text to reappear on the left side of the LCD as soon as it disappears from the right.

Could you suggest how I could get last 'L' character to appear on the left side of the screen, once the

'S' character has gone off the screen to the right?

This is a bit tricky, complicated by the fact that you are using a 16x2 device in the 1-line mode.  For some background information about the LCD controller memory addressing and how that affects what you are trying to do you might like to follow the LCD Addressing link at http://web.alfredstate.edu/faculty/weimandn .  After you read that you may want to consider the suggestion in the post just above although I don't agree with the premise in his first sentence.

 

Don