LCD Interfacing with Atmega16
LCD display:
The display used here is 16x2 LCD (Liquid Crystal Display); this means 16 characters per line by 2 lines. A very popular standard exists which allows us to communicate with the vast majority of LCDs regardless of their manufacturer. The standard is referred to as HD44780U, which refers to the controller chip which receives data from an external source (in this case, the Atmega16) and communicates directly with the LCD. The 44780 standard requires 3 control lines as well as either 4 or 8 I/O lines for the data bus. Here we are using 8-bit mode of LCD, i.e., using 8-bit data bus.
The three control lines are referred to as EN, RS, and RW.
The EN line is called "Enable." This control line is used to tell the LCD that we are sending it data. To send data to the LCD, our program should make sure this line is low (0) and then set the other two control lines and/or put data on the data bus. When the other lines are completely ready, bring EN high (1) and wait for the minimum amount of time required by the LCD datasheet (this varies from LCD to LCD), and end by bringing it low (0) again.
The RS line is the "Register Select" line. When RS is low (0), the data is to be treated as a command or special instruction (such as clear screen, position cursor, etc.). When RS is high (1), the data being sent is text data which should be displayed on the screen. For example, to display the letter "T" on the screen you would set RS high.
The RW line is the "Read/Write" control line. When RW is low (0), the information on the data bus is being written to the LCD. When RW is high (1), the program is effectively querying (or reading) the LCD. Only one instruction ("Get LCD status") is a read command. All others are write commands--so RW will almost always be low.
In our case of an 8-bit data bus, the lines are referred to as DB0, DB1, DB2, DB3, DB4, DB5, DB6, and DB7.
Fig: 16X2 LCD display
Function | Pin Number | Name | Logic State | Description |
Ground | 1 | Vss | - | 0V |
Power supply | 2 | Vdd | - | +5V |
Contrast | 3 | Vee | - | 0 - Vdd |
Control of operating | 4 | RS | 0 | D0 – D7 are interpreted as commands |
5 | R/W | 0 | Write data (from controller to LCD) | |
6 | E | 0 | Access to LCD disabled | |
Data / commands | 7 | D0 | 0/1 | Bit 0 LSB |
8 | D1 | 0/1 | Bit 1 | |
9 | D2 | 0/1 | Bit 2 | |
10 | D3 | 0/1 | Bit 3 | |
11 | D4 | 0/1 | Bit 4 | |
12 | D5 | 0/1 | Bit 5 | |
13 | D6 | 0/1 | Bit 6 | |
14 | D7 | 0/1 | Bit 7 MSB |
Table: Pin description of LCD
LCD Circuit:
To Pin 4,5,6 To PortA
Of PortD
Fig: LCD Connections
Testing (D.C. Conditions):
- PIN 7 to 14 are data pins.
- Voltage at pin 2 is +5.00V
- Pin 3 is connected to 10K variable resistance for contrast setting.
- Pin 4, 5, 6 are control lines connected to PORT D.
Actual circuit diagram is similar to the LCD connections in this CIRCUIT.
LCD Basic Commands:
No. | Instruction | Hex | Decimal |
1 | Function Set: 8-bit, 1 Line, 5x7 Dots | 0x30 | 48 |
2 | Function Set: 8-bit, 2 Line, 5x7 Dots | 0x38 | 56 |
3 | Function Set: 4-bit, 1 Line, 5x7 Dots | 0x20 | 32 |
4 | Function Set: 4-bit, 2 Line, 5x7 Dots | 0x28 | 40 |
5 | Entry Mode | 0x06 | 6 |
6 | Display off Cursor off | 0x08 | 8 |
7 | Display on Cursor on | 0x0E | 14 |
8 | Display on Cursor off | 0x0C | 12 |
9 | Display on Cursor blinking | 0x0F | 15 |
10 | Shift entire display left | 0x18 | 24 |
12 | Shift entire display right | 0x1C | 30 |
13 | Move cursor left by one character | 0x10 | 16 |
14 | Move cursor right by one character | 0x14 | 20 |
15 | Clear Display (also clear DDRAM content) | 0x01 | 1 |
16 | Set DDRAM address or cursor position on display | 0x80+add | 128+add |
17 | Set CGRAM address or set pointer to CGRAM location | 0x40+add | 64+add |
Programming Steps Sequence:
1) Initialize the LCD.
2) Select the command or instruction register (RS=0 or RS=1).
3) Set RW low (to write to LCD).
4) Send a high to low pulse on EN pin.
5) Check if the LCD is busy (Optional Step, it eliminates the delay issue).
6) Move to instruction or command function.
7) Repeat above steps.
The Source Code:
/*Every relevant command is included with a detailed and explanatory comment, if you still encounter any problem in the code feel free to post your queries*/
/* Platform: WINAVR*/
/*This code simply prints RoboZeal on LCD*/
#define F_CPU 12000000 //Change the F_CPU value to that you're using in your hardware, I used 12Mhz
#include <avr/io.h>
#include <util/delay. h>
#define dataport PORTA
#define commport PORTD
#define rs PD4
#define wr PD5
#define en PD6
int LCD_init(void);
int LCD_SendData(void);
int wrcomm(void);
int wrdata(void);
int main(void)
{
DDRA = 0xFF; //Set PortA as output port
DDRD = 0x70 //Set PortD 4, 5, 6 pin as output pins
LCD_init(); //Initialise LCD
LCD_SendData( ); //Write to LCD
return 1;
}
int LCD_init()
{
dataport = 0x38; //initialize LCD 2 lines, 5x7 matrix
wrcomm(); //Right the command byte to command register
dataport = 0x01; //Clear LCD
wrcomm(); //Right the command byte to command register
dataport = 0x0E; //Display on Cursor Blinking
wrcomm(); //Right the command byte to command register
dataport = 0x80; //Cursor at line 1, position 1
wrcomm(); //Right the command byte to command register
dataport = 0x1C; //Shift Entire Display To Right
wrcomm(); //Right the command byte to command register
return 1;
}
/*********** **** <<Sending Data To LCD Display>> ************ ***/
int LCD_SendData(void)
{
unsigned char j[] = "RoboZeal";
int i;
for(i = 0; i < sizeof j; i++)
{
dataport = j[i];
wrdata();
}
return 1;
}
/******* <<Righting the command byte to command register>> ********/
int wrcomm(void)
{
commport &= ~(1 << rs); //Setting RS = 0, selecting command register
commport &= ~(1 << wr); //Setting RW = 0
commport |= (1 << en); //EN = 1
commport &= ~(1 << en); //EN = 0, thus giving high to low pulse on Enable pin
_delay_ms(10); //10ms delay
return 1;
}
/********** <<Righting the Data byte to Data register>> **********/
int wrdata(void)
{
commport |= (1 << rs); //Setting RS = 1, selecting data register
commport &= ~(1 << wr); //Setting RW = 0
commport |= (1 << en); //EN = 1
commport &= ~(1 << en); //EN = 0, thus giving high to low pulse on Enable pin
_delay_ms(10) ; //10ms delay
return 1;
}
NOTE:
- Only one command that is “Get LCD status” is a read command all others are write command.
- The LCD interprets and executes our command at the instant the EN line is brought low. If you never bring EN low, your instruction will never be executed. Additionally, when you bring EN low and the LCD executes your instruction, it requires a certain amount of time to execute the command. The time it requires to execute an instruction depends on the instruction and the speed of the crystal which is attached to the 44780's oscillator input. (So watch the delay function in the code).
For Compiling & Burning the Program refer to: WinAVR for Parallel Port Programmer
For Building simple Parallel Port Programmer refer to: Programmer For Atmega 16/32
Regards:
Aditya Sharma