Difference between revisions of "LPC1768: Lcd 4bit"
Line 80: | Line 80: | ||
=Port Connection= | =Port Connection= | ||
− | This section shows how to configure the GPIO for interfacing the LCD.< | + | This section shows how to configure the GPIO for interfacing the LCD.<br> |
− | The below configuration is as per the above schematic. You | + | The below configuration is as per the above schematic. You can connect the LCD to any of the PORT pins available on your boards and update this section accordingly |
<syntaxhighlight> | <syntaxhighlight> |
Revision as of 19:48, 18 May 2015
Contents
Objective
In this tutorial we are going to see how to interface a 2x16 LCD with LPC1768 in 4-bit mode. As per the name the 2x16 has 2 lines with 16 chars on each lines. It supports all the ascii chars and is basically used for displaying the alpha numeric characters. Here each character is displayed in a matrix of 5x7 pixels. Apart from alpha numeric chars it also provides the provision to display the custom characters by creating the pattern. Scope of this tutorial is to show how to display the alpha numeric chars on LCD, Generating and displaying the custom chars will be discussed in subsequent tutorials.
LCD UNIT
All the pins are identically to the lcd internal controller discussed above
PIN NUMBER | FUNCTION |
---|---|
1 | Ground |
2 | VCC |
3 | Contrast adjustment (VO) |
4 | Register Select (RS). RS=0: Command, RS=1: Data |
5 | Read/Write (R/W). R/W=0: Write, R/W=1: Read |
6 | Clock (Enable). Falling edge triggered |
7 | Bit 0 (Not used in 4-bit operation) |
8 | Bit 1 (Not used in 4-bit operation) |
9 | Bit 2 (Not used in 4-bit operation) |
10 | Bit 3 (Not used in 4-bit operation) |
11 | Bit 4 |
12 | Bit 5 |
13 | Bit 6 |
14 | Bit 7 |
15 | Back-light Anode(+) |
16 | Back-Light Cathode(-) |
Apart from the voltage supply connections the important pins from the programming perspective are the data lines(8-bit Data bus), Register select, Read/Write and Enable pin.
Data Bus: As shown in the above figure and table, an alpha numeric lcd has a 8-bit data bus referenced as D0-D7.
As it is a 8-bit data bus, we can send the data/cmd to LCD in bytes. It also provides the provision to send the the data/cmd in chunks of 4-bit, which is used when there are limited number of GPIO lines on the microcontroller.
Register Select(RS): The LCD has two register namely a Data register and Command register. Any data that needs to be displayed on the LCD has to be written to the data register of LCD. Command can be issued to LCD by writing it to Command register of LCD.
This signal is used to differentiate the data/cmd received by the LCD.
If the RS signal is LOW then the LCD interprets the 8-bit info as Command and writes it Command register and performs the action as per the command.
If the RS signal is HIGH then the LCD interprets the 8-bit info as data and copies it to data register. After that the LCD decodes the data for generating the 5x7 pattern and finally displays on the LCD.
Read/Write(RW): This signal is used to write the data/cmd to LCD and reads the busy flag of LCD.
For write operation the RW should be LOW and for read operation the R/W should be HIGH.
Enable(EN): This pin is used to send the enable trigger to LCD.
After sending the data/cmd, Selecting the data/cmd register, Selecting the Write operation. A HIGH-to-LOW pulse has to be send on this enable pin which will latch the info into the LCD register and triggers the LCD to act accordingly.
Schematic
Port Connection
This section shows how to configure the GPIO for interfacing the LCD.
The below configuration is as per the above schematic. You can connect the LCD to any of the PORT pins available on your boards and update this section accordingly
/* Configure the data bus and Control bus as per the hardware connection */ #define LcdDataBusPort LPC_GPIO1->FIOPIN #define LcdControlBusPort LPC_GPIO2->FIOPIN #define LcdDataBusDirnReg LPC_GPIO1->FIODIR #define LcdCtrlBusDirnReg LPC_GPIO2->FIODIR #define LCD_D4 24 #define LCD_D5 25 #define LCD_D6 26 #define LCD_D7 27 #define LCD_RS 0 #define LCD_RW 1 #define LCD_EN 2
Example1
In this program we are going to do both INPUT and OUTPUT operation. The port pin to which switch is connected is configured as Input and the pin to which LED is connected is configured as OUTPUT. Here the switch status is read and accordingly the LED will be turned ON/OFF.
#include <lpc17xx.h> #define SwitchPinNumber 11 #define LedPinNumber 0 /* start the main program */ void main() { uint32_t switchStatus; SystemInit(); //Clock and PLL configuration LPC_GPIO2->FIODIR = ((1<<LedPinNumber) | (0<<SwitchPinNumber)); //Configure the PORT pins as OUTPUT; while(1) { /* Turn On all the leds and wait for one second */ switchStatus = (LPC_GPIO2->FIOPIN>>SwitchPinNumber) & 0x01 ; // Make all the Port pins as high if(switchStatus == 1) { LPC_GPIO2->FIOPIN = (1<<LedPinNumber); } else { LPC_GPIO2->FIOPIN = (0<<LedPinNumber); } } }
Example2
This is the alternate method using the stdutils macros.
#include <lpc17xx.h> #include "delay.h" //User defined library which contains the delay routines #include "stdutils.h" #define SwitchPinNumber 11 #define LedPinNumber 0 /* start the main program */ void main() { uint32_t switchStatus; SystemInit(); //Clock and PLL configuration LPC_GPIO2->FIODIR = ((1<<LedPinNumber) | (0<<SwitchPinNumber)); //Configure the PORT pins as OUTPUT; while(1) { /* Turn On all the leds and wait for one second */ switchStatus = util_GetBitStatus(LPC_GPIO2->FIOPIN,SwitchPinNumber); // Make all the Port pins as high if(switchStatus == 1) { util_BitSet(LPC_GPIO2->FIOPIN,LedPinNumber); } else { util_BitClear(LPC_GPIO2->FIOPIN,LedPinNumber); } } }
Video Tutorial
Introduction:LCD
Liquid Crystal Display(LCDs) provide a cost effective way to put a text output unit for a microcontroller. As we have seen in the previous tutorial, LEDs or 7 Segments do no have the flexibility to display informative messages. This display has 2 lines and can display 16 characters on each line. Nonetheless, when it is interfaced with the micrcontroller, we can scroll the messages with software to display information which is more than 16 characters in length.
LCD Internal Controller
The LCD is a simple device to use but the internal details are complex. Most of the 16x2 LCDs use a Hitachi HD44780 or a compatible controller. Yes, a micrcontroller is present inside a Liquid crystal display as shown in figure 1.
The Display Controller takes commands and data from a external microcontroller and drivers the LCD panel(LCDP). It takes a ASCII value as input and generate a patter for the dot matrix. E.g., to display letter 'A', it takes its value 0X42(hex) or 66(dec) decodes it into a dot matrix of 5x7 as shown in figure 2.
Basic Commands
The LCD controller uses RS and RW lines along with E to operate the LCD.
- Resister Select (RS): Determines weather a command(RS = 0) is sent (to set up the display) or actual data(RS=1) is sent.
- Read/Write RW=0; writes to the LCD. RW=1;Reads from the LCD.
The commonly used instructions are shown in the instruction set below. Observe the Bit names: I/D, S, D, C etc at the bottom of instruction set to decode the instructions completely.
- Clear Display
- Cursor Home
- Set Entry Mode
- Display on/off control
- Cursor/display shift
- Function Set
- Read Busy Flag
- Data Read
- Data Write
Instruction Set
Instruction | Code | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
RS | R/W | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | |||
Clear display | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | Clears display and returns cursor to the home position (address 0). | |
Cursor home | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * | Returns cursor to home position. Also returns display being shifted to the original position. DDRAM content remains unchanged.
| |
Entry mode set | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | Sets cursor move direction (I/D); specifies to shift the display (S). These operations are performed during data read/write.
| |
Display on/off control | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | Sets on/off of all display (D), cursor on/off (C), and blink of cursor position character (B).
| |
Cursor/display shift | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * | Sets cursor-move or display-shift (S/C), shift direction (R/L). DDRAM content remains unchanged.
| |
Function set | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * | Sets interface data length (DL), number of display line (N), and character font (F). | |
Read busy flag & address counter |
0 | 1 | BF | CGRAM/DDRAM address | Reads busy flag (BF) indicating internal operation being performed and reads CGRAM or DDRAM address counter contents (depending on previous instruction). | |||||||
Write CGRAM or DDRAM |
1 | 0 | Write Data | Write data to CGRAM or DDRAM. | ||||||||
Write CGRAM or DDRAM |
1 | 0 | Write Data | Write data to CGRAM or DDRAM. | ||||||||
Instruction bit names — I/D - 0 = decrement cursor position, 1 = increment cursor position; S - 0 = no display shift, 1 = display shift; |
Interfacing LCD with 8051
8 bit Mode
Objective
There is lot of stuff that can be done with the LCDs, to start with we will simple display a couple of strings on the 2 lines of the LCD as shown in the image.
Schematic Discription
- Data Lines: In this mode, all of the 8 datalines DB0 to DB7 are connected from the micrcontroller to a LCD module as shown the schematic.
- Control Lines:' The RS, RW and E are control lines, as discussed earlier.
- Power & contrast:Apart from that the LCD should be powered with 5V between PIN 2(VCC) and PIN 1(gnd). PIN 3 is the contrast pin and is output of center terminal of potentiometer(voltage divider) which varies voltage between 0 to 5v to vary the contrast.
- Back-light: The PIN 15 and 16 are used as backlight. The led backlight can be powered through a simple current limiting resistor as we do with normal leds.
Schematic
Code
As with all the interfaces to simplify thing we have separated code into two files, main.c and lcd_8_bit.c. You may go through the tools setup tutorial on configuring the code.
The main.c is very simple it includes the standard library files. Then it uses several functions from the lcd_8_bit.c file to set up and display messages. As you can see, it makes things very simple when the libraries are well written. We will discuss the implementation while discussing the lcd_8_bit.c file.
The main file main.c
/* Reg51.h contains the defnition of all ports and SFRs */ #include <reg51.h> #include "lcd.h" //Xplore labz LCD library #include "delay.h" //Xplore Labz Delay library /* start the main program */ void main() { /* Initilize the lcd before displaying any thing on the lcd */ LCD_Init(); /* Display "hello, world" on first line*/ LCD_DisplayString("hello, world"); /*Go to second line and display "good morning" */ LCD_GoToLineTwo(); LCD_DisplayString("good morning"); while(1); }
lcd_8_bit.c: 8 bit lcd library file
#define databus P2 // LCD databus connected to PORT2 sbit rs= P0^0; // Register select pin connected to P0.0 sbit rw= P0^1; // Read Write pin connected to P0.1 sbit en= P0^2; // Enable pin connected to P0.2
Let us look at three important functons in lcd_8_bit.c
1. void LCD_CmdWrite( char cmd)
Commands are required to sent to lcd in order to set it up or initialize.
The timing diagrams for command write are shown in the figure,
- step1: Send the I/P command to LCD.
- step2: Select the Control Register by making RS low.
- step3: Select Write operation making RW low.
- step4: Send a High-to-Low pulse on Enable PIN with some delay_us.
void LCD_CmdWrite( char cmd) { databus=cmd; // Send the command to LCD rs=0; // Select the Command Register by pulling RS LOW rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(10); en=0; delay_ms(1); }
2. void LCD_DataWrite( char dat) This function sends a character to be displayed on LCD in the following steps.
- step1: Send the character to LCD.
- step2: Select the Data Register by making RS high.
- step3: Select Write operation making RW low.
- step4: Send a High-to-Low pulse on Enable PIN with some delay_us.
The timings are similar as above only change is that RS is made high.
void LCD_DataWrite( char dat) { databus=dat; // Send the data to LCD rs=1; // Select the Data Register by pulling RS HIGH rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(10); en=0; delay_ms(1); }
3. void LCD_Init()
Looking at the instruction set of the LCD controller, we can initialize the LCD with following steps
- Set the display mode as 2 lines, 5 x 7 matrix
- Turn On the dislay, and cursor.
- Clear the LCD
- Get the cursor to first line first position.
The code is listed below.
void LCD_Init() { delay_us(5000); LCD_CmdWrite(0x38); // LCD 2lines, 5*7 matrix LCD_CmdWrite(0x0E); // Display ON cursor ON Blinking off LCD_CmdWrite(0x01); // Clear the LCD LCD_CmdWrite(0x80); // Cursor to First line First Position }
The remaining code is listed below. You could observe that the basic functions to read data and write write command are used extensively and entire library is built upon them. There are also other functions that are used to display number etc in the lcd library file. The entire listing can be found here.
#include<reg51.h> #include "delay.h" #include "lcd.h" #define databus P2 // LCD databus connected to PORT2 sbit rs= P0^0; // Register select pin connected to P0.0 sbit rw= P0^1; // Read Write pin connected to P0.1 sbit en= P0^2; // Enable pin connected to P0.2 /* 16x2 LCD Specification */ #define LCDMaxLines 2 #define LCDMaxChars 16 #define LineOne 0x80 #define LineTwo 0xc0 #define BlankSpace ' ' void LCD_Init() { delay_us(5000); LCD_CmdWrite(0x38); // LCD 2lines, 5*7 matrix LCD_CmdWrite(0x0E); // Display ON cursor ON Blinking off LCD_CmdWrite(0x01); // Clear the LCD LCD_CmdWrite(0x80); // Cursor to First line First Position } void LCD_CmdWrite( char cmd) { databus=cmd; // Send the command to LCD rs=0; // Select Command Register by pulling RS LOW rw=0; // Select Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(10); en=0; delay_ms(1); } void LCD_DataWrite( char dat) { databus=dat; // Send the data to LCD rs=1; // Select the Data Register by pulling RS HIGH rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(10); en=0; delay_ms(1); } void LCD_GoToXY(char row, char col) { char pos; if(row<LCDMaxLines) { pos= LineOne | (row << 6); // take the line number //row0->pos=0x80 row1->pos=0xc0 if(col<LCDMaxChars) pos= pos+col; //take the char number //now pos points to XY pos LCD_CmdWrite(pos) } } void LCD_DisplayString(char *string_ptr) { while(*string_ptr) LCD_DataWrite(*string_ptr++); } |
4 bit Mode
Schematic
There are following differences in 4 bit mode.
- Only data lines D4 to D7 are used as shown in the schematic below.
- In code, we need to send the command to select 4 bit mode as shown in the instruction set above.
The main program remains exactly as in 8 bit mode, we simply include the lcd_4_bit.c to work in 4 bit mode. The important and required code is listed below, you find other useful functions and entire library here
Code
#include<reg51.h> #include "delay.h" #include "lcd.h" #define databus P0 //LCD databus connected to PORT0 sbit rs= databus^0; // Register select pin connected to P0.0 sbit rw= databus^1; // Read Write pin connected to P0.1 sbit en= databus^2; // Enable pin connected to P0.2 /* 16x2 LCD Specification */ #define LCDMaxLines 2 #define LCDMaxChars 16 #define LineOne 0x80 #define LineTwo 0xc0 #define BlankSpace ' ' void LCD_Init() { delay_us(5000); LCD_CmdWrite(0x02); //Initilize the LCD in 4bit Mode LCD_CmdWrite(0x28); LCD_CmdWrite(0x0E); // Display ON cursor ON LCD_CmdWrite(0x01); // Clear the LCD LCD_CmdWrite(0x80); // Cursor to First line First Position } void LCD_CmdWrite( char cmd) { databus=(cmd & 0xf0); // Send the Higher Nibble rs=0; // Select the Command Register by pulling RS LOW rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(1); en=0; delay_us(10); // wait for some time databus=((cmd<<4) & 0xf0); // Send the Lower Nibble rs=0; // Select the Command Register by pulling RS LOW rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(1); en=0; delay_ms(1); } void LCD_DataWrite( char dat) { databus=(dat & 0xf0); // Send the Higher Nibble rs=1; // Select the Data Register by pulling RS HIGH rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(1); en=0; delay_us(10); // wait for some time. databus=((dat <<4) & 0xf0); // Send the Lower Nibble rs=1; // Select the Data Register by pulling RS HIGH rw=0; // Select the Write Operation by pulling RW LOW en=1; // Send a High-to-Low Pusle at Enable Pin delay_us(1); en=0; delay_ms(1); } void LCD_DisplayString(char *string_ptr) { while(*string_ptr) LCD_DataWrite(*string_ptr++); } void LCD_GoToLineTwo() { LCD_CmdWrite(LineTwo); // Move the Cursor to Second line } |
Downloads
{{#widget:Facebook_Like_Box|profile=https://www.facebook.com/ExploreEmbedded}}
Have a opinion, suggestion , question or feedback about the article let it out here!