In this article I'm using a PIC 16F628a to demonstrate one way of using a 4 line LCD.
The hardware
The following schematic is put on a breadboard:
Click here for a bigger view.
BOM - Bill of material
This is what you need.
Partlist
Exported from PIC16F628A-16x4-lcd-demo.sch at 08.11.17 20:56
EAGLE Version 7.2.0 Copyright (c) 1988-2014 CadSoft
Assembly variant:
Part Value Device Package Library Sheet
C1 0.1uF C-EU025-024X044 C025-024X044 rcl 1
C2 100uF CPOL-EUE2.5-5 E2,5-5 rcl 1
C3 0.1uF C-EU025-024X044 C025-024X044 rcl 1
C4 100uF CPOL-EUE2.5-5 E2,5-5 rcl 1
C5 18pF C-EU025-024X044 C025-024X044 rcl 1
C6 18pF C-EU025-024X044 C025-024X044 rcl 1
C7 0.1uF C-EUC0805K C0805K rcl 1
C8 0.1uF C-EUC0805K C0805K rcl 1
D1 1N4004 DIODE-SMB SMB diode 1
IC1 78L05Z 78L05Z TO92 linear 1
IC3 PIC16F628a DIL18S SOCKET-18 ic-package 1
JP1 ICSP PINHD-1X5/90 1X05/90 pinhead 1
JP5 2*16 LCD PINHD-1X16 1X16 pinhead 1
Q1 16MHz XTAL/S QS special 1
R1 10K R-EU_R0805 R0805 rcl 1
R2 10K TRIM_EU-CA6V CA6V pot 1
TP1 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
TP2 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
TP3 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
TP4 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
TP5 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
TP6 TPPAD1-13Y TPPAD1-13Y P1-13Y testpad 1
X1 12vDC W237-102 W237-102 con-wago-500 1
The Breadboard
This is how the breadboard look like:
The software
This is the code that's loaded into the PIC.
// INCLUDES
#include <xc.h>
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#pragma warning disable 359 // Disable warning 359 - illegal conv between pointer types
#pragma warning disable 373 // Disable warning 373 - signed to unsigned conversion
// DEFINITIONS
#define _XTAL_FREQ 16000000 // refenrence freq for the compiler
#define Rs PORTAbits.RA0 // Rs is connected to RA0
#define En PORTAbits.RA1 // En is connected to RA1
#define lcd_port TRISB // lcd port b
#define lcdLine1 0x00 // line one begins here
#define lcdLine2 0x40 // line two begins here
#define lcdLine3 0x90 // line three begins here
#define lcdLine4 0xd0 // line four begins here
// VARIABLES
// FUNCTION PROTOTYPE
void lcd_cmd(unsigned char cmd);
void lcd_data(unsigned char dat);
void lcd_init(void);
void lcd_line1(void);
void lcd_line2(void);
void lcd_setcursor(unsigned char loc);
int lcd_strobe(void);
void lcd_write(unsigned char dat);
void lcd_writestr(const unsigned char *c);
void show_welcome();
// FUNCTIONS
// function to pulse the En pin high
int lcd_strobe(void)
{
En = 1;
__delay_us(1);
En = 0;
}
// function to write to the lcd port
void lcd_write(unsigned char dat)
{
lcd_port &= 0x0f; // get current port and clear upper bits
lcd_port |= (dat & 0xf0); // combine upper and lower, leave lower
lcd_strobe();
lcd_port &= 0x0f;
lcd_port |= ((dat << 4) & (0xf0)); // combine upper and lower
lcd_strobe();
__delay_ms(2); // little delay for lcd to process
}
// function to set lcd in command mode
void lcd_cmd(unsigned char cmd)
{
Rs = 0; // rs low for cmd mode
lcd_write(cmd);
}
// functionto set lcd in data mode
void lcd_data (unsigned char dat)
{
Rs = 1; // rs high for data mode
lcd_write(dat);
}
// function to initialize the lcd
void lcd_init(void)
{
lcd_port &= 0x0f; // clear upper bits
lcd_port |= 0x30; // send data to d7-4
Rs = 0;
lcd_strobe();
__delay_ms(10);
lcd_strobe();;
__delay_ms(10);
lcd_strobe();
__delay_ms(10);
lcd_port &= 0x0f; // clear upper bits
lcd_port |= 0x30; // send data to d7-4
lcd_strobe();
__delay_ms(50);
lcd_cmd(0x28); // 4-bit, 2-line, 5x7 font
lcd_cmd(0x0e); // display on, cursor on, blink off
lcd_cmd(0x06); // auto increment, no shift
lcd_cmd(0x80); // address ddram with 0 offset 80h
}
// function to write a strng to the lcd
void lcd_writestr(const unsigned char *c)
{
while (*c != '\0')
{
lcd_data(*c);
c++;
}
}
// function to place the cursor on the lcd
void lcd_setcursor(unsigned char loc)
{
lcd_cmd(loc | 0x80);
}
// function to move cursor to 1st place on line 1
void lcd_line1(void)
{
lcd_setcursor(lcdLine1);
}
// function to move cursor to 1st place on line 2
void lcd_line2(void)
{
lcd_setcursor(lcdLine2);
}
// function to move cursor to 1st place on line 3
void lcd_line3(void)
{
lcd_setcursor(lcdLine3);
}
// function to move cursor to 1st place on line 4
void lcd_line4(void)
{
lcd_setcursor(lcdLine4);
}
// Function that shows a welcome message
void show_welcome()
{
lcd_writestr(" 16x4 LCD");
lcd_line2();
lcd_writestr(" PIC16F628a");
lcd_line3();
lcd_writestr("Line 3");
lcd_line4();
lcd_writestr("Line 4");
__delay_ms(2000);
}
/* THIS IS THE MAIN PROGRAM LOOP */
void main(void)
{
CMCON = 0x07; // Turn comparators off
TRISA = 0b00000000; // All output
TRISB = 0b00000000; // All output
PORTA = 0b00000000; // All low
PORTB = 0b00000000; // All low
lcd_strobe();
lcd_init();
show_welcome();
while (1)
{
// Nothing to do.
} // end while
} // end main