Anda di halaman 1dari 13

Harris Semiconductor

Harris Semiconductor

No. AN9702

February 1997

Harris Digital

Keypad Scan and LCD Interface for the CDP68HC05

Author: Christopher Mazzanti

Introduction

This application note details input/output interfaces to a Har- ris CDP68HC05 microcontroller. Being able to easily display text information to human operators and prompt for data input from a keypad is a very important part of what makes low cost 8-bit microcontrollers attractive. The LCD interface detailed within this application note is not directly to an LCD but rather to LCD modules with the Hitachi HD44780 LCD chipset, such as the Optrex 16202. The keypad scan inter-

face uses the IRQ/Pull up mask options available on all “B” versions of Harris CDP68HC05 microcontrollers (i.e.,

CDP68HC05C8B).

Operation

This section is divided into two sections: Keypad Scan and LCD Interface. Each of these sections gives an overview of the operation of the hardware and software associated with each type of interface.

KEYPAD SCAN INTERFACE

The keypad scan interface described in this application note uses the Port B interrupt/pull-up mask option of the CDP68HC05C16B. Before an explanation of the keypad scan- ning routine, a brief description of these options is detailed.

Port B Interrupts and Pullups

Note: The Port B interrupts and pull ups described here are in terms of the CDP68HC05C4B, C8B and C16B. Port A inter- rupts and pull ups on the CDP68HC05J4B function similarly except where noted.

In addition to being a standard bidirectional port, each bit of Port B has a mask option to connect a pullup device to the I/O pad and to simultaneously feed the input to the internal interrupt logic. When the mask option is not selected, each Port B pin behaves as a standard bidirectional port pin.

When the mask option is selected, a pullup PMOS device with an impedance of approximately 20k is connected between the pad and V DD (see Figure 1B for Pullup Current I IN ) and the input signal is inverted and internally ORed with the IRQ signal (refer to Figure 1A).

The interrupt behavior of any port B pin which has the pul- lup/interrupt mask option activated is identical to the results one would achieve by externally ORing (active low) the sig-

nal with the IRQ signal.

The pullup device and the interrupt function are disabled when the associated DDRB bit is set high. When its DDRB bit is a 1, each port B pin acts as a normal output regardless of whether or not the pullup/interrupt mask option has been selected. Thus the DDRB bit can be used as an interrupt enable for the interruptible port B pins. Care should be taken when re-enabling a port B interrupt to avoid false interrupts. False interrupts can be avoided by first driving the PORTB bit high before clearing the DDRB bit. Further note that all DDRB bits are cleared by reset, thus enabling port B inter- rupts (no interrupt will be recognized until execution of the first CLI instruction following reset).

V DD V DD MASK OPTION P DDRB BIT n PBn PORT CIRCUITRY TO INTERNAL
V DD
V DD
MASK OPTION
P
DDRB BIT n
PBn
PORT
CIRCUITRY
TO INTERNAL
OTHER PORT B INPUTS
INTERRUPT
IRQ

FIGURE 1A.

PORT B INTERRUPT AND PULLUP MASK OPTION

300 250 200 150 100 50 0 1.0 2.0 3.0 4.0 5.0 6.0 I IN
300
250
200
150
100
50
0
1.0
2.0
3.0
4.0
5.0
6.0
I IN , P-CHANNEL PULL UP DEVICE
CURRENT ( A)

V PD , PULL DOWN VOLTAGE (V)

FIGURE 1B. C4B, C8B, C16B P-FET PULL UP DEVICE CHARACTERIZATION CURVE

Copyright © Harris Corporation 1997

1

Application Note 9702

Keypad Scanning

The keypad scan routine detailed here is for a 16 key, 4 row by 4 column matrix keypad. Four of the keypad I/O port lines

must be on a I/O port with the IRQ/Pull-up mask option set. These lines will detect a key press by causing an external hardware interrupt to be issued whenever any key is pressed. The other four port I/O lines connected to the key- pad can be from any general purpose output port. Also, it is

assumed that the IRQ edge/level option is set to “edge only”.

The basic operation for scanning a keypad is quite simple. Four lines from the microcontroller connect to the row lines of the keypad. These are output lines that the MCU will strobe to determine which key is being pressed. The other four lines are connected to the column lines of the keypad

and go straight to the IRQ/Pull-up I/O port lines of the MCU (Port B for the CDP68HC05C4B/C8B/C16B and Port A for the CDP68HC05J4B). These lines will always be in the input mode when scanning the keypad (See Figure 2). When wait- ing for a keypress, all four row lines (i.e., the output lines) will be driven low. The column lines (input lines) will be pulled up through their individual on-chip pull-up resistors. Whenever any key is pressed, the associated column line is pulled low (since it is now connected to a row line), causing a hardware

interrupt to be issued. It is the responsibility of the IRQ ser- vice routine to determine if a key is being pressed and if so, to debounce it and figure out which one. While waiting for a key press, the 68HC05 will most likely have other things to do. To allow the MCU to go about it’s processing, all Harris 68HC05xxxB version microcontrollers have mask options that can make each one of the lines on a specific I/O port act

like the IRQ pin when that particular line is pulled low in input mode. Thus, whenever one of these lines is pulled low, a hardware interrupt is issued. Internal active CMOS pull-up resistors are connected to the port so that the inputs are not floating when not connected to anything, causing inadvertent interrupts. Since all four row lines are driven low while wait- ing, any keypress will pull at least one line low, causing an

IRQ interrupt. Without this port interrupt ability, the MCU would have to continuously scan the keypad to detect a key-

press. This is the advantage of having the IRQ/Pull-up mask option enabled.

1 2 3 4 1 2 3 4 ROW LINES TO MCU OUTPUT
1
2
3
4
1
2
3
4
ROW LINES
TO MCU OUTPUT

COLUMN LINES - TO MCU INPUT

FIGURE 2. 4x4 MATRIX KEYPAD

The IRQ service routine is where all of the keypad scanning,

debouncing and key identification takes place. In the IRQ service routine, the first thing that has to be done is to deter-

mine the source of the IRQ. If the user code is using the IRQ pin of the MCU to connect to another peripheral (a Harris

65C51 UART for example), the IRQ service routien must

determine if the interrupt came from the IRQ pin or from the

Port B pull-ups. Once the source of the IRQ has been deter- mined to be a keypress, the next thing to do is to debounce it. This needs to be done because switch bounce (caused by the switch contacts closing, separating and the closing again) can cause the 68HC05 to read the switch during a bounce and incorrectly assume that no key is being pressed. To avoid this we use a 5ms timing delay loop. This delay gives the contacts plenty of time to bounce and settle into position. Now that the keypress has been detected and debounced, the interrupt routine must now figure out which key is being pressed. To do this we read in the column bits and test them sequentially to determine in which column a key is being pressed in. If two keys are being pressed simul- taneously, this scan routine will detect the one in the column scanned first.

Once it has been determined which column the key is in, the service routine must now determine which row in that col- umn the key is in, thus giving us the key location. At this point we write “1”s to all of the row locations except for the first one (i.e., row 1 in this case). We then test the column bit where we determined previously that the key being pressed was in. If this line is low, then we have found the key. If not, then we write “1”s to all of the row lines except for row 2 and test the column again. In this way we can scan through the keypad and determine the exact location of the keypress. Running at 4MHz, the 68HC05 can scan the keypad much faster than a human can press a key and release it (even with the 5ms debounce delay). If the routine determines that no key is pressed, then it simply returns from the interrupt

and continues from where it left off. The IRQ service routine in the assembly listing later in the document details the entire keypad scanning process.

LCD INTERFACE

Strictly speaking, the interface described here does not con- nect a 68HC05 with an LCD. To do so would require special control circuitry in the 68HC05 itself and many more I/O lines than are available even with the 40 pin CDP68HC05C16B. Rather, this interface is to the Hitachi LCD driver/display con- trol chip set specifically designed for controlling text LCD dis- plays. These chips have become very standard in their interface and are used by many LCD module manufacturers such as Optrex. The LCD unit used for this application note is an Optrex DMC16202. This is a 16 character by 2 line dis- play, although larger displays (in terms of character length

and line count) work similarly.

The standard LCD interface (as the Hitachi-interface will be

referred to from now on) will need a maximum of 14 lines connected to the LCD module - 8 data, 3 control, 2 power and 1 contrast (see the LCD technical information for details on power supply and contrast connections) of which any- where from 6 to 11 lines will need to be connected to the MCU. Data can be transferred to the LCD in either byte-wide transfers or nibble-wide transfers, but since all text to be dis- played on the LCD is encoded in an 8-bit ASCII-like format, choosing four bit operation means that two transfer opera- tions will be needed for every character sent to the LCD. 8- bit transfers require more I/O port lines, but they do speed up

LCD transfers and make the software interface a bit more

2

Application Note 9702

simple. This application note contains a code to run the LCD in either 8-bit or 4-bit mode, depending upon assembler directives. Diagrams for the two types of LCD interface along with the keypad connections are shown below in Figures 3A and 3B. Both of these connections and the code associated with them read from the LCD and poll the LCD busy flag instead of using timing delays. Note that the four bit interface transfers data on the low nibble of the port, although the soft- ware could just as easily be changed to transfer on the high nibble of the port.

When writing data to the LCD module, there are two types of transfers that can occur - a control write or a data write. Con- trol writes are data sent to the LCD for configuration pur- poses such as setting the DDRAM address pointer (more about the DDRAM in the next paragraph), data interface length, and cursor display for example (a complete list of all of the control codes for the LCD is listed below). The RS control line to the LCD needs to be low for control code writes to the LCD. If the RS line is high, writes to the LCD are written to the DDRAM.

Data written to the LCD module for display is written to RAM locations in the Hitachi interface chips and is echoed to the display. This RAM is known as Data Display RAM (DDRAM). Every display location on the LCD has an associated DDRAM location with it; there are even DDRAM locations that exist that are not displayed. The DDRAM has an internal

address pointer so that data byte writes to the LCD will go to

a specific location. This address pointer can be set up to

increment or not to increment when data is written to the DDRAM. The address pointer can also be set directly by a

control write. DDRAM display locations along with a table of all of the control codes for the LCD module are shown below

in Figure 6 and Table 2, respectively.

The E control line of the LCD module is used as the data strobe of the module. This is an active high pulse used to latch the data being written into the LCD or to signal the MCU that the data being read from the LCD is ready. Timing diagrams for write and read operations are shown in Figure 4 below.

LCD RS KEYPAD PORT I/O E R/W ROW 4 PORT B [7:4] DATA [7:4] COLUMN
LCD
RS
KEYPAD
PORT I/O
E
R/W
ROW
4
PORT B [7:4]
DATA [7:4]
COLUMN
PORT B [3:0]
DATA [3:0]
4
68HC05C8B
FIGURE 3A. 8-BIT LCD INTERFACE WITH KEYPAD
68HC05J4B
LCD
RS
KEYPAD
E
PORT I/O
R/W
ROW
4
PORT A [3:0]
DATA [7:4]
COLUMN
4
PORT C [3:0]

NOTE: IRQ/PULL-UP OPTION ON PORT B [7:4]

NOTE: IRQ/PULL-UP OPTION ON PORT A [3:0]

FIGURE 3B. 4-BIT LCD INTERFACE WITH KEYPAD

LINE 1

LINE 2

DISPLAY POSITION

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

0E

0F

10

11

.

.

.

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4E

4F

50

51

.

.

.

UNSHIFTED 16 CHARACTER DISPLAY AREA

50 51 . . . UNSHIFTED 16 CHARACTER DISPLAY AREA UPPER DDRAM ADDRESSES DDRAM ADDRESSES (HEX)
50 51 . . . UNSHIFTED 16 CHARACTER DISPLAY AREA UPPER DDRAM ADDRESSES DDRAM ADDRESSES (HEX)

UPPER DDRAM

ADDRESSES

DDRAM ADDRESSES (HEX)

FIGURE 4. DDRAM ADDRESSES AND LCD DISPLAY POSITION

3

Application Note 9702

RS t AS t AH R/W PW EH t AH t ER E t EF
RS
t AS
t AH
R/W
PW EH
t AH
t ER
E
t
EF
t DSW
t H
VALID
DB0 ~ DB7
DATA
t
CYCE

FIGURE 5A. WRITE OPERATION

RS t AS t AH R/W t ER PW EH t AH E t EF
RS
t AS
t AH
R/W
t ER
PW EH
t AH
E
t EF
t
DDR
t DHR
VALID
DB0 ~ DB7
DATA
t
CYCE

FIGURE 5B. READ OPERATION

TABLE 1. TIMING CHART

ITEM

SYMBOL

MEASURING CONDITION

MIN

TYP

MAX

UNIT

Enable Cycle Time

T CYCE

Write, Read

1000

 

-

- ns

 

Enable Pulse Width, High Level

PW EH

Write, Read

450

 

-

- ns

 

Enable Rise and Decay Time

t Er , t Ef

Write, Read

-

 

25

- ns

 

Address Setup Time, RS, R/W-E

 

t

AS

Write, Read

140

 

-

- ns

 

Data Delay Time

t

DDR

Read

-

 

320

- ns

 

Data Setup Time

t

DSW

Write

195

 

-

- ns

 

Data Hold Time (Write Operation)

 

t

H

Write

10

 

-

- ns

 

Data Hold Time (Read Operation)

t

DHR

Read

20

 

-

- ns

 

Address Hold Time

 

t

AH

Write, Read

10

 

-

- ns

 

The LCD interface contains a read/write control line that can allow the MCU to read data from the LCD module. Since the characters being displayed each have their own address loca- tion within the LCD’s “display RAM”, they can be addressed and read just like any other peripheral RAM. Chances are that most applications will not need to do this. However, being able to read the LCD means that the LCD subroutines can check the status of the LCD busy flag. Each operation the LCD per- forms takes a certain amount of time to complete. Most of these times are around to 40 s range, although some opera- tions can take as long as 1.64ms to complete. With a MCU running at 4MHz, this can be quite a long time. During one of the operations, the LCD ignores all data transmissions until it is done. To avoid sending the LCD data that will be ignored, the MCU must either poll the busy flag by reading a control byte from the LCD or sit in delay loops until the LCD has com- pleted it’s operation. The second alternative saves an I/O line (the LCD read/write bit would simply be tied low) but does require extra timing loops in the source program that may be unnecessary. Another drawback to using timing loops is that for every write to the LCD, at least 40 s of MCU time will be wasted, most of it in unproductive delay loops. If the busy flag is only polled at the beginning of a write sequence, so if the MCU was doing other things between writes to the LCD (as would probably be the case), chances are that the LCD will almost always have time to complete a write cycle. If the LCD is busy when a write starts, then and only then will the 68HC05 wait for the LCD to complete it’s operation. If the operation is a clear display (or similar) that takes 1.64ms to complete, even more MCU time is wasted if timing loops are

used. Also, there is still the risk that the LCD is not finished with an operation even though the timing loop is finished. Reading the LCD has the drawback of the added I/O line and code complexity, but is assures that the LCD is done with pre- vious operations before being written to. As long as I/O port constraints and code size permit it, we recommend polling the busy flag over timing loops.

7

8

9

/

4

5

6

*

1

2

3

-

0

.

C

+

FIGURE 6. ASCII KEYPAD ASSIGNMENT

Software

The software routines written for this application note include all of those needed to interface a 4x4 matrix keypad and a 16x2 Optrex LCD display. Included in the assembly listing are all of the subroutines necessary to read data from the LCD, write data to the LCD and scan the keypad. Also included are some higher level subroutines (i.e., they call the LCD read/write rou- tine WLCD and RLCD) to make string display a little easier. The basic function of the “main” program listed here is to “wait” for a keypress and display the key that was pressed. The LCD will be cleared and the cursor set to the home position when the “C” key is hit. Each of the 16 keys on the keypad have been assigned an ASCII value in a setup similar to a calculator key-

pad (Figure 6). All of the keypad scanning is done in the IRQ interrupt service routine.

4

Application Note 9702

TABLE 2. LCD COMMAND CODE CHART

   

CODE

   

EXECUTION

INSTRUCTION

RS

R/W

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

DESCRIPTION

TIME (MAX)

Clear Display

0

0

0

0

0

0

0

0

0

1

Clears the display and returns cursor to home position.

1.64ms

Cursor at Home

0

0

0

0

0

0

0

0

1

x

Returns cursor to home position. Also returns the display being shifted.

1.64ms

Entry Mode Set

0

0

0

0

0

0

0

1

I/D

S

Sets cursor increment (I/D) and dis- play shift (S).

40 s

Display On/Off

0

0

0

0

0

0

1

D

C

B

Sets Display On/Off (D), cursor On/Off (C), Blink Cursor (B)

40 s

Cursor/Display

0

0

0

0

0

1

S/C

R/L

x

x

Sets display/cursor shift (S/C) and di- rection of shift (R/L)

40 s

Shift

Function Set

0

0

0

0

1

DL

N

F

x

x

Set interface length (DL), number of lines (N) and character font (F)

40 s

CGRAM

0

0

0

1

 

CGRAM Address

 

Sets the Character Generator RAM address

40 s

address set

 

DDRAM

0

0

1

 

DDRAM Address

 

Sets the Data Display RAM address

40 s

address set

 

Busy Flag/

0

1

BF

Address Counter (Both DDRAM and CGRAM)

Reads the Busy Flag (BF) and ad- dress counter contents.

40 s

Address Read

CG/DDRAM

1

0

 

Write Data

 

Writes data into DDRAM or CGRAM

40 s

Data Write

 

CG/DDRAM

1

1

 

Read Data

 

Reads data from DDRAM or CGRAM

40 s

Data Read

 

I/D: 0 = increment, 1 = decrement S: 0 = no shift, 1 = shift display S/C: Display Shift, 1 = Cursor Shift

R/L: 0 = Shift Left, 1= Shift Right DL: 0 = 4-bit, 1 = 8-bit N: 0 = 1 line, 1 = 2 lines

 

F: 0 = 5x7 dots, 1 = 5x10 dots BF: 0 = LCD ready, 1 = LCD Busy x = don’t care

 

irqIsr - this is the IRQ interrupt service routine and where all of the keypad scanning and key identification takes place. The first thing that is done here is a delay subrou- tine called debounce is called. The purpose of this rou- tine is to give the switch contacts enough time to settle so that reads of the keypad won’t produce erroneous results. This delay here is set for approximately 5ms (at 4MHz) but can easily be shorted or lengthened to suit different applications. Next, the columns of the keypad are scanned to see in which column the key being pressed is in. Note that this routine relays heavily on the keypad constants defined at the beginning of the assembly list- ing. “Col” is defined as the I/O port to which the keypad columns are connected. Likewise, “row” is the port to which the keypad row lines are connected. “row1”, “row2, “col1”, etc., are the bits within the “row” and “col” ports that those respective keypad lines are connected to. In this way the keypad columns and rows can be moved to different port locations without changing the assembly code. Once the column that the key being pressed is in is identified, it’s value minus 1 (i.e., column 1 = 0) is stored in the RAM variable colID. Next the rows are scanned.

This is done in a loop where each row line is individually driven low while the others are high and the columns checked for a keypress. When the row that the key is in is identified, it’s row location is stored in rowID the same way as the column number was stored in colID. Now that the row and column of the key are known, colID and rowID are put together (rowID:colID) to form a unique four bit ID of the key that was pressed (This method can be used to scan keypads up to 16x16). This ID number is then used as an offset into a table (keyTable). The table here simply contains the ASCII values of the keys for dis- play on the LCD. This ASCII value for the key that was pressed is stored in the RAM variable “keyData” for return to the main routine. The “keyFlag” variable also has it’s bit 0 set to indicate to the main program that a keypress has occurred. Before the RTI is issued, this particular routine waits until the key is released. This is done because the key being pressed could interfere with accesses to the LCD and cause false interrupts to be issued. If the key- pad does not share I/O ports with another peripheral, this part of the routine can be removed.

5

Application Note 9702

hex2asc - This is a simple but useful little subroutine for converting hexadecimal nibbles into ASCII bytes. For any hex number sent to this routine in the low nibble of ACCA, it’s ASCII value will be returned.

txlcd1 - This is one of a pair of text string display routines written for the LCD interface. This routine uses a constant defined in the assembler as mesPage and a variable in IX as a pointer to the beginning of the message. The disad- vantage to this is that ALL of the text messages must reside in the same 256 byte page (i.e., $09xx). The advan- tage of this routine is that it is smaller than txlcd2, it requires only one parameter to be setup prior to being called (IX) and it only uses 1 byte of RAM (no RAM is used except for that used in wclcd and wdlcd if the contents of ACCA are not preserved). The format for the message is <control byte, message, $00>. The control byte is used for positioning the LCD cursor before the write (i.e., $80 would send the cursor to position 0, line 1). The message part is simply ASCII text. The $00 at the end is essential because this is how the routine knows the message is fin- ished.

txlcd2 - This is the other text string display routine devel- oped for the LCD interface. This routine is more complex and uses 4 bytes of RAM but it does have the advantage that the LCD message can be anywhere in memory. The location of the message is passed to the subroutine in ACCA and IX in the form ACCA:IX. In the subroutine, another subroutine is set up in RAM and it is this routine that is used to get the bytes of the message. If this routine is used, it is important that a $C6 is stored to ramSub1 and a $81 is stored to ramSub4. These are the LDA (extended) and RTS opcodes for the RAM subroutine. If the user program does not wish to load both ACCA and IX (IX may be being used as a counter) then the message address can be stored directly in ramSub2:ramSub3 before calling the program. In this case the first two lines of the subroutine could be deleted.

wclcd - This is the subroutine called for writing a control byte, contained in ACCA, to the LCD. The meat of this subroutine, like that of wdlcd, is the routine wlcd. The wclcd part simply sets the RS control line of the LCD low, indicating a control write.

wdlcd - Same as wclcd except that the RS control line of the LCD is set high indicating a data write to the LCD.

wlcd - This is one of the two main LCD interface subrou- tines. This routine takes a byte passed to it in the accumu- lator and writes it to the LCD. It is important to remember that the RS control line is not affected by this subroutine, so writes to the LCD will almost always call either wclcd or wdlcd instead. This routine requires several RAM bytes to properly preserve the state of the LCD data port upon exit (this is important when using the port i/o for both LCD and keypad interface). If the state of the LCD data port is not important in that only the LCD is connected to these lines, the RAM variables lcdTemp5 and lcdTemp6 can be removed from this routine. The first thing that happens when wlcd is called is that the state of the RS bit is pre- served. This is important because when the subroutine

rclcd is called to check the LCD busy flag, the RS bit will return clear. Wlcd will loop infinitely until the flag is clear. When the flag is clear, the RS bit is restored and the E strobe is lowered. The byte sent to the routine is loaded and, if the 4bit assemble option, the byte is shifted right four times, added to the previous port data and written to the LCD output. If the 4bit option is not set, the entire byte is simple written to the LCD port. After the write, the E strobe is pulled high followed by two NOPs for timing (this gives a 2ms pulse width at 4MHz. More may be needed at higher frequencies), after which time the E strobe is low- ered. At this point the 8-bit interface is done, but the 4-bit interface still has to write the lower nibble of the data byte to the LCD port and strobe the LCD again.

rclcd - This is the subroutine called for reading a control byte from the LCD and returned to the calling program in ACCA. The meat of this subroutine, like that of rdlcd, is the routine rlcd. The rclcd part simply sets the RS control line of the LCD low, indicating a control read.

rdlcd - Same as rclcd except that the RS control line of the LCD is set high indicating a data read from the LCD.

rlcd - this subroutine is a second of the two major LCD interface subroutines. Like wlcd, this routine has the 4bit assembler option for a 4-bit/8-bit LCD interface.

lcdini - this subroutine is an important one to call before any of the other LCD interface routines are called. When the LCD module powers up, its default state is usually not what is desired. In this routine the data interface length is set along with the cursor type and increment, the display is then turned on and cleared. If these operations are not performed, the other LCD routines will not work. This sub- routine also sets up the RS, E and R/W LCD control lines as outputs. The ramSub1 and ramSub4 locations are ini- tialized here, but these lines can be removed if the main program does not use txlcd2.

kbiIni - this is a simple subroutine that initializes the I/O ports to which the keypad is connected. In the example program, the 4-bit LCD interface has the rows of the key- pad connected to PC0:3. In the 8-bit interface, the rows of the keypad are connected to PB4:7. In both cases the col- umns of the LCD are connected to PB0:3. This program uses the scans input from the keypad from the columns, so PB0:3 are set to input mode. The output bits connected to the rows are made outputs and they are all forced low,

so that when any key on the keypad is pressed, an IRQ will be issued.

6

Application Note 9702

HARRIS Semiconductor (c)1990 - 1996 68HC05 Assembler Version 2.6

Filename:

LCD2.LST

 

Source Created:

01/13/97, 00:20 am

 

Assembled:

01/13/97, 00:20:06

00001

;*****************************************************************************

00002

;

aaaaaaaaaaaa

 

00003

;

rH""""HHHH""""Hr

00004

;

HHH

HHHH

HHH

COPYRIGHT 1995,1996,1997

 

00005

;

,-.

,-.

,-.

HARRIS SEMICONDUCTOR

00006

;

/

|_/

|_/

|

00007

;

sss

ssss

sss

00008

;

HH

HHHH

HH

00009

;

"HHHHHHHHHHHH"

 

00010

;

00011

;

File:

lcd.s

 

00012

;

00013

;

Version: 1.0

 

00014

;

00015

;

Author: Christopher Mazzanti

 

00016

;

00017

;

Date: Wed 01-07-96

 

00018

;

00019

;

Description:

 

00020

;

The following is a file of subroutines created for inter-

00021

;

afacing a 68HC05 MCU with a LCD module containing the Hitachi

00022

;

HD44780 LCD interface chip and a 16 key (4x4 matrix) keypad.

00023

;

The main program used to test out these subroutines prints a

00024

;

text message to the LCD prompting for data and displays char-

00025

;

acters corresponding to the keys that are pressed. This program

00026

;

was tested out on a CDP68HC05C16B wired so that both 4 and 8

00027

;

bit interfaces to the LCD could be tried out. Note that if

00028

;

the four bit interface is chosen, the LCD must be connected to

00029

;

the lower nibble of the port.

 

00030

;

Hardware Setup:

4 bit

8 bit

LCD

Keypad

00031

;

-----

-----

---

------

00032

;

PC3

PB7

DB7

row 4

00033

;

PC2

PB6

DB6

row 3

00034

;

PC1

PB5

DB5

row 2

00035

;

PC0

PB4

DB4

row 1

00036

;

PB3

PB3

DB3

col 4

(IRQ)

00037

;

PB2

PB2

DB2

col 3

(IRQ)

00038

;

PB1

PB1

DB1

col 2

(IRQ)

00039

;

PB0

PB0

DB0

col 1

(IRQ)

00040

;

PC7

PC7

RS

00041

;

PC6

PC6

R/W

00042

;

PC6

PC5

E

00043

;*****************************************************************************

00044

#include c:\6805\c16b.s

 

--------------------- START OF INCLUDE C:\6805\C16B.S --------------------

00001

#nolist

00125

#list

----------------------- END OF INCLUDE C:\6805\C16B.S ---------------------

00045

00046

;*****************************************************************************

00047

; Define Statements: The following constants must be defined for the

00048

;

the proper operation of the LCD and keypad interface

00049

;

subroutines/interrupt service routines:

00050

;

4bit - this constant defines the LCD interface.

00051

;

lcd - the I/O port to which the LCD is connected.

00052

;

row - the I/O port to which the rows of the keypad are connected

00053

;

row1, row2, etc. - bit pos. in the row I/O port of each row

00054

;

col - the I/O port connected to the columns of the keypad.

00055

;

col1, col2, etc. - bit pos. in the column I/O port of each column

00056

;

lcdctl - I/O port connected to the control lines of the LCD

00057

;

rw - bit pos. of the rw LCD control line in the lcdctl port

00058

;

rs - bit pos. of the rs LCD control line in the lcdctl port

00059

;

e - bit pos. of the e LCD control line in the lcdctl port

00060

;

rowMask - a special mask used in keypad scanning

00061

;

colMask - a special mask used in keypad scanning

00062

;*****************************************************************************

00063

00064

$0001 =

1

4bit

equ

1

;used to set data interface length

00065 TRUE

#if 4bit

;set up constants for 4 bit interface

00066 $0002 =

2

lcd

equ

portc

00067 $0002 =

2

row

equ

portc

00068 $0000 =

0

row1

equ

0

00069 $0001 =

1

row2

equ

1

00070 $0002 =

2

row3

equ

2

00071 $0003 =

3

row4

equ

3

7

Application Note 9702

00072

FALSE

#else

;set up constants for 8 bit interface

00079

#endif

00080

00081

$0002 =

2

lcdctl

equ

portc

00082

$0007 =

7

rs

equ

7

00083

$0005 =

5

e

equ

5

00084

$0006 =

6

rw

equ

6

00085

00086

$0001 =

1

col

equ

portb

00087

$0000 =

0

col1

equ

0

00088

$0001 =

1

col2

equ

1

00089

$0002 =

2

col3

equ

2

00090

$0003 =

3

col4

equ

3

00091

00092

$000F =

15

rowMask

equ

2!row1+2!row2+2!row3+2!row4

00093

$000F =

15

colMask

equ

2!col1+2!col2+2!col3+2!col4

00094

00095

;*****************************************************************************

00096

; RAM Variables: The following RAM locations must be allocated for the

00097

;

proper use of the LCD and keypad scanning subroutines.

00098

;

lcdTemp1-6 - temp storage locations used by WLCD and RLCD. These

00099

;

can be used by the main program in between calls.

00100

;

ramSub1-4 - used to create a RAM subroutine, used by TXLCD2 only.

00101

;

rowID - used as temp storage for row detection in keypad scanning

00102

;

colID - used as temp storage for column detection

00103

;

scanMask - used to hold scanning mask during keypad scan

00104

;

keyFlag - used as keypad status (bit 0 only)

00105

;

keyData - used to store key ID from keypad scan routine

00106

;*****************************************************************************

00107

00108

0050

section vars, $50

 

00109

0050

lcdTemp1

ds

1

;\

00110

0051

lcdTemp2

ds

1

;

;

|

00111

0052

lcdTemp3

ds

1

; | These locations are used for temp

00112

0053

lcdTemp4

ds

1

; | storage in the LCD subroutines

00113

0054

lcdTemp5

ds

1

|

00114

0055

lcdTemp6

ds

1

;/

00115

0056

ramSub1

ds

1

;\

00116

0057

ramSub2

ds

1

; | These locations are used for the

00117

0058

ramSub3

ds

1

; | LCD subroutine TXLCD2 only

00118

0059

ramSub4

ds

1

;/

00119

005A

rowID

ds

1

;\

00120

005B

colID

ds

1

;

;

;

;

|

00121

005C

scanMask

ds

1

; | Used for the keypad scan ISR

00122

005D

keyFlag

ds

1

|

00123

$0000 =

0

keyin

equ

0

|

00124

$0001 =

1

imask

equ

1

|

00125

005E

keyData

ds

1

;/

00126

00127

0180

section code, $180

 

00128

00129

0180

9C

rsp

00130

0181

9B

sei

00131

0182

125D

bset

imask,keyFlag

;interrupts masked

00132

0184

4F

clra

00133

0185

C73FDF

sta

option

;set C16B IRQ to edge only

00134

0188

CD0311

jsr

lcdIni

;initialize LCD

00135

018B

CD0230

jsr

kbiIni

;initialize keypad

00136

018E

AE00

ldx

#msg&$FF

;send 1st half of lcd message

00137

0190 CD024C

 

jsr

txlcd1

00138

0193

A606

lda

#msg2/256

;send 2nd half of lcd message

00139

0195 AE07

 

ldx

#msg2&$FF

00140

0197 CD0260

jsr

txlcd2

00141

019A

A6C0

lda

#$C0

;position LCD to beginning of

00142

019C

CD0277

jsr

wclcd

;line 2

00143

019F

3F5D

clr

keyFlag

;clear keypad flag

00144

01A1

9A

cli

;enable interrupts

00145

waitKey

00146

01A2

015DFD

brclr

0,keyFlag,*

;wait for key press

00147

break

00148

01A5

3F5D

clr

keyFlag

;clear keypad flag

00149

01A7

B65E

lda

keyData

;get keypad data

00150

01A9

A143

cmp

#'C'

;check for "C"

00151

01AB

2705

beq

clrLine

;if C, clear line 2

00152

01AD

CD027B

jsr

wdlcd

;else write character

00153

01B0

20F0

bra

waitKey

;get another key

00154

clrLine

00155

01B2

AE0F

ldx

#clearMes&$FF

;clear line 2

00156

01B4 CD024C

 

jsr

txlcd1

00157

01B7

A6C0

lda

#$C0

;reposition cursor

00158

01B9 CD0277

 

jsr

wclcd

00159

01BC 20E4

bra

waitKey

8

Application Note 9702

00160

00161

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00162

;

**** IRQISR ****

 

;

00163

; This is the interrupt service routine called whenever any

;

00164

; key on the keypad is pressed. This routine includes a 5ms

;

00165

; debounce delay to avoid erroneous keypresses from switch

;

00166

;

bounce. The keypad is then checked. If no key is being

;

00167

;

pressed, the routine will simply return. If a key is pressed ;

00168

; this routine will display it's assigned character on the LCD ;

00169

;

If the "C" key is pressed, line 2 of the LCD will be cleared ;

00170

; and the cursor returned to the beginning of the line.

;

00171

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00172

00173

irqIsr

00174

01BE

CD0216

jsr

debounce

;5ms debounce

00175

01C1

3F5B

clr

colID

;clear column ID #

00176

01C3

010112

brclr

col1,col,scanRow

;check column 1 for key

00177

01C6 3C5B

 

inc

colID

00178

01C8

03010D

brclr

col2,col,scanRow

;check column 2 for key

00179

01CB 3C5B

 

inc

colID

00180

01CD

050108

brclr

col3,col,scanRow

;check column 3 for key

00181

01D0 3C5B

 

inc

colID

00182

01D2

070103

brclr

col4,col,scanRow

;check column 4 for key

00183

01D5

CC01F6

jmp

noKey

;if none, quit ISR

00184

scanRow

00185

01D8

A603

lda

#$03

;set up row ID

00186

01DA

B75A

sta

rowID

;for scan of row 4

00187

01DC

A6F7

lda

#~(2!row4)

;set up scan mask

00188

01DE B75C

 

sta

scanMask

00189

rowLoop

00190

01E0

B602

lda

row

;get keypad row

00191

01E2

AA0F

ora

#rowMask

;make keypad row all "1"s

00192

01E4

B45C

and

scanMask

;mask row

00193

01E6 B702

 

sta

row

00194

01E8

B601

lda

col

;get keypad column

00195

01EA

AAF0

ora

#~colMask

;set non column bits to 1

00196

01EC

43

coma

;test results (no key = 0)

00197

01ED

260A

bne

gotKey

;if not 0, found key

00198

01EF

99

sec

;set carry bit for rotate

00199

01F0

365C

ror

scanMask

;shift row scan bit right

00200

01F2

3A5A

dec

rowID

;decrement to shift next row

00201

01F4

2AEA

bpl

rowLoop

;loop for all 4 rows

00202

noKey

00203

01F6

AD38

bsr

kbiIni

;when done (or no key) re-init

00204

01F8

80

rti

;keypad port & return

00205

gotKey

00206

01F9 B602

 

lda

row

00207

01FB

A4F0

and

#~rowMask

;drive all rows low again

00208

01FD

B702

sta

row

;needed for 8 bit routine

00209

01FF

B65A

lda

rowID

;form ofset from rowID:colID

00210

0201 48

 

lsla

00211

0202 48

lsla

00212

0203

BB5B

add

colID

00213

0205

97

tax

;use rowID:colID as offset

00214

0206

D60220

lda

keyTable,x

;get key ID from table

00215

0209

B75E

sta

keyData

;store to keyData

00216

020B

105D

bset

0,keyFlag

;set keypress flag

00217

release

00218

020D

B601

lda

col

;wait for key to be released

00219

020F AAF0

 

ora

#~colMask

00220

0211 43

coma

00221

0212 26F9

bne

release

00222

0214

20E0

bra

noKey

;and quit

00223

00224

debounce

;\

00225

0216

A609

lda

#$09

;

;

;

|

|

|

|

00226

debounce1

|

00227

0218

5F

clrx

|

00228

debounce2

; | ~5ms delay loop

00229

0219

5A

decx

; | for debouncing keypress

00230

021A

26FD

bne

debounce2

;

00231

021C

4A

deca

;

00232

021D

26F9

bne

debounce1

;

00233

021F

81

rts

;/

00234

00235

0220

3738392F keyTable

db

"789/456*123-0.C+"

;keypad lookup table

0224

3435362A

0228

3132332D

022C 302E432B

 

00236

00237

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00238

; **** kbiIni ****

 

;

9

Application Note 9702

00239

; This routine is used to set up the keyboard i/o ports for

 

;

00240

; the scanning routine.

 

;

00241

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00242

00243

kbiIni

 

00244

0230

B605

lda

col+4

;column are inputs

00245

0232 A4F0

 

and

#~colMask

00246

0234 B705

sta

col+4

00247

0236

B606

lda

row+4

#rowMask

;make rows outputs

00248

0238

AA0F

ora

;and load w/ 0's

00249

023A B706

 

sta

row+4

00250

023C B602

lda

row

00251

023E A4F0

and

#~rowMask

00252

0240 B702

sta

row

00253

0242

81

rts

00254

00255

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00256

;

**** HEX2ASC ****

 

;

00257

; This routine converts a hexadecimal number in the low nibble ;

00258

;

of ACCA to ASCII for output to the LCD

 

;

00259

;

Calls:

None

Modified: ACCA

;

00260

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00261

00262

0243 AB30

HEX2ASC

ADD

#$30

00263

0245 A13A

CMP

#$3A

00264

0247 2B02

BMI

SKIP

00265

0249 AB07

ADD

#$07

00266

024B

81

SKIP

RTS

00267

00268

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00269

;

**** TXLCD1 ****

 

;

00270

; This routine takes the ASCII message pointed to by

;

00271

; mesPage:X and displays it on the LCD. This routine ass-

;

00272

; umes the entire message in on memory page mesPage. This

;

00273

; routine is smaller than TXLCD2 because it only increments ;

 

00274

;

one value (X) and only uses 1 RAM location (mesPage).

The ;

00275

;

first byte of the message pointed to should be the control ;

00276

;

code for placement of the message in the LCD. The last

;

00277

;

byte of the message MUST be $00.

;

00278

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00279

00280

TXLCD1

 

00281

024C

B750

sta

lcdTemp1

;PRESERVE ACCA AND IX

00282

024E

D60600

lda

mespage,x

;get first byte of message

00283

0251

AD24

bsr

wclcd

;and use it as control (position LCD)

00284

mesloop

 

00285

0253

5C

incx

 

;increment pointer into message

00286

0254

D60600

lda

mespage,x

;get next byte of message

 

00287

0257

2704

beq

mesLoopDone

00288

0259

AD20

bsr

wdlcd

;check for $00 (end of message) ;send byte to LCD as data

00289

025B

20F6

bra

mesLoop

;loop until end of message

00290

mesLoopDone

 

00291

025D

B650

lda

lcdtemp1

;restore ACCA

00292

025F

81

rts

00293

00294

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00295

;

**** TXLCD2 ****

 

;

00296

; This routine takes the ASCII message pointed to by

;

00297

;

ACCA:IX and displays it on the LCD. This routine uses

;

00298

;

more RAM than TXLCD2 but does have the advantage that the ;

 

00299

;

text message can be anywhere in memory. This routine uses ;

00300

; four bytes of memory (in addition to temp locations) and

;

00301

;

is slighly longer than TXLCD1. The first byte of the

;

00302

; message pointed to should be the control code for place-

;

00303

;

ment of the message in the LCD.

The last byte of the

;

00304

;

message MUST be $00.

 

;

00305

;

00306

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00307

00308

TXLCD2

 

00309

0260

B757

sta

ramSub2

;store ACCA and IX for subroutine jump

00310

0262 BF58

 

stx

ramSub3

00311

0264

BD56

jsr

ramSub1

;use ram subroutine to get byte

 

00312

0266

AD0F

bsr

wclcd

;position LCD

00313

mesloop2

 

00314

0268

3C58

inc

ramSub3

;increment message pointer low byte

00315

026A

2602

bne

noIncHi

;ckeck for overflow, increment high byte of

00316

026C 3C57

 

inc

ramSub2

;necessary

00317

noIncHi

 

00318

026E

BD56

jsr

ramSub1

;get next byte on message

00319

0270

2704

beq

mesLoopDone2

 

00320

0272

AD07

bsr

wdlcd

;check for end of message ($00) ;if not end, write data to LCD

10

Application Note 9702

00321

0274 20F2

 

bra

mesLoop2

00322

mesLoopDone2

00323

0276

81

rts

00324

00325

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00326

;

**** WCLCD ****

 

;

00327

;

This routine takes the contents of ACCA and writes it to ;

00328

;

the LCD as a conrtol byte.

 

;

00329

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00330

00331

0277

1F02

WCLCD

BCLR

RS,LCDCTL

;Pull RS line low for control

00332

0279

2002

BRA

WLCD

;byte write

00333

00334

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00335

;

**** WDLCD ****

 

;

00336

;

This routine takes the contents of ACCA and writes it to ;

00337

;

the LCD as a data byte.

 

;

00338

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00339

00340

027B

1E02

WDLCD

BSET

rs,LCDCTL

;Pull RS line high for data byte write

00341

00342

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

00343

;

**** WLCD ****

 

;

00344

;

This subroutine takes the contents of ACCA and writes it ;

00345

;

to the LCD. This routine polls the LCD busy flag and

;

00346

;

waits until it is low before writing to the LCD. This

;

00347

;

This routine does NOT control the RS bit of the LCD, so

;

00348

; the contents of ACCA may be either display data or

;

00349

; control data. This routine has a conditional assembly

;

00350

; flag "4bit" that controls the LCD interface length. If

;

00351

;

the 4 bit interface is chosen, data is transfered on the

;

00352

;

low nibble of the port.

 

;

00353

;

RAM used:

 

;

00354

;

lcdTemp2 - byte to send

;

00355

;

lcdTemp3 - RS preserved for RCLCD call

;

00356

;

lcdTemp4 - preserved LCD port data

;

00357

;

lcdTemp5 - preserved LCD DDR port data

;

00358

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

00359

00360

00361

WLCD

00362

027D

B751

sta

lcdTemp2

;save data byte in ACCA

00363

027F

B602

lda

lcdctl