I finally got round to writing my own ‘Hello World!’ for an LCD connected to an Arduino Nano. So what! I hear you all cry. Well, I wanted to do it without the Arduino LCD library. Why? Well, it’s a challenge isn’t it!
First off, the following PDFs are invaluable in understanding the controller on the majority of the LCD on the market utilising the ubiquitous Hitachi HD44780 controller.
LCD Controller part 1
LCD Controller part 2
Oh, in 4-bit mode only!
#define LCD_ENABLE (0x00 << 2)
#define LCD_CLEAR (0x01 << 2)
#define LCD_HOME (0x02 << 2)
#define LCD_DISP_ON_UNDERLINE_BLINK (0x0f <>2)
#define LCD_8BITMODE (0x30 >>2)
#define LCD_RESET 0x38
#define LCD_RS_COMMAND_MODE 0x00
#define LCD_RS_DATA_MODE 0x01
int RS=A0;
int RW=A1;
int ENABLE=A2;
void setup()
{
delay(100); // power on delay
DDRD=B11111100; // set bits on D2-D7 as outputs
PORTD=0;
pinMode (ENABLE,OUTPUT);
pinMode (RW,OUTPUT);
pinMode (RS,OUTPUT);
digitalWrite (RW,LOW);
}
wire D2 to LCD D4
wire D3 to LCD D5
wire D4 to LCD D6
wire D5 to LCD D7
wire A2 to LCD Enable pin
wire A1 to LCD R/W pin
wire A0 to LCD RS pin
The basic sequence of operation is as follows:
Once the LCD had powered on the init sequence should be:
- set the read/write line permanently low to write as we won’t be reading from the display – or tie to 0V
- set command mode (RS pin) (logic 0)
- set 8 bit mode X 3
- set the data lines;
- pulse the enable line (high to low transition and back to low again
#define LCD_ENABLE (0x00 << 2)
#define LCD_CLEAR (0x01 << 2)
#define LCD_HOME (0x02 << 2)
#define LCD_DISP_ON_UNDERLINE_BLINK (0x0f <>2)
#define LCD_8BITMODE (0x30 >>2)
#define LCD_RESET 0x38
#define LCD_RS_COMMAND_MODE 0x00
#define LCD_RS_DATA_MODE 0x01
int RS=A0;
int RW=A1;
int ENABLE=A2;
void setup()
{
delay(100); // power on delay
DDRD=B11111100; // set bits on D2-D7 as outputs
PORTD=0;
pinMode (ENABLE,OUTPUT);
pinMode (RW,OUTPUT);
pinMode (RS,OUTPUT);
digitalWrite (RW,LOW);
}
wire D2 to LCD D4
wire D3 to LCD D5
wire D4 to LCD D6
wire D5 to LCD D7
wire A2 to LCD Enable pin
wire A1 to LCD R/W pin
wire A0 to LCD RS pin
The basic sequence of operation is as follows:
Once the LCD had powered on the init sequence should be:
set the read/write line permanently low to write as we won't be reading from the display - or tie to 0V
set command mode (RS pin) (logic 0)
set 8 bit mode X 3
set the data lines;
pulse the enable line (high to low transition and back to low again
void hd44780_init() // it's recommended that the 8-bit mode be sent 3 times to ensure full initialisation of the LCD controller
{
for (int poweron=0; poweron<3; poweron++)
{
digitalWrite(RS,LCD_RS_COMMAND_MODE); // switch LCD into COMMAND_MODE
PORTD=LCD_8BITMODE;
pulse();
}
}
void init_4bitmode()
{
delay(5);
digitalWrite(RS,LCD_RS_COMMAND_MODE);
PORTD=LCD_4BITMODE;
delay(5);
pulse();
}
void lcd_clear()
{
digitalWrite(RS,LCD_RS_COMMAND_MODE);
PORTD=(0 <<2);
pulse();
PORTD=(1 <<2);
pulse();
delay(200);
}
void lcd_2linemode()
{
digitalWrite(RS,LCD_RS_COMMAND_MODE);
PORTD=(2 <<2);
pulse();
PORTD=(8 <<2);
pulse();
}
void lcd_displayon() // also cursor underline and blink
{
digitalWrite(RS,LCD_RS_COMMAND_MODE);
PORTD=(0 <<2);
pulse();
PORTD=(0xf <<2);
pulse();
}
void pulse()
{
digitalWrite(ENABLE,HIGH);
delayMicroseconds(40);
digitalWrite(ENABLE,LOW);
delayMicroseconds(40);
}
void lcd_print_char(char *nextchar)
{
digitalWrite(RS,LCD_RS_DATA_MODE);
while (*nextchar !='\0')
{
char lower=(*nextchar & 0x0f);
char upper=(*nextchar >> 4) &0x0f;
char shiftup=(upper << 2);
char shiftlow=(lower << 2);
PORTD=shiftup;
delay(5);
pulse();
PORTD=shiftlow;
delay(5);
pulse();
nextchar++;
}
}
void loop()
{
hd44780_init(); // post power-on-reset send 8 bit mode three times to ensure reset
init_4bitmode(); // now switch to 4-bit mode
lcd_clear(); // clear the display and set cursor position to home
lcd_2linemode(); // set two line mode for the 2X16 HD44780 DEM controller
lcd_displayon(); // finally, turn the LCD's display on so we can see this!!!!
lcd_print_char("Hello World!");
while (1==1)
{
}
}
One response to “Hitachi HD44780 LCD Character Display”