(Created page with "category: LPC1768 Tutorials =Objective= This is first example on LPC1768 where we start with blinking the LEDs. In this tutorials we are going to discuss how to configur...")
 
Line 164: Line 164:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
=Video Tutorial=
 +
{{Box|type=l_green_light|text=<br />
 +
{{#ev:youtube|YDJISiPUdA8|600}}
 +
{{#ev:youtube|xG7uu98qz_A|200}}
 +
{{#ev:youtube|jRA4gefNVhM|200}}
 +
{{#ev:youtube|g-3Vt7SyL9w|200}}
 +
=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==
 +
[[File:HD44780U Block diagram.png|570x250px|framed|Fig 1: LCD Block diagram]]<br />
 +
 +
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.
 +
[[File:LCD Char 5x7 Matrix.jpg|thumbnail]]
 +
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<br />
 +
 +
}}
 +
==Instruction Set==
 +
{|class="wikitable" border="1" cellpadding="10" cellspacing="0" align="center"
 +
 +
|+ '''HD44780U based instruction set'''
 +
 +
|-
 +
 +
! style="background: #efefef;" rowspan="2" | Instruction
 +
 +
! style="background: #efefef;" colspan="10" | Code
 +
 +
! style="background: #efefef;" rowspan="2" | Description
 +
 +
|-
 +
 +
! style="background: #efefef; border-right: 0px;" | RS
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | R/W
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 1px dashed;" | B7
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B6
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B5
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B4
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B3
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B2
 +
 +
! style="background: #efefef; border-right: 0px; border-left: 0px;" | B1
 +
 +
! style="background: #efefef; border-left: 0px;" | B0
 +
 +
|-
 +
 +
| Clear display
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-left: 0px;"| 1
 +
 +
|| Clears display and returns cursor to the home position (address 0).
 +
 +
|-
 +
 +
|| Cursor home
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-left: 0px;"| *
 +
 +
|| Returns cursor to home position. Also returns display being shifted to the original position. DDRAM content remains unchanged.
 +
 +
 +
|-
 +
 +
|| Entry mode set
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| I/D
 +
 +
|align="center" style="border-left: 0px;"| 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
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| D
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| C
 +
 +
|align="center" style="border-left: 0px;"| B
 +
 +
|| Sets on/off of all display (D), cursor on/off (C), and blink of cursor position character (B).
 +
 +
 +
|-
 +
 +
|| Cursor/display shift
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| S/C
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| R/L
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| *
 +
 +
|align="center" style="border-left: 0px;"| *
 +
 +
|| Sets cursor-move or display-shift (S/C), shift direction (R/L). DDRAM content remains unchanged.
 +
 +
 +
|-
 +
 +
|| Function set
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| DL
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| N
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| F
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| *
 +
 +
|align="center" style="border-left: 0px;"| *
 +
 +
|| Sets interface data length (DL), number of display line (N), and character font (F).
 +
 +
|-
 +
 +
|| Read busy flag &<br> address counter
 +
 +
|align="center" style="border-right: 0px;"| 0
 +
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 1
 +
 +
|align="center" style="border-right: 0px; border-left: 1px dashed;"| BF
 +
 +
|align="center" style="border-left: 0px;" colspan="7"| 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<br> DDRAM
 +
|align="center" style="border-right: 0px;"| 1
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
|align="center" style="border-left: 1px dashed;" colspan="8"| Write Data
 +
|| Write data to CGRAM or DDRAM.
 +
|-
 +
|| Write CGRAM or<br> DDRAM
 +
|align="center" style="border-right: 0px;"| 1
 +
|align="center" style="border-right: 0px; border-left: 0px;"| 0
 +
|align="center" style="border-left: 1px dashed;" colspan="8"| Write Data
 +
|| Write data to CGRAM or DDRAM.
 +
|-
 +
|colspan="13" style="font-size: 90%;"| '''Instruction bit names —'''<br>
 +
'''I/D''' - 0 = decrement cursor position, 1 = increment cursor position;<br/>
 +
 +
'''S''' - 0 = no display shift, 1 = display shift;<br/>
 +
'''D''' - 0 = display off, 1 = display on;<br/>
 +
'''C''' - 0 = cursor off, 1 = cursor on;<br/>
 +
'''B''' - 0 = cursor blink off, 1 = cursor blink on ;<br/>
 +
'''S/C''' - 0 = move cursor, 1 = shift display;<br/>
 +
'''R/L''' - 0 = shift left, 1 = shift right;<br/>
 +
'''DL''' - 0 = 4-bit interface, 1 = 8-bit interface;<br/>
 +
'''N''' - 0 = 1/8 or 1/11 duty (1 line), 1 = 1/16 duty (2 lines);<br/>
 +
'''F''' - 0 = 5×8 dots, 1 = 5×10 dots;<br/>
 +
'''BF''' - 0 = can accept instruction, 1 = internal operation in progress.<br/>
 +
|}
 +
 +
=LCD UNIT=
 +
{{Box|type=l_green_light|text=
 +
 +
Let us look at a pin diagram of a commercially available LCD like '''JHD162''' which uses a '''HD44780''' controller and then describe its operation.
 +
 +
[[File:PIN_Diagram.PNG]]
 +
 +
All the pins are identically to the lcd internal controller discussed above
 +
 +
}}
 +
 +
{|class="wikitable "
 +
|-
 +
! 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(-)
 +
|}
 +
<br/>
 +
<br/>
 +
<br/>
 +
<br/>
 +
 +
=Interfacing LCD with 8051=
 +
{{Box|type=l_green_light|text=
 +
LCD can be interfaced with the 8051 micrcontroller in two modes, 8 bit and 4 bit.
 +
Let us Interface it in 8 bit mode first.
 +
}}
 +
==8 bit Mode==
 +
{{Box|type=l_green_light|text=<br />
 +
===Objective===
 +
[[File:LCD_output.PNG|thumbnail|fig LCD display ]]
 +
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===
 +
[[File:8051 LCD8BIT Interface.PNG|Fig 3: Schematic LCD 8 bit mode]]
 +
 +
 +
{{Box|type=l_green_light|text=<br />
 +
===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 [[8051 ToolsSetup|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====
 +
<syntaxhighlight>
 +
/* 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);
 +
}
 +
</syntaxhighlight>
 +
 +
====lcd_8_bit.c: 8 bit lcd library file====
 +
{{Box|type=l_green_light|text=
 +
The '''lcd_8_bit.c''' consists of various functions that are required to initialize and use the LCD. Let us look at few important lines and functions.
 +
'''Specifying the Connections''': The connections described in the schematic are specified with following lines of code.
 +
<syntaxhighlight>
 +
#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
 +
</syntaxhighlight>
 +
 +
Let us look at three important functons  in ''' lcd_8_bit.c'''<br />
 +
1. '''void LCD_CmdWrite( char cmd)'''<br />
 +
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,
 +
[[File:LCD CmdWrite.jpg|figure: command write]]<br />
 +
*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.
 +
<syntaxhighlight>
 +
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);
 +
}
 +
</syntaxhighlight>
 +
 +
'''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.
 +
<syntaxhighlight>
 +
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);
 +
}
 +
</syntaxhighlight>
 +
 +
'''3. void LCD_Init()'''<br />
 +
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.
 +
 +
<syntaxhighlight>
 +
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
 +
}
 +
</syntaxhighlight>
 +
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 [[8051_Family_C_Library#LCD_16x2_8_bit_mode|here]].
 +
}}
 +
 +
{{scroll box|width=700px|height=500px|text=<br />
 +
<syntaxhighlight>
 +
#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++);
 +
}
 +
</syntaxhighlight>
 +
}}
 +
 +
==4 bit Mode==
 +
{{Box|type=l_green_light|text=<br />
 +
===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.
 +
[[File:8051 LCD4BIT Interface.PNG|Fig 4: Schematic LCD 4 bit mode]]
 +
 +
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
 +
[[8051_Family_C_Library#LCD_4_bit_mod|here]]
 +
}}
 +
===Code===
 +
{{scroll box|width=700px|height=500px|text=<br />
 +
<syntaxhighlight>
 +
#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
 +
}
 +
</syntaxhighlight>
 +
}}
 +
= Downloads=
 +
{{Box|type=l_green_light|text="The code is given for 4 and 8 bit modes with and without busy Flag"}}
 +
[http://exploreembedded.com/wiki/images/0/02/8051_LCD_Tutorial_Code.zip '''Code''']
 +
 +
 +
[[File:SwitchesLEDs.jpg|left|thumbnail|x120px|{{Box|type=l_blue_light|text=Switches and LED Interfacing with 8051 }}|link=8051_Interfacing_swithes_leds|'''''PREVIOUS TUTORIAL''''']]
 +
[[File:8051_Timers_Poster.jpg|right|thumbnail|x150px|link=8051_timers|'''''NEXT TUTORIAL''''']]
 +
 +
{{#widget:Facebook_Like_Box|profile=https://www.facebook.com/ExploreEmbedded}}
 +
 +
Have a opinion, suggestion , question or feedback about the article let it out here!
 +
{{DISQUS}}

Revision as of 13:31, 17 May 2015


Objective

This is first example on LPC1768 where we start with blinking the LEDs. In this tutorials we are going to discuss how to configure the LPC1768 ports for GPIO and then to use to send a low/high signal on it. Lets start blinking with LEDs and then generate the different patterns using the available LEDs.

Register Configuration

As all the LPC1768 SFRs(Special Function Registers) are defined in lpc17xx.h, this has to be included at the beginning of our project/code.

LPC1768 has its GPIOs divided into five ports PORT0 - PORT4, although many of them are not physically 32bit wide. Refer the data sheet for more info. The Below registers will be used for Configuring and using the GPIOs registers for sending and receiving the Digital signals. A structure LPC_GPIOn(n= 0,1,2,3) contains all the registers for required for GPIO operation. Refer lpc17xx.h file for more info on the registers.


PINSEL: GPIO Pins Select Register Every GPIO pin has a minimum of one function and max of four functions. The required function can be selected by configuring the PINSEL register. As there can be up to 4 functions associated with a GPIO pin, two bits for each pin are available to select the function. This concludes that we need two PINSEL registers to configure a PORT pins. By this the first 16(P0.0-P0.16) pin functions of PORT0 and be selected by 32 bits of PINSELO register. The remaining 16 bits(P0.16-P0.32) are configured using 32bits of PINSEL1 register. As mentioned earlier every pin has max of four functions. Below table shows how to select the function for a particular pin using two bits of the PINSEL register.

Value Function
00 Primary (default) function, typically GPIO port
01 First alternate function
10 Second alternate function
11 Third alternate function


FIODIR:Fast GPIO Direction Control Register.
This register individually controls the direction of each port pin.

Values Direction
0 Input
1 Output


FIOSET:Fast Port Output Set Register.
This register controls the state of output pins. Writing 1s produces highs at the corresponding port pins. Writing 0s has no effect. Reading this register returns the current contents of the port output register not the physical port value.

Values FIOSET FIOCLR
0 No Effect No Effect
1 Sets High on Pin Sets Low on Pin


FIOCLR:Fast Port Output Clear Register.
This register controls the state of output pins. Writing 1s produces lows at the corresponding port pins. Writing 0s has no effect.

Values FIOCLR
0 No Effect
1 Sets Low on Pin


FIOCLR:Fast Port Output Clear Register.
This register controls the state of output pins. Writing 1s produces lows at the corresponding port pins. Writing 0s has no effect.

Values FIOCLR
0 No Effect
1 Sets Low on Pin


FIOPIN:Fast Port Pin Value Register.
This register is used for both reading and writing data from/to the PORT.
Output: Writing to this register places corresponding values in all bits of the particular PORT pins.
Input: The current state of digital port pins can be read from this register, regardless of pin direction or alternate function selection (as long as pins are not configured as an input to ADC).
Note:Although it is recommended to configure the PORT direction and pin function before using it.

Values FIOPIN
0 Sets Low on Pin
1 Sets High on Pin

Schematic

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

Fig 1: LCD Block diagram

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.

LCD Char 5x7 Matrix.jpg

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

HD44780U based 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;
D - 0 = display off, 1 = display on;
C - 0 = cursor off, 1 = cursor on;
B - 0 = cursor blink off, 1 = cursor blink on ;
S/C - 0 = move cursor, 1 = shift display;
R/L - 0 = shift left, 1 = shift right;
DL - 0 = 4-bit interface, 1 = 8-bit interface;
N - 0 = 1/8 or 1/11 duty (1 line), 1 = 1/16 duty (2 lines);
F - 0 = 5×8 dots, 1 = 5×10 dots;
BF - 0 = can accept instruction, 1 = internal operation in progress.

LCD UNIT

Let us look at a pin diagram of a commercially available LCD like JHD162 which uses a HD44780 controller and then describe its operation.

PIN Diagram.PNG

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(-)





Interfacing LCD with 8051

LCD can be interfaced with the 8051 micrcontroller in two modes, 8 bit and 4 bit. Let us Interface it in 8 bit mode first.

8 bit Mode


Objective

fig LCD display

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

Fig 3: Schematic LCD 8 bit mode



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

The lcd_8_bit.c consists of various functions that are required to initialize and use the LCD. Let us look at few important lines and functions. Specifying the Connections: The connections described in the schematic are specified with following lines of code.

#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, figure: command write

  • 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.

Fig 4: Schematic LCD 4 bit mode

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

"The code is given for 4 and 8 bit modes with and without busy Flag"
Code


PREVIOUS TUTORIAL
NEXT TUTORIAL

{{#widget:Facebook_Like_Box|profile=https://www.facebook.com/ExploreEmbedded}}

Have a opinion, suggestion , question or feedback about the article let it out here!