Файл: 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’ |