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

Communications

369

RESET

DB-9 (female)

5 4 3 2 1

9

8

7

6

0.1mF

0.1mF

0.1mF

+5V

R/W

RS

R=10K

1

18

E

RA2

RA1

2

17

RA3

RA0

3

16

4

RA4/TOCKI

OSC1

15

MCLR

OSC2

5

16F84

14

+5V

PB SW1

Vss

Vdd

+5V

6

RB0/INT

RB7

13

R=10K

7

12

RB1

RB6

8

RB2

RB5

11

9

RB3

RB4

10

0.1mF

+

+

1

16

C1+

Vcc

+

2

15

GND

V+

3

14

T1out

C1-

4

MAX202

R1in

13

+5V

+

C2+

+5V

5

12

R1out

C2-

6

11

T1in

V-

7

T2out

T2in

10

1

9

8

R2in

R2out

+

0.1mF

Osc 4Mhz

LCD

2 rows x 16

14

RS

E

R/W

HD44780

Figure 14-13 PC-to-PIC Serial Communications Circuit

The circuit in Figure 14-13 contains previously discussed components. The LCD is wired in 4-bit mode, with control lines for RS (reset), E (pulse), and R/W (read/write). The MAX202 provides the TTL-to-RS-232-C conversion and vice versa. The physical connection between the PC and the PIC board is by means of a DB-9 connector and a standard null modem cable. The cable is not shown in the circuit diagram.

A 16F84A UART Emulation

The 16F84A PIC contains no built-in facilities for RS-232-C communications. Therefore, a 16F84A application that communicates through the serial port using the RS-232-C protocol must emulate the protocol in software. The programs previously developed for PIC-to-PIC communications, discussed in Section 14.3.1, serve as a base for the UART emulation application. The major differences between a “free style” PIC communications program and one that complies for RS-232-C are the following:


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: