Файл: Microcontroller Programming. Thi Micro Chip PIC (Julio Sanchez, 2007).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 14.06.2025

Просмотров: 8608

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

LCD Interfacing and Programming

295

pacity of the PIC hardware. The actual instruction speed is determined by the clocking device, so a 20 MHZ 16f84A using a 4 MHz oscillator effectively runs at 4 MHz.

Pulsing the E Line

The LCD hardware does not recognize data as it is placed in the input lines. When the various control and data pins of the LCD are connected to ports in the PIC and data is placed in the port bits, no action takes place in the LCD controller. In order for the controller to respond to commands or to perform read or write operations, it must be activated by pulsating (or strobing) the E line. The pulsing or strobing mechanism requires that the E line be kept low and then raised momentarily. The LCD checks the state of its lines on the raising edge of the E line. Once the command has completed, the E line is brought low again. The following code fragment pulses the E line in the manner described.

;========================

; pulse E line

;========================

pulseE

bsf

porta,E_line

;

pulse

E line

bcf

porta,E_line

call

delay_125mics

;

delay

125 microseconds

return

Note that the listed routine includes a 125µs delay following the pulsing operation. This delay is not part of the pulse function but is required by most LCD hardware. Some pulse functions in the popular PIC literature include a no operation opcode (nop) between the commands to set and clear the E line. In most cases this short delay does not hurt, but some LCDs require a minimum time lapse during the pulse and will not function correctly if the nop is inserted in the code.

Reading the Busy Flag

Synchronization between LCD commands and between data access operations is based on time delay loops or on reading the LCD busy flag. The busy flag, which is in the same pin as the bit 7 data line, is read clear when the LCD is ready to receive the next command, read, or write operation and is set if the device is not ready. By reading the state of the busy flag, code can accomplish more effective synchronization than with time delay loops. The sample program named LCDTest2, in the book’s online software package, performs LCD display using the busy flag method. The following procedure shows busy flag synchronization:

;========================

;busy flag test routine ;========================

;Procedure to test the HD44780 busy flag

;Execution returns when flag is clear busyTest:

movlw

b’11111111’

;

All lines to input

tris

portb

; in port B

bcf

porta,RS_line

;

RS line low for control


296

Chapter 13

bsf

porta,RW_line

; Read mode

bsf

porta,E_line

; E line

high

movf

portb,w

; Read port

B into W

; Port B

bit 7 is busy flag

bcf

porta,E_line

; E line

low

andlw

0x80

; Test bit 7, high is busy

btfss

status,z

; Test zero

bit in STATUS

goto

busyTest

; Repeat

if

set

;At this point busy flag is clear

;Reset R/W line and port B to output

bcf

porta,RW_line

;

Clear R/W

line

movlw

b’00000000’

;

All lines

to output

tris

portb

; in port B

return

Note that testing the busy flag requires setting the LCD in read mode, which in turn requires implementing a connection between a PIC port and the R/W line. Also that the listed procedure contains no safety mechanism for detecting a hardware error condition in which the busy flag never clears. If such were the case, the program would hang in a forever loop. To detect and recover from this error the routine would have to include an external timing loop or some other means of recovering a possible hardware error.

Bit Merging Operations

Often, PIC/LCD circuits do not use all of the lines in an individual port. In this case the routines that manipulate PIC/LCD port access should not change the settings of other port bits. This situation is not exclusive to LCD interfacing; the discussion that follows has many other applications in PIC programming.

A processing routine can change one or more port lines without affecting the remaining ones. For example, an application that uses a 4-bit interface between the PIC and the LCD typically leaves four unused lines in the access port, or uses some of these lines for interface connections. In this case, the programming problem can be described as merging bits of the data byte to be written to the port and some existing port bits. One operand is the access port value and the other one is the new value to write to this port. If the operation at hand uses the four high-order port bits, then its four low-order bits must be preserved. The logic required is simple: AND the corresponding operands with masks that clear the unneeded bits and preserve the significant ones, then OR the two operands. The following procedure shows the required processing:

;=================

;merge bits ;=================

;Routine to merge the 4 high-order bits of the

;value to send with the contents of port B

;so as to preserve the 4 low-bits in port B

;Logic:

;AND value with 1111 0000 mask


LCD Interfacing and Programming

297

;AND port B with 0000 1111 mask

;At this point low nibble in value and high

;nibble in port B are all 0 bits:

;

value = vvvv 0000

;

port B = 0000 bbbb

;OR value and port B resulting in:

;

vvvv bbbb

;ON ENTRY:

;w contain value bits

;ON EXIT:

;w contains merged bits

merge4:

andlw

b’11110000’

; ANDing with

0 clears

the

; bit. ANDing

with 1 preserves

; the original value

movwf

store2

; Save result

in variable

movf

portb,w

; port B to w

register

andlw

b’00001111’

; Clear high nibble in

port b

; and preserve low nibble

iorwf

store2,w

; OR two operands in w

return

Note that this particular example refers to merging two operand nibbles. The code can be adapted to merge other size bit-fields by modifying the corresponding masks. For example, the following routine merges the high-order bit of one operand with the seven low-order bits of the second one:

;Routine to merge the high-order bit of the first operand with

;the seven low-order bits of the second operand

;ON ENTRY:

;w contains value bits of first operand

;port b is the second operand

merge1:

andlw

b’10000000’

; ANDing

with

0 clears the

; bit. ANDing

with 1 preserves

; the original value

movwf

store2

; Save result

in variable

movf

portb,w

; port B

to w

register

andlw

b’01111111’

; Clear high-order bit in

; port b

and preserve the

; seven low order bits

iorwf

store2,w

; OR two

operands in w

return

Popular PIC literature describes routines to merge bit fields by assuming certain conditions in the destination operand, then testing the first operand bit to determine if the assumed condition should be preserved or changed. This type of operation is sometimes called “bit flipping,” for example:


298

Chapter 13

flipBit7:

;Code fragment to test the high-order bit in the variable named

;oprnd1 and preserve its status in the register variable portb

bcf

portb,7

; Assume oprnd1 bit

is

reset

btfsc

oprnd1,7

; Test operand bit and

skip if

;

clear (assumption

valid)

bsf

portb,7

;

Set bit if necessary

return

The logic in bit-flipping routines contains one critical flaw: if the assumed condition is false then the second operand is changed improperly, even if for only a few microseconds. However, the incorrect value can produce errors in execution if it is used by another device during this period. Since there is no such objection to the merge routines based on masking, the programmer should always prefer them.

13.3.4 Text Data Storage and Display

Text display operations require some way of generating the ASCII characters that are to be stored in DDRAM memory. Although the PIC Assembler contains several operators to generate ASCII data in program memory, there is no convenient way of storing a string in the General Purpose register area. Even if this was possible, SRAM is typically in short supply and text strings gobble up considerable data space.

Several possible approaches are available. The most suitable one depends on the total string length to be generated or stored, whether the strings are reused in the code, and other program-related circumstances. In this sense, short text-strings can be produced character-by-character and sent sequentially to DDRAM memory by placing the characters in the corresponding port and pulsing the E line.

The following code fragment consecutively displays the characters in the word

“Hello.” Code assumes that the command to set the Address register has been entered previously:

; Generate characters and send directly to DDRAM

movlw

‘H’

; ASCII for H in w

movwf

portb

; Store code in port B

call

pulseE

; Pulse E line

movlw

‘e’

; Continues

movwf

portb

call

pulseE

movlw

‘l’

movwf

portb

call

pulseE

movlw

‘l’

movwf

portb

call

pulseE

movlw

‘o’

movwf

portb

call

pulseE

call

delay_5


LCD Interfacing and Programming

299

Note in the preceding fragment, the code assumes that the LCD has been initialized to automatically increment the Address register left-to-right. For this reason, the Address register is bumped to the next address with each port access.

Generating and Storing a Text String

An alternative approach suitable for generating and displaying longer strings consists of storing the string data in a local variable (sometimes called a buffer) and then transferring the characters, one by one, from the buffer to DDRAM. This kind of processing has the advantage of allowing the reuse of the same string and the disadvantage of using up scarce data memory. The logic for one possible routine consists of first generating and storing in PIC RAM the character string, then retrieving the characters from the PIC RAM buffer and displaying them. The character generation and storage logic is shown in Figure 13-5.

START

Buffer pointer = 0

Get character using generator

YES

Character = 0

END

?

NO

Store character in buffer

Bump buffer pointer

Figure 13-5 Flowchart for String Generation Logic

The processing is demonstrated in the following procedure.

;===============================

;first text string procedure ;=============================== storeMN:

;Procedure to store in PIC RAM buffer the message

;contained in the code area labeled msg1

;ON ENTRY:

;variable pic_ad holds address of text buffer

;in PIC RAM

300

Chapter 13

;w register hold offset into storage area

;msg1 is routine that returns the string characters

;and a zero terminator

;index is local variable that hold offset into

;text table. This variable is also used for

;temporary storage of offset into buffer

;ON EXIT:

;Text message stored in buffer

;

;Store offset into text buffer (passed in the w register)

;in temporary variable

movwf

index

; Store w in index

; Store base address of text buffer in fsr

movf

pic_ad,w ;

first display RAM address to W

addwf

index,w

;

Add offset to address

movwf

fsr

;

W to FSR

; Initialize index for text string access

movlw

0

;

Start at 0

movwf

index

;

Store index in variable

; w still = 0

get_msg_char:

call

msg1

;

Get character from table

; Test for zero terminator

andlw

0x0ff

btfsc

status,z ;

Test zero flag

goto

endstr1

;

End of string

;ASSERT: valid string character in w

;store character in text buffer (by fsr)

movwf

indf

; store in buffer by fsr

incf

fsr,f

; increment buffer pointer

; Restore table character counter from variable

movf

index,w

; Get value into w

addlw

1

; Bump to next character

movwf

index

; Store table index in variable

goto

get_msg_char

; Continue

endstr1:

return

; Routine for returning message stored in program area msg1:

addwf

PCL,f

; Access table

retlw

‘M’

retlw

‘i’

retlw

‘n’

retlw

‘n’

retlw

‘e’

retlw

‘s’

retlw

‘o’

retlw

‘t’