0% found this document useful (0 votes)
7 views26 pages

Mcapp Lab 10 (Student) LCD (Apr 25)

This document outlines Lab 10 for interfacing an LCD module using a microcontroller, detailing objectives, required equipment, and software. It provides a comprehensive guide on connecting the LCD, controlling it through various pins, and executing functions to display data. Additionally, it includes exercises for practical application, such as displaying text and a running clock on the LCD.

Uploaded by

Fan Hong
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views26 pages

Mcapp Lab 10 (Student) LCD (Apr 25)

This document outlines Lab 10 for interfacing an LCD module using a microcontroller, detailing objectives, required equipment, and software. It provides a comprehensive guide on connecting the LCD, controlling it through various pins, and executing functions to display data. Additionally, it includes exercises for practical application, such as displaying text and a running clock on the LCD.

Uploaded by

Fan Hong
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

Diploma in BME

Diploma in CEN
Diploma in ELN

Microcontroller Applications (EMC3006)

Name: Class:

Lab 10 – Interfacing the LCD Module (4-bit Mode)

Objectives:
1. To learn how to interface to the LCD module.
Equipment & Software:
1. Computer / notebook
2. Microchip MPLAB X IDE Version 6.00
3. Microchip XC8 Compiler Version 2.41
4. Target board with PICKit-4

Please go through this reading material before you come for the laboratory
session.

Introduction
Displays are vital components for embedded devices. It enables
the user to know the status of your application program. In this lab,
we shall learn how to use one of the commonly used LCD modules
in the market.

Reference: https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 1 of 26


Contents

1 LCD Module 3
1.1 Pin Layout and Connection 3
1.2 Controlling the LCD Module 4
1.2.1 Enable Line 4
1.2.2 Register Select Line 4
1.2.3 Sending Control Instructions and Display Data 5
1.2.4 Initialising the LCD 7
1.2.5 Display Data RAM Address (DD RAM) 8

2 Exercises 10
2.1 Exercise 1: Display Text on Both Rows 10

3 Lab Extra 15
3.1 Exercise 2: Display Running Clock on LCD 15
3.2 Exercise 3: Display External Interrupt Counts on LCD 20

Appendix – Control Instructions for LCD 26

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 2 of 26


1 LCD Module

1.1 Pin Layout and Connection


The LCD used on the target board is a commonly used device. It is also known as the
"1602" LCD. Shown below is its pin layout.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Ground

Data Pin 0
Data Pin 1
Data Pin 2
Data Pin 3
Data Pin 4
Data Pin 5
Data Pin 6
Data Pin 7
R/W

Backlight +
Contrast

Backlight -
+5V

RS

Figure 1-1: 1602 LCD

The LCD can be interfaced to a microcontroller via 4 or 8 data pins. For our purpose, in
order to save the number of I/Os used for interfacing, we shall use 4 data pins only.

Overall, the connections consist of the following pins:


• A 4-bit data bus, and
• A set of 3 control signal lines referred to as RS, E and R/W�.
o With R/W � tied to ground, the microcontroller can only write to the LCD.

PIC16F18877

RE0 E (Enable)

RE1 RS (Register Select)



R/W

RD4 DB4
RD5 DB5
RD6 DB6 LCD
RD7 DB7 16 characters by 2 lines
4-bit Data Bus

Hardware Connection to LCD on Lab’s Target Board

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 3 of 26


1.2 Controlling the LCD Module

1.2.1 Enable Line


To send data to the LCD, the microcontroller needs to:
1) Put the data on the 4-bit data bus, and,
2) Trigger a falling-edge pulse on the Enable line.

Falling edge
2 triggered

E (Enable)

RS (Register Select)

1
RD<7:4>
Data LCD
Data Lines

LCD is Falling-Edge Triggered

1.2.2 Register Select Line

The Register Select line is used by the LCD module to determine the type of data being
received on its data lines based on the following rule:

LCD module will interpret data received


If RS is:
at its data lines to be:
Logic ‘1’ Data to be displayed
Control instruction
Logic ‘0’
(Also known as control word)

Control instructions are commands such as:


• Clearing the LCD display
• Setting the LCD cursor position
• And others

The full list of control instructions is tabulated in the Appendix.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 4 of 26


Note:
As the microcontroller can only write data to the LCD module, RD<7:4> shall be
configured as digital output function.

Question:
RE0 and RE1 are used to control the Enable and Register Select lines respectively.
Hence, they should be configured as ___________________.
Tick the correct answer.
Digital Input
Digital Output

1.2.3 Sending Control Instructions and Display Data


Since we are using only 4 bits for the data bus, a typical 8-bit wide data needs to be
separated into 2 nibbles, the upper nibble (bit 4-7) and lower nibble (bit 0-3).

Sending ASCII ‘H’


(8 bit value = 0x48)
E (Enable)
0 1 0 0 1 0 0 0 RS (Register Select)

2 1
1 0 0 0 0 1 0 0 Data Lines
Lower nibble is Upper nibble is
LCD
sent next sent fist

• Each nibble is sent out with a falling-edge transition on the Enable line.
• The upper nibble is sent out first and followed by the lower nibble.

Definitions for Pins Used:


Only RD<7:4> pins are
used for LCD data.
#define LCD_DATA_D7 PORTDbits.RD7
#define LCD_DATA_D6 PORTDbits.RD6
#define LCD_DATA_D5 PORTDbits.RD5
#define LCD_DATA_D4 PORTDbits.RD4
#define LCD_RS PORTEbits.RE1 // RS pin for LCD
#define LCD_E PORTEbits.RE0 // E pin for LCD

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 5 of 26


Function to write a nibble:

The function to write a nibble, lcdWriteNibble() is shown below. It accepts an 8-bit


argument which represents the value of the 4 bit nibble (right-justified). After the 4 bits
are placed on RD(7:4), the Enable line is pulsed low to latch the data into the LCD data
pins.
void lcdWriteNibble(char nibble)
{
LCD_DATA_D7 = (nibble & 0b00001000) >> 3;
LCD_DATA_D6 = (nibble & 0b00000100) >> 2;
LCD_DATA_D5 = (nibble & 0b00000010) >> 1;
LCD_DATA_D4 = (nibble & 0b00000001);

LCD_E = 1;
__delay_ms(1); Falling Edge
LCD_E = 0;
__delay_ms(1);
}

Function to write a control instruction:

The function to send a control instruction, lcdWriteCtrlWord() is shown below. It


accepts an 8-bit argument which represents the value of the control word to be sent to
the LCD. In the function, the upper nibble and lower nibble are extracted using the bitwise
AND operator as well as shift operator.

void lcdWriteCtrlWord(char x)
{
char upper_nibble, lower_nibble;

upper_nibble = (x & 0b11110000) >> 4;


lower_nibble = x & 0b00001111;

LCD_RS = 0; RS=0 for writing control word


lcdWriteNibble(upper_nibble); // Write upper nibble
lcdWriteNibble(lower_nibble); // Write lower nibble
}

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 6 of 26


Function to write display data:

The function to write data byte to be displayed, lcdWriteDspData() is shown below. It


is similar to lcdWriteCtrlWord(), except that the RS line is set to logic 1.

void lcdWriteDspData(char x)
{
char upper_nibble, lower_nibble;

upper_nibble = (x & 0b11110000) >> 4;


lower_nibble = x & 0b00001111;

LCD_RS = 1; RS=1 for writing data to be displayed


lcdWriteNibble(upper_nibble); // Write upper nibble
lcdWriteNibble(lower_nibble); // Write lower nibble
}

1.2.4 Initialising the LCD

When the LCD is first powered up, we would need to initialise it through a few control
instructions including turning on the display, setting the cursor blink mode, bringing the
cursor to the home position, and others. The program segment below is the function to
initialise the LCD.

Sequence (a) to (d) is a special sequence, considering that when the LCD is first powered
up, it can either be in 4-bit mode or 8-bit mode. The algorithm in the special sequence
ensures that the LCD is in the correct 4-bit mode after the sequence (a) to (d) is
completed before sending the other control instructions to initialise it.

void initLCD()
{
// Special Sequence a) to d) required for 4-bit interface
__delay_ms(15); // a) 15ms LCD power-up delay
lcdWriteCtrlWord(0b00000011);// b) Function Set (DB4-DB7:8-bit interface)
__delay_ms(5); // c) 5ms delay
lcdWriteCtrlWord(0b00000010);// d) Function Set (DB4-DB7:4-bit interface)

lcdCtrl_FunctionSet(); // Function Set - 4-bit, 2 lines, 5x7


lcdCtrl_OnOffDisplay(1, 0); // Display on, cursor off
lcdCtrl_SetEntryMode(); // Entry mode - inc addr, no shift
lcdCtrl_ClearDisplay(); // Clear display & home position
}

There are a number of instructions that are being sent to the LCD, as you can see. As an
example, you can refer to the Appendix for the following instruction which serves to clear
the LCD display:

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 7 of 26


Making use of the instruction entry shown above, the function lcdCtrl_ClearDisplay() is
thus structured as:

void lcdCtrl_ClearDisplay(void) {
lcdWriteCtrlWord(0b00000001);
}

1.2.5 Display Data RAM Address (DD RAM)

The LCD module contains memory that is used for storing the text data to be displayed.
This memory can be represented by the following “memory map”.

Col 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
Line 1 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Line 2 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F Hex

Memory Map for 16 x 2 LCD Module

The numbers in the map represent the 7-bit DDRAM addresses for the LCD screen
positions (or cursor positions).
• For the first row, the address ranges from 0x00 to 0x0F.
• For the second row, the address ranges from 0x40 to 0x4F.

Set DDRAM Address

In the list of control instructions, the Set DDRAM Address instruction is used with the
memory map to set the desired cursor position.

The lower 7 bits A6 to A0 are determined from the memory map.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 8 of 26


Example:

What is the program statement to set the cursor position to line 2, column 8?

• Referring to the memory map, the memory address for line 2, column 8 is 0x47
(0b01000111).
• Taking the lower 7 bits (A6:A0) only, the complete 8-bit control instruction is
0b11000111, or 0xC7. Note that the most significant bit for the Set DD RAM Address
instruction is a 1.
• Hence, the program statement is:
lcdWriteCtrlWord(0b11000111);

Bit 7 is always 1 for Set DD Ram Address


control instruction.

Function to set the cursor position:

We can come up with a function to set the cursor position (lcdCtrl_SetPos()). Allowing it
to take in 2 arguments, row and column, it takes the form below.

// row values are 1 to 2:


// col values are 1 to 16:
void lcdCtrl_SetPos(unsigned char row, unsigned char col)
{
unsigned char ramAddr; // Ctrl instruction to be sent Why
subtract
if (row == 1) // If row is 1: 1?
ramAddr = col - 1; // Subtract 1 from the col
else // If row is 2:
ramAddr = 0x40 + col - 1; // Add 0x40 to ramAddr, and
Why // subtract 1 from the col
add with
0x40? lcdWriteCtrlWord(0x80 + ramAddr); // Add 0x80 to ramAddr and write
// ctrl instruction
}

Why add
with 0x80?

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 9 of 26


2 Exercises

2.1 Exercise 1: Display Text on Both Rows

Procedure

1. Create a new project named as Lab_LCD_Ex1.

2. Create the header file, config.h.


#pragma config FEXTOSC = XT // Crystal Oscillator
#pragma config WDTE = OFF // Disable watch dog timer
#pragma config LVP = OFF // Disable Low Voltage Programming

#define _XTAL_FREQ 4000000


config.h

3. The program design map for this project is:

Project

config.h
main.c lcd.c

Program Design Map

4. Create a new source file and name it as main.c.


• This source file contains the main() function, which will call initSysPins() and
initLCD() to configure the ports and to initialise the LCD respectively.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 10 of 26


#include <xc.h>
#include "config.h"

// Function Declarations:
// - Defined in this file:
void initSysPins(void);
Declare functions
// - Defined in other file(s): that are called in
void initLCD(void); this file
void lcdWriteDspData(char x);
void lcdCtrl_SetPos(char row, char col);

void main(void)
{ Two messages to
char message1[] = "Hello, World!"; be displayed
char message2[] = "I'm learning LCD";
unsigned int i;

initSysPins();
initLCD();

lcdCtrl_SetPos(1, 1); Set cursor and


for(i = 0; message1[i]!=0; i++) { display first message
lcdWriteDspData(message1[i]);
}

lcdCtrl_SetPos(2, 1);
for(i = 0; message2[i]!=0; i++) {
lcdWriteDspData(message2[i]);
}

PORTA = 0b00001010;

while(1) { Toggle the 4 LEDs to


PORTA ^= 0b00001111; indicate program is
__delay_ms(1000); running
}
}

void initSysPins(void)
{
ANSELA = 0b00000000;
ANSELD = 0b00000000; Why does ANSELE and
ANSELE = 0b00000000; TRISE needs to be
TRISA = 0b11110000;
configured?
TRISD = 0b00001111;
TRISE = 0b11111100;
}
main.c

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 11 of 26


Note:
The reason why the for-loop checks for message[i] in its test expression is because
any strings that are initialised are null terminated (ends with a zero).

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]
‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘,’ ‘W’ ‘o’ ‘r’ ‘l’ ‘d’ ‘!’ 0

That is, the program exits from the for-loop when it encounters a null in the
message[12] array element.

5. Download the lcd.c file from the LMS. Add it into the source file branch of this
project.

#include <xc.h>
#include "config.h"

#define LCD_DATA_D7 PORTDbits.RD7


#define LCD_DATA_D6 PORTDbits.RD6 Pins
#define LCD_DATA_D5 PORTDbits.RD5 used
#define LCD_DATA_D4 PORTDbits.RD4 for
#define LCD_RS PORTEbits.RE1 // RS pin LCD
#define LCD_E PORTEbits.RE0 // E pin

// Function Declarations:
// Defined in this file:
void lcdWriteCtrlWord(char x);
void lcdWriteDspData(char x);
void lcdWriteNibble(char nibble);
void lcdCtrl_SetPos(unsigned char row, unsigned char col);

void lcdCtrl_FunctionSet(void);
void lcdCtrl_OnOffDisplay(char display_state, char cursor_state);
void lcdCtrl_SetEntryMode(void);
void lcdCtrl_ClearDisplay(void); Steps (a) to (d): Special
Sequence
void initLCD()
{
// Special Sequence a) to d) required for 4-bit interface
__delay_ms(15); // a) 15ms LCD power-up delay
lcdWriteCtrlWord(0b00000011); // b) Function Set (DB4-DB7:8-bit interface)
__delay_ms(5); // c) 5ms delay
lcdWriteCtrlWord(0b00000010); // d) Function Set (DB4-DB7:4-bit interface)

lcdCtrl_FunctionSet(); // Function Set - 4-bit, 2 lines, 5x7


lcdCtrl_OnOffDisplay(1, 0); // Display on, cursor off
lcdCtrl_SetEntryMode(); // Entry mode - inc addr, no shift
lcdCtrl_ClearDisplay(); // Clear display & home position
}

lcd.c (Continue on next page)

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 12 of 26


void lcdWriteCtrlWord(char x) Function to write
{ control word
char upper_nibble, lower_nibble;

upper_nibble = (x & 0b11110000) >> 4;


lower_nibble = x & 0b00001111;

LCD_RS = 0;
lcdWriteNibble(upper_nibble); // Write upper nibble
lcdWriteNibble(lower_nibble); // Write lower nibble
}

void lcdWriteDspData(char x) Function to write


{ display data
char upper_nibble, lower_nibble;

upper_nibble = (x & 0b11110000) >> 4;


lower_nibble = x & 0b00001111;

LCD_RS = 1;
lcdWriteNibble(upper_nibble); // Write upper nibble
lcdWriteNibble(lower_nibble); // Write lower nibble
}
Function to write
void lcdWriteNibble(char nibble)
{ 4 bits (a nibble)
LCD_DATA_D7 = (nibble & 0b00001000) >> 3;
LCD_DATA_D6 = (nibble & 0b00000100) >> 2;
LCD_DATA_D5 = (nibble & 0b00000010) >> 1;
LCD_DATA_D4 = (nibble & 0b00000001);

LCD_E = 1;
__delay_ms(1);
LCD_E = 0;
__delay_ms(1);
}
Function to set
// row values are 1 to 2: cursor position
// col values are 1 to 16:
void lcdCtrl_SetPos(unsigned char row, unsigned char col)
{
unsigned char ramAddr; // Ctrl instruction to be sent

if (row == 1) // If row is 1:
ramAddr = col - 1; // Subtract 1 from the col
else // If row is 2:
ramAddr = 0x40 + col - 1; // Add 0x40 to ramAddr, and
// subtract 1 from the col

lcdWriteCtrlWord(0x80 + ramAddr); // Add 0x80 to ramAddr and write


// ctrl instruction
}
lcd.c (Continued from previous page)

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 13 of 26


void lcdCtrl_FunctionSet(void)
{
lcdWriteCtrlWord(0b00101000); // Function Set - 4-bit, 2 lines, 5x7
}

void lcdCtrl_OnOffDisplay(char display_state, char cursor_state)


{
char pattern = 0b00001000;

if(display_state == 1)
pattern |= 0b00000100; // Display on
if(cursor_state == 1)
pattern |= 0b00000011; // Cursor on and blinking

lcdWriteCtrlWord(pattern);
}

void lcdCtrl_SetEntryMode(void)
{
lcdWriteCtrlWord(0b00000110); // Entry mode - inc addr, no shift
}

void lcdCtrl_ClearDisplay(void)
{
lcdWriteCtrlWord(0b00000001); // Clear display & home position
}
lcd.c (Continued from previous page)

6. Build your project and download the program into the microcontroller. You should
see the messages appear on the LCD.

7. Complete the program design map by listing down the functions that are defined in
each source file.

Project

config.h

main.c lcd.c

_________ _________
_________ _________
_________ _________

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 14 of 26


3 Lab Extra

In these extra exercises, you will learn how to integrate different parts of a program
together. As with some exercises you have done before using timer interrupts, you will
see a “background” task and a “foreground” task. You will learn how to link events in
the “background” interrupt with updates to the “foreground” display.

3.1 Exercise 2: Display Running Clock on LCD

Problem Statement:
Using the 1 second timer, show the running time on the LCD in HH:MM:SS format.

Tips: To help with


debugging in the event
that your running clock
is not shown on the
LCD, toggle the LEDs
at RA<1:0> too upon
every 1-second timer
interrupt.

Running Clock on LCD

Design Plan:
• The plan for the project is drawn in the program design map below.
• The file, dspTask.c manages the refresh of the time on the LCD whenever the 1-
second interrupt happens.

Project

config.h

main.c dspTask.c timer0.c isr.c lcd.c

Program Design Map


MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 15 of 26
Procedure:

1. Create a new project and name it as Lab_LCD_WithTimer_Ex2.

2. Complete the program skeleton provided below.

3. The main.c file has the structure shown below. It calls the function,
dspTask_TimeOnLCD() continuously.

#include <xc.h>
#include "config.h"

// Function declarations:

// - Defined in this file:


void ______________(void);

// - Defined in other file(s):


void initSysTimer0(void);
void ______________(void);
void dspTask_TimeOnLCD(void);

void main(void)
{
initSysPins(); // Initialise the port pins
______________(); // Initialise Timer0
______________(); // Initialise the LCD

while(1) {
dspTask_TimeOnLCD();
}
}

void initSysPins(void)
{
ANSELA = ____________;
ANSELD = ____________;
ANSELE = ____________;
TRISA = ____________;
TRISD = ____________;
TRISE = ____________;
}
main.c

4. The dspTask.c file contains 2 functions:


• The dspTask_OnTimer0Interrupt() function is called whenever the 1-second
timer interrupt occurs (refer to isr.c). This function takes care of managing the
incrementing and roll-over of the second, minute and hour variables.
Above is the “background” task.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 16 of 26


• The dspTask_TimeOnLCD() function is called in the while(1) loop of the main().
It refreshes the LCD display whenever the updateTime flag is set to 1 in the ISR.
This function takes care of displaying the second, minute and hour variable.
Above is the “foreground” task.

By depending on the updateTime flag to display, the CPU is freed-up to do other


tasks when the flag has the value of 0.

#include <xc.h>
#include "config.h"

// Function Declarations:
// - Declared in other file(s)
void lcdCtrl_SetPos(char x);
______________________

// Global variable(s):
unsigned char updateTime = 0;
unsigned char hour = 0, min = 0, sec = 0;

// This function is called by the ISR whenever there is 1-second interrupt:


void dspTask_OnTimer0Interrupt(void)
{
sec++; // Increments the second
if (sec>59) {
sec=0;
min++;
if (min>59) {
min=0;
hour++;
if (hour>23)
hour=0;
}
}

updateTime = 1; // Sets the flag to 1


}

dspTask.c (continues on next box)

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 17 of 26


void dspTask_TimeOnLCD(void)
{
unsigned char dig0, dig1;

if(updateTime == 1) {
lcdCtrl_SetPos(1, 1);

// Display the hour. Make use of the % and / operators


dig0 = ________________;
dig1 = ________________;
lcdWriteDspData(dig1 + ____); // Add 0x30 to translate digit to ASCII
lcdWriteDspData(dig0 + ____);
lcdWriteDspData(':');

// Display the min


dig0 = ________________;
dig1 = ________________;
lcdWriteDspData(dig1 + ____);
lcdWriteDspData(dig0 + ____);
lcdWriteDspData(':');

// Display the sec


_______________________;
_______________________;
_______________________;
_______________________;

updateTime = ___; // Reset the flag to zero so that refresh on LCD


// is only done once every second.
}
}

dspTask.c (continues from previous box)

5. In isr.c, the ISR reconfirms if the timer0 interrupt flag was set to 1. If it is, it calls the
dspTask_OnTimer0Interrupt() function. It then reloads the start count.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 18 of 26


#include <xc.h>
#include "config.h"

// Function Declarations
// - Defined in other file(s)
void __________________________(void);

void __interrupt() isr(void)


{
if(_________________) { // Check Timer0 interrupt flag
_________________; // Clear Timer0 interrupt flag
dspTask_OnTimer0Interrupt();

________________________; // Toggle RA0


________________________; // Toggle RA1

// Reload the preload value for next interrupt


TMR0H = _________;
TMR0L = _________;
}
}
isr.c

6. In timer0.c, the initSysTimer0() function manages the initialisation of Timer0 to 1


second duration using the 16-bit mode.
#include <xc.h>
#include "config.h"

void initSysTimer0(void)
{
____________________; // Disable Global Interrupt
____________________; // Set T0CON0
____________________; // Set T0CON1
____________________; // Set TMR0H
____________________; // Set TMR0L
____________________; // Clear Timer0 interrupt flag
____________________; // Enable Timer0
____________________; // Enable Global Interrupt
}

timer0.c
7. Include the file, lcd.c from previous lab exercises.
8. Build your project. Demonstrate that the running clock is displayed on the LCD.

Ponder:
How do the “background” and “foreground” tasks interact with each another? Why do
you want to design the program like this?

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 19 of 26


3.2 Exercise 3: Display External Interrupt Counts on LCD
o
+5V
SW1
PIC16F18877
RB1 RE0 E (Enable)

RE1 RS (Register Select)



R/W
RA0

RD4 DB4
RD5 DB5
RD6 DB6 LCD
RD7 DB716 characters by 2 lines
4-bit Data Bus

Hardware Connection to LCD on Lab’s Target Board

Problem Statement:

Count the number of push-button presses


on RB1 using external interrupt. Display
the count on the LCD. Blink the LED at RA0
briefly whenever the count is changed.

Applications: Steps Tracker

The push-button simulates a sensor that


detects the number of steps made.

Procedure:

1. Create a new project and name it as Lab_LCD_WithExtInt_Ex3.

2. Draw the program design map.

This enables you to conceptualise how your program will turn out to be. Fill in the
blanks to indicate the files used.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 20 of 26


Project Which other files are
there in this program?

config.h

main.c dspTask.c lcd.c _______ ______

Program Design Map

Complete the functions below.


• In main.c:
o The main() will continuously call a function dspTask_OnLCD() so that a
number can be displayed on the LCD when a step is detected.
#include <xc.h>
#include "config.h"

// Function Declarations:
// - Defined in this file:
void _____________(void);
Declare
// - Defined in other file(s): the
void _____________(void); functions
void initLCD(void); that are
void lcdWriteDspData(char x); used in
void lcdCtrl_SetPos(char row, char col); this file
void dspTask_OnLCD(void);

void main(void)
{
char message1[] = "Steps Tracker";
char message2[] = "Today:";
unsigned int i;

initSysPins(); // Initialise the port pins


initSysExtInt(); // Initialise the external interrupt
_____________(); // Initialise the LCD

lcdCtrl_SetPos(1, 1);
for(i = 0; message1[i]!=0; i++) {
lcdWriteDspData(message1[i]);
}

lcdCtrl_SetPos(2, 1);
for(i = 0; message2[i]!=0; i++) {
lcdWriteDspData(message2[i]);
}

PORTA = 0b00000000;

while(1) {
_______________();
}
}

main.c (continues on next page)

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 21 of 26


void initSysPins(void)
{

main.c (continued from previous page)


• In extint.c:
o This file will contain the function to configure the external interrupt.

o It will also keep a global variable to keep track of the number of button presses.
unsigned int extint_pbCount = 0;

o It has another global variable that is set to 1 whenever the external interrupt is
detected. And cleared to 0 whenever number display to LCD is completed.
unsigned int extint_RefreshLCDFlag = 0;

o It will have a function to increment the number of button presses detected by


external INT.
void extint_IncrCount(void)

o And another, provided for other files, to get the number of button presses.
unsigned int extint_GetCount(void)

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 22 of 26


#include <xc.h>
#include "config.h"
Global variable to
keep track of count
// Global Variable:
unsigned int extint_pbCount = 0; // Keep track of button presses.

unsigned int extint_RefreshLCDFlag = 0; // Flag:Set when ext int is detected


// Cleared when display is completed

void initSysExtInt(void)
{
Configure
the
external
interrupt
}

void extint_IncrCount(void) Function to increment count


{
_________________ // Increment the value

_________________________ // Check limit count


_________________________ // Reset count to 0, as we cannot dsp 5 digits

extint_RefreshLCDFlag = 1; // Set flag to 1 so main() can refresh the LCD


}

unsigned int extint_GetCount(void) Function to return count to caller


{
________________________ // Return the count
}

extint.c
• In dspTask.c:
o It will have a function that will be called by main() continuously so that there
will be display updates on the LCD whenever the flag,
extint_RefreshLCDFlag goes to 1.

o void dspTask_OnLCD(void)
In the function, a call will be made to the extint_GetCount() to get the
number to be displayed.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 23 of 26


#include <xc.h>
#include "config.h"

// Function Declarations:
// - Defined in other file(s):
void lcdWriteDspData(char x);
void lcdCtrl_SetPos(unsigned char row, unsigned char col);
unsigned int extint_GetCount(void); By declaring with
keyword extern, it
// Extern Global Variable means that this
extern unsigned int extint_RefreshLCDFlag; variable was already
declared in another
void dspTask_OnLCD(void) file and is shared here.
{
unsigned int count;
unsigned char dig0, dig1, dig2, dig3; What's the purpose of
checking this flag?
if(extint_RefreshLCDFlag == 1) {

PORTAbits.RA0 = 1; // Turn on the LED


Use LED as a visual
_______ = extint_GetCount(); // Get the count indication that refresh
is taking place.
dig0 = ____________________;
dig1 = ____________________;
dig2 = ____________________;
dig3 = ____________________;

lcdCtrl_SetPos(2, 8);
lcdWriteDspData(dig3 + _____); // Add 0x30 to translate digit to ASCII
lcdWriteDspData(dig2 + _____);
lcdWriteDspData(dig1 + _____);
lcdWriteDspData(dig0 + _____);

PORTAbits.RA0 = 0; // Turn off the LED Clear the flag. What's


extint_RefreshLCDFlag = ___; the purpose of doing
} so?
}

dspTask.c
The "extern" Keyword
In C, the "extern" keyword is used to declare a variable that was first declared in another file
that we could not access. It is declared with this syntax:

extern data_type identifier_name;

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 24 of 26


• In isr.c:
o Whenever the external interrupt is detected, the ISR will call
extint_IncrCount() to increase the number of push button counts by 1.
#include <xc.h>
#include "config.h"

// Function Declarations:
// - Defined in other file(s):
void extint_IncrCount(void);

void __interrupt() isr(void)


{ Call function to
if(PIR0bits.INTF == 1) // Check the INT flag increment count
{
_________________; // Clear the INT flag
_________________; // Increment the number of INT count
}
}

isr.c
8. Complete the program design map by writing down the functions that are "offered" in
each source file. Draw the flow connections.

Project

config.h

main.c dspTask.c lcd.c ________ _______

_________ _________ _________ _________ _________


_________ _________ _________ _________ _________
_________ _________ _________ _________ _________

Program Design Map

9. Build the project and download the built program into the PIC16F18877 flash memory.
Press the push button RB1. Observe the LCD. Demonstrate your program to your
tutor.
Ponder:
(1) Identify which is the “background” and the “foreground” tasks. How do each
interact with the another?

(2) Recall how does the LCD distinguishes between display data and control
instructions.

~ End of Lab ~

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 25 of 26


Appendix – Control Instructions for LCD

Control Instruction Set for LCD Module

Control Execution
D7 D6 D5 D4 D3 D2 D1 D0 Description
Word Time*

DL = 1(8-bit data length)

DL = 0(4-bit data length)

Function N = 1(2 lines)


0 0 1 DL N F 0 0 37µs
Set N = 0(1 line)

F = 1(5 by 10 dots)

F = 0(5 by 7 dots)

D = 1(Display ON)

D = 0(Display OFF)
Display
C = 1(Cursor Display ON)
On/Off 0 0 0 0 1 D C B 37µs
C = 0(Cursor Display OFF)
Control
B = 1(Blink)

B = 0(Don’t Blink)

I/D = 1(Increment position)

Entry Mode I/D = 0(Decrement position)


0 0 0 0 0 1 I/D S 37µs
Set S = 1(Shift)

S = 0(Don’t Shift)

Cursor at Return Cursor to home


0 0 0 0 0 0 1 X 1.52ms
Home position (Address 0)

Clear all display and DDRAM


Clear
0 0 0 0 0 0 0 1 address counter (home 37µs
Display
position)

Setting the cursor position


Set DD
RAM 1 A6 A5 A4 A3 A2 A1 A0 A6 = 0: line 1 37µs
Address
A6 = 1: line 2

* The execution time for the respective LCD control words are based on the Fosc (LCD built-in oscillator) =
270 kHz and are for your reference only.

MCAPP (EMC3006) Apr 25 Property of TP, Copyright © Lab 10 (LCD) | Page 26 of 26

You might also like