Файл: Microcontroller Programming. Thi Micro Chip PIC (Julio Sanchez, 2007).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 8548
Скачиваний: 0
368 |
Chapter 14 |
Note that the MAX232 and MAX202 consist of two drivers and two receivers per chip. Lines 14 and 7 (labeled D1out and D2out) provide RS-232-C output. Lines 13 and 8 (labeled R1in and R2in) are RS-232-C input. Lines 10 and 11 (labeled D1in and D2in) are TTL (or
CMOS) inputs. Lines 9 and 12 (labeled R2out and R1out) are TTL output. In this designation the letter R stands for receiver and the letter D for driver. The digit 1 indicates the first driver/receiver set and the digit 2 the second one. The lines labeled D are wired to capacitors.
A circuit using the transceiver ICs is simple and easy to build. If a single communication line is required, then the TTL input line can be wired to pin 10 (D2in) and the TTL output to pin 9 (R2out). The RS-232-C input is wired to pin 8 (R2in) and the output to pin 7 (D2out). Later in this section, we present a circuit that uses the MAX202 with a 16F84 PIC.
PIC to PC Communications
Often, a PIC-based circuit has to communicate with a device that conforms to a standard communications protocol. One of the most common cases is a PIC board that interfaces with a computer, usually a PC or Mac with an RS-232-C port. For example, a PIC board is placed somewhere to collect information, such as temperature, pressure, and humidity. Before the internal storage capacity of the PIC board is exhausted, it is connected to a laptop PC and the data is downloaded from the PIC board to the computer. Once this is done, then the local PIC memory is cleared so that new data can be collected and stored. This application, called a data logger, requires some way of transferring data from the PIC-based board to the PC. The
RS-232-C line is often available on the PC end and the required interface hardware and programming is uncomplicated.
On the PC end, the communications software can be off-the-shelf applications or especially developed programs. If the purpose is simply to download data to the PC or send simple commands to the PIC board, then a standard utility is used. For example, the Windows program named Hyper Terminal allows sending and receiving files and commands at various baud rates and RS-232-C communications parameters. Hyper Terminal is included with most Windows versions or can be downloaded free from the developer’s website.
The PIC board must have a system that conforms to the communications protocol of the device, in this case, the PC. In order to use the PC’s serial port, PIC hardware and software must be able to generate required signal levels, baud rate, and other RS-232-C communications parameters. Hardware interfacing is implemented by using a transceiver chip, such as the MAX232 or 202 previously described. If the PIC contains a UART or USART module, then the communications software is easy to develop. This case is explored later in this chapter.
An RS-232-C TTY Board
The terms “teletype” and “teletypewriter” refer to an obsolete electro-mechanical typewriter that was used to send and receive information through a simple communication channel. In a modern sense, TTY refers to a simple style of communications where the same device sends and receives text messages interactively. The current board is actually a TTY receiver since it does not contain a keyboard that allows sending data. Figure 14-13 shows the circuit diagram for an 16F84-based PC-to-PIC serial communications board.
370 |
Chapter 14 |
1.Data must be transmitted and received at one of the standard RS-232-C baud rates. The most often-used baud rates in this case are: 600, 1,200, 2,400, 4,800, 9,600, and 19,200.
2.Data must be formatted according to the protocol’s conventions; that is, a start bit, 5, 6, 7, or 8 data bits, the presence or absence of a parity bit, and 1, 1½, or 2 stop bits.
3.RS-232-C communication data is transmitted and received with the least-signifi- cant-bit first.
The first problem (transmitting and receiving at a standard baud rate) often requires an approximation. The PIC’s instructions execute at the rate of its internal clock, which also determines the rate of its timer module.
The time taken by each counter iteration is obtained by dividing the PIC’s clock speed by four. For example, a PIC running on a 4 Mhz oscillator clock increments the counter every 1 Mhz. The counter register is incremented at a rate of 1µs (assuming no prescaler). If we were to use the unmodified timer rate to measure bit time, the result would be a baud rate of approximately 3,906. Since 3,906 is not a standard baud rate, the timer is adjusted to approximate one of the standard RS-232-C baud rates. For example, at 4,800 baud the time per bit is:
1 |
= 208.33μs. |
|
4,800 |
||
Since the timer of a PIC with a 4 Mhz clock runs at 1 µs per timer iteration, then we could count up from 0 to 208 iterations of the counter in order to approximate the bit time of 208 µs needed at 4,800 baud. In addition, we would have to calculate one-half the bit time since synchronization requires offsetting the timer from the edge to the center of the start bit (see Section 14.3.1). In this case, to delay approximately 104 µs we would count up from 0 to 104.
But counting up is inconvenient with the PIC timer/counter since the signal is produced when the counter reaches its maximum. A better solution is to preset the Timer counter (TMR0) to a calculated value such that the desired time lapse occurs when the Timer register reaches 255. So the actual delays for 4,800 baud are as follows:
DELAY |
CALCULATION |
TMR0 PRESET |
|||
208 |
μs |
255 |
– |
208 |
48 |
104 |
μs |
255 |
– |
104 |
151 |
Once we have obtained the clock rate for a standard baud rate, it is easy to obtain slower standard rates by slowing down the clock with the prescaler. For example, if the prescaler is assigned to the timer/counter register with a bit value of 000, then the counter rate is one-half the unscaled rate. This would produce a baud rate of 2,400 baud. By the same token, assigning a 1:4 prescaler to the timer produces a baud rate of 1,200 baud using the same preset values previously calculated. Faster baud rates are easily calculated by the same method.
Communications |
371 |
Formatting the data transmission according to the RS-232-C protocol presents no major problem. In fact, the communications programs previously listed in this chapter use a start bit to commence character transmission, followed by eight data bits, and one stop bit to end it, with no parity bit. This same format is compatible with RS-232-C.
The third compatibility issue refers to the bit order in RS-232-C, which requires that the low-order bit be transmitted first. In previous applications, we have sent the high-order bit first by rotating the bits left inside the holding register and testing the carry flag. In the RS-232-C routine, the bits are rotated right into the carry flag and then the carry flag is rotated into the storage variable.
The demonstration program for the circuit in Figure 14-13, named TTYUsart, uses a 2-line by 16 character LCD to display the characters received from the PC through the serial line. The program initially sends the test string “Ready-” to the PC to test the data transmission routine and to let the PC user know that the PIC board is ready to receive. The program operates at 2,400 baud, one start bit, eight data bits, no parity, and one stop bit. The communications program on the PC must be set to these parameters.
An LCD Scrolling Routine
LCDs have limited capacity for data display. A 2-line by 16 character LCD fills the screen when 32 characters are displayed. For some applications it is convenient to have a procedure that takes some reasonable action when the LCD screen is full. One approach is to detect when the last character in the second LCD line is displayed, then move the second line to the first line, clear the second line, and continue displaying at the start of the second line. This is the standard screen handling for a computer program.
An LCD screen scroll routine can be called as each character is displayed. For the scroll to work, the program must keep track of the currently selected LCD line (variable LCDline can be 0 for line 1, and 1 for line 2), of the number of characters displayed on that line (variable LCDcount), and of the total capacity of the line
(constant LCDlimit). Given this information, the logic for an LCD line scrolling routine can be as follows:
1.Add current character to LCDcount. If LCDcount is equal to LCD limit then the end of a line was reached. If not, exit routine.
2.If line end reached is for line 1, set current display address to start of line 2. Reset variable LCDcount. Exit routine.
3.If line end reached is for line 2, then copy the characters displayed in line 2 to line 1. Clear line 2. Reset the display address to the start of line 2. Reset LCDline variable to line 2. Reset variable LCD count. Exit routine.
Of these operations, copying the characters from the second line to the first one can be the most troublesome. One possibility is to read the data from the LCD directly. This approach requires that the connection between the PIC and the LCD includes the R/W line. Another option is to create a buffer in RAM and copy each character displayed to this area. In the case of an LCD with 16 characters per line
372 |
Chapter 14 |
the buffer requires a capacity of 16 bytes. Since the line input is “remembered” in the buffer, the program scrolls a line by copying the contents of the buffer to the other line. This alternative does not require reading the LCD and saves implementing the R/W line.
Storing the characters received in a local buffer first requires reserving a 16-byte area (the buffer) in PIC RAM. There are several ways of accomplishing this. A simple one is using the cblock directive, as shown in the following code fragment:
;=====================================================
;buffer and variables in PIC RAM ;=====================================================
;Create a 16-byte storage area
cblock |
0x0c |
; Start of first data block |
lineBuf |
; buffer for text storage |
|
endc |
||
; Leave 16 bytes and continue with local variables; |
||
cblock |
0x1c |
; Second data block |
count1 |
; Counter # 1 |
|
count2 |
; Counter # 2 |
|
. . . other variables can go here endc
In reality, the buffer is most likely accessed by indirect addressing, so a buffer name (lineBuf in this case) is not really necessary. This is due to the fact that PIC assembly language does not contain a directive for finding the address of a variable. So the buffer address has to be hard-coded or defined in a constant. But, in any case, having a buffer name does not cost storage capacity and it may help make the code clearer.
In our design, the scrolling routine depends on finding the characters in the ending line stored in the RAM area mentioned in the preceding paragraph. The buffer locations are accessed directly by referencing the address. For example, the first byte in lineBuf is stored at addres 0x0c, the second one at 0xod, and so on. A more effective way of using a buffer is by creating and keeping a buffer pointer variable that has the current offset from the start of the buffer. The buffer pointer is then added to the buffer’s base address in order to access the current buffer location. Indirect addressing using the FSR and the INDF registers simplify the process, as shown in the following code fragment:
;Store character in local line buffer using indirect
;addressing. Byte to store is in rcvData variable.
;16-byte buffer named lineBuf starts at address 0x0c
;Register variable bufPtr holds offset into buffer
movlw |
0x0c |
; Buffer base address |
|
addwf |
bufPtr,w |
; Add pointer in |
w |
movwf |
FSR |
; Value to index |
register |
movf |
rcvData,w |
; Character into |
w |
movwf |
INDF |
; Store w in [FSR] |
|
incf |
bufPtr,f |
; Bump pointer |
|
Communications |
373 |
The manipulation requires loading the base address of the buffer (0x0c in this case) in the w register, adding the value stored in the buffer pointer variable (bufPtr), and storing the sum in the FSR register. The character is then loaded into the w register and moved into the INDF register, which has the effect of storing it in the address pointed at by FSR. Conventionally, brackets are used to indicate indirect addressing, so [FSR] means the memory location referenced by the FSR register.
Once the line characters are stored locally, all that is left is the design of a line scrolling routine following the processing steps previously listed. The following procedure performs the necessary operations:
;==========================
;scroll LCD line 2 ;==========================
;Procedure to count the number of characters displayed on
;each LCD line. If the number reaches the value in the
;constant LCDlimit, then display is scrolled to the second
;LCD line. If at the end of the second line, then the
;second line is scrolled to the first line and display
;continues at the start of the second line
;reset to the first line.
LCDscroll: |
||
incf |
LCDcount,f |
; Bump counter |
; Test for line limit |
||
movf |
LCDcount,w |
|
sublw |
LCDlimit |
; Count minus limit |
btfss |
STATUS,z |
; Is count - limit = 0 |
goto |
scrollExit |
; Go if not at end of line |
;At this point the end of the LCD line was reached
;Test if this is also the end of the second line movf LCDline,w
sublw |
0x01 |
; Is it |
line 1? |
|
btfsc |
STATUS,z |
; Is LCDline minus 1 = 0? |
||
goto |
line2End |
; Go if |
end |
of second line |
; At this point it is the end of the top LCD line |
||||
call |
line2 |
; Scroll to |
second line |
|
clrf |
LCDcount |
; Reset |
counter |
|
incf |
LCDline,f |
; Bump line |
counter |
|
goto |
scrollExit |
|||
;End of second LCD line line2End:
;Scroll second line to first line. Characters to be
;scrolled are stored in buffer starting at address 0x0c.
;16 characters are to be moved
;First clear LCD
call initLCD
call |
delay_5 |
; Make sure not busy |
; Set up for data
374 |
Chapter 14 |
||
bcf |
PORTA,E_line |
; E line low |
|
bsf |
PORTA,RS_line |
; RS line high for data |
|
; Set up counter for 16 characters |
|||
movlw |
D’16’ |
; Counter = 16 |
|
movwf |
count2 |
||
; Get address of storage buffer |
|||
movlw |
0x0c |
||
movwf |
FSR |
; W to FSR |
|
getchar: |
|||
movf |
INDF,w |
; get character from display RAM |
|
; location pointed to by file select |
|||
; register |
|||
call |
send8 |
; 4-bit interface routine |
|
; Test for 16 characters displayed |
|||
decfsz |
count2,f ; Decrement counter |
||
goto |
nextchar ; Skipped if done |
||
; At this point scroll operation has concluded |
|||
clrf |
LCDcount ; Clear counters |
||
; Stay at line 2 |
|||
clrf |
LCDline |
||
incf |
LCDline,f |
||
call |
line2 |
; Set for second line |
|
scrollExit: |
|||
return |
|||
nextchar: |
|||
incf |
FSR,f |
; Bump pointer |
|
goto |
getchar |
||
;============================
;clear line buffer ;============================
;Use indirect addressing to store 16 blanks in the
;buffer located at 0x0c
blankBuf: |
||
Bank0 |
||
movlw |
0x0c |
; Pointer to RAM |
movwf |
FSR |
; To index register |
blank16: |
||
clrf |
INDF |
; Clear memory pointed at by FSR |
incf |
FSR,f |
; Bump pointer |
btfss |
FSR,4 |
; 000x0000 when bit 4 is set |
; count reached 16 |
||
goto |
blank16 |
|
return |
||
;======================== |
||
;Set address register
;to LCD line 1 ;========================
;ON ENTRY: