Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

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

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

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

Добавлен: 15.06.2025

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

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

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

3. Stored Program Processing 65

the most significant addition becomes the highest bit of the outcome. For example FF FFh + FF FFh = 1 FF FFh (65, 535d + 65, 635d = 131, 070d).

F20h F21h

AUGEND_H AUGEND_L

F24h

F25h

F26h

SUM_H

SUM_M

SUM_L

F22h F23h

ADDEND_H ADDEND_L

Fig. 3.8 The process.

The overall process is diagrammatically shown in Fig. 3.8. However, given that we need to implement the process as a sequence of steps executable by the byte-sized instructions of Table 3.1 then the next step is to produce a task listing.

1.Add the low bytes of the augend and addend, generating the low byte of the sum and carry C1.

F20h F21h

AUGEND_H AUGEND_L

F20h F21h

AUGEND_H AUGEND_L

C1

F22h

F23h

F22h

F23h

ADDEND_H ADDEND_L

C1

C2

ADDEND_H ADDEND_L

F24h

F25h

F26h

F24h

F25h

F26h

SUM_H

SUM_M

SUM_L

SUM_H

SUM_M

SUM_L

(a) Adding the least-significant bytes

(b)

And the most-significant bytes

F20h

F21h

AUGEND_H

AUGEND_L

C2

F22h

F23h

ADDEND_H

ADDEND_L

F24h

F25h

F26h

SUM_H

SUM_M

SUM_L

(c) The most-significant sum byte is the last carry-out

Fig. 3.9 Visualization of the task process.


66The Quintessential PIC Microcontroller

2.Add the high bytes of the augend and addend plus the last carry-out C1 to give the middle byte of the sum and a new carry-out C2.

3.The high byte of the sum is the last carry-out C2, either 0 or 1.

Given that this is our first program of any substance, a detailed visualization of this task list will be useful. For most instances detail at this level is not helpful and subsequently we will use a more abstract visualization known as a flow chart (see Example 3.3).

Once a task list has been established then the next step is to implement this as a sequence of instructions, that is the program. One possible is shown in Program 3.5.

In the listing the three tasks are identified by an appropriate comment.

Task 1

This comprises a Load-Add-Store sequence to add the lower byte of the addend to that of the similarly significant augend. The outcome byte is

Program 3.5 The double-precision add program.

AUGEND_H

equ 020h

AUGEND_L

equ 021h

ADDEND_H

equ 022h

ADDEND_L

equ 023h

SUM_H

equ 024h

SUM_M

equ 025h

SUM_L

equ 026h

STATUS

equ

03

; STATUS flag register

C

equ

0

; The C flag

DP_ADD

clrf

SUM_M

; Zero the 2 upper bytes of the sum

clrf

SUM_H

; Task 1

movf

AUGEND_L,w

; Get LSB of the augend

addwf

ADDEND_L,w

; Add LSB of addend

movwf

SUM_L

; and put it away

; Tasks 2 and 3

btfsc

STATUS,C

; Was there a carry C1?

incf

SUM_M

; IF yes THEN add to middle sum byte

movf

AUGEND_H,w

; Get MSB of the augend

addwf

ADDEND_H,w

; Now add to MSB of the addend

btfsc

STATUS,C

; Was there a carry C2?

incf

SUM_H

; IF so THEN add to high byte sum

addwf

SUM_M,f

; Add the outcome to mid sum byte

btfsc

STATUS,C

; Was there a carry C2 from this?

incf

SUM_H

; IF so THEN add to high sum byte

....

.....

; Next program


3. Stored Program Processing 67

stored in memory at File 26h (SUM_L) and the Carry flag bit (bit 0 in File 3) is set as appropriate to C1.

Task 2

If there was a carry-out from Task 1 then the precleared middle byte of the sum is incremented as the carry-in C1. Then the upper bytes of the addend and augend are added. The final outcome of SUM_M (in File 25h) is determined by adding its current state (00h or 01h) to the outcome of this addition.

Task 3

Either of the two additions in Task 2 can result in a carry-out. The C flag in the STATUS register can be tested after each addition and if set, the upper byte of the sum SUM_H (File 26h) is incremented to add C2, as shown in Fig. 3.8(c). There will not be a carry-out generated by both the Task 2 additions.

Example 3.3

Write a program to divide the byte in the Working register by ten. The quotient is to be in File 20h and the remainder in W.

Solution

Division is the process in finding how many times the divisor (ten in our case) can be subtracted from the dividend without underflowing, that is producing a borrow.

The flow chart shown in Fig. 3.10 outlines the task list to implement our algorithm. Initializing the quotient to −1 means that the subtract and increment loop can begin by incrementing, and this process will continue until a borrow is produced after the subtraction by ten process. A

Program 3.6 Dividing by ten.

QUOTIENT

equ

020h

; Where the quotient will be stored

STATUS

equ

03

; Where STATUS reg. flags are located

DIV_10

clrf

QUOTIENT

; 1: Zero quotient

decf

QUOTIENT,f

; 1: Initial value is -1

DIV_LOOP

incf

QUOTIENT,f

; 2: Increment quotient

addlw

-10

; 3: Subtract ten from dividend

btfsc

STATUS,0

; 4: Leave loop if borrow (bit 0 = 0)

goto

DIV_LOOP

; 4: ELSE repeat increment and subtract

addlw

10

; 5: Add ten to give remainder

.... .....

; Next program


68 The Quintessential PIC Microcontroller

borrow-out indicates that the last subtraction was not successful in that the divisor (i.e. ten) was larger than the residue it was subtracted from. That is the outcome is negative. The loop count on exit represents the number of successful subtractions and thus the quotient.

The coding in Program 3.6 closely follows the flow chart, with comment numbers referring to the statement boxes. The actual subtract constant ten is implemented by adding minus ten! This is because the more obvious sublw 10 instruction actually subtracts W from ten and not ten from W. Notice the mechanism for exiting the loop by testing and skipping if bit 0 in STATUS is clear after this subtraction.

Remembering that bit 0 in File 3 is the Carry flag doubling as the Borrow flag, then a borrow out is indicated if this bit is zero after the subtraction. On exit ten is added back on to compensate for the last unsuccessful subtraction and the outcome then gives the remainder.

Quotient =

-1

LOOP

Increment

quotient

Subtract ten

from dividend

No

Borrow?

Yes

Add ten to give remainder

End

Fig. 3.10 Division by repetitive subtracting.

3. Stored Program Processing 69

Example 3.4

As part of a program to convert degrees Celsius to Fahrenheit it is necessary to multiply the byte in W by nine. Devise a suitable coding.

Solution

There are two ways of multiplying. The fundamental definition of multiplication is repetitive addition, thus we could add the datum nine times to implement our specified function. An alternative approach is the shift and add technique outlined on page 11. Thus the ×9 function is implemented as ×8 +×1. The former is carried out by shifting left three times (i.e. 23). Thus we have:

W × 9 = W × 8 + W × 1 = (W << 3) + W

No matter what technique is used, the outcome by definition will be larger than either the multiplier or multiplicand. In this case we need two bytes. In the coding of Program 3.7 the two memory locations File 20h and File 21h are used to hold the high byte and the low byte respectively of the final 2-byte product. By copying the multiplicand from W to the low byte and clearing the upper byte we make an extended 2-byte version of the multiplicand in Data memory. Shifting left is implemented by using

Program 3.7 Multiplying by nine.

STATUS

equ

3

; STATUS register flags

C

equ

0

; Carry flag is bit0

PRODUCT_H equ 020h

; High byte of the product

PRODUCT_L equ 021h

; Low byte

MUL_9

movwf

PRODUCT_L

; Move the multiplicand to memory

clrf

PRODUCT_H

; Extend it to 2 bytes

; Now shift the double byte multplicand three times to give x8

bcf

STATUS,C

;

Clear carry

rlf

PRODUCT_L,f ;

Shift left low byte of product

rlf

PRODUCT_H,f ;

and

the high byte

bcf

STATUS,C

;

Clear carry

rlf

PRODUCT_L,f ;

Shift left low byte of product

rlf

PRODUCT_H,f ;

and

the high byte

bcf

STATUS,C

;

Clear carry

rlf

PRODUCT_L,f ;

Shift left low byte of product

rlf

PRODUCT_H,f ;

and

the high byte

; Now add the original value giving

x8 + x1 = x9

addwf

PRODUCT_L,f ;

Add

to lower byte

btfsc

STATUS,C

;

and

any carry to the upper byte

incf

PRODUCT_H,f

end


70 The Quintessential PIC Microcontroller

C

0

PRODUCT_L

1 bcf CCR,C

C

2 rlf PRODUCT_L,f

PRODUCT_H

3 rlf PRODUCT_H,f

Fig. 3.11 Double-precision shifting.

the rlf (Rotate Left File) instruction twice, beginning with the lower byte. As well as shifting the byte PRODUCT_L left once, the most significant bit is moved into the Carry flag. Subsequently rotating the contents of the high byte PRODUCT_H moves this Carry in as the new least significant bit and shifts the high byte left as shown in Fig. 3.11. Of course the Carry flag needs to be cleared prior to this process. This 3-instruction double-precision routine is repeated three times to give the required ×8 function. Adding the original multiplicand, which is still in W gives the final ×9 function.

Example 3.5

The circuit diagram of Fig. 3.12 shows a 7-bit pseudo-random number generator (PRNG) based on a shift register with an Exclusive-OR gate feedback. Devise a routine to continually send these 127 binary random numbers to a port located at File 06. The routine must initialize the PRN to any non-zero value.

1D

Data in = B5 + B6

B6 B5 B4 B3 B2 B1 B0

C1 Sample rate

Fig. 3.12 A 7-bit pseudo-random number generator.

3. Stored Program Processing 71

Solution

A suitable task list is:

1.Initialize the number to 01.

2.DO forever.

(a)Rotate shift a copy of the number once left so that bits 5 & 6 are aligned.

(b)Bitwise XOR the number and its shifted copy.

(c)Rotate the outcome twice left to pop out bit 6 into the C flag, which will be B6 B5.

(d)Rotate the original number once left with C becoming the new bit 0.

Program 3.8 A 7-bit pseudo-random number generator.

PORTB

equ

6

NUMBER

equ

0x20

TEMP

equ

0x21

PRNG

movlw

1

; Initial value of random number is 01

P_LOOP

movwf

NUMBER

; Make a copy in memory

rlf

NUMBER,f

; Shift number to align bits 5 & 6

xorwf

NUMBER,f

; Bitwize XOR them

rlf

NUMBER,f

; Shift twice left to put 5XOR6 in Carry

rlf

NUMBER,f

movwf

TEMP,f

; Put original number in memory

rlf

TEMP,w

; >> with carry coming in, and put in W

movwf

PORTB

; and send this new random number out

goto

P_LOOP

; and repeat

The listing in Program 3.8 follows the task list fairly closely. The value of the number is temporarily saved in memory so that it can be processed without altering the original number down in W. This is done by specifying the destination to be the file, eg. rlf NUMBER,f. After rotating left once left, bit 5 in the shifted copy in NUMBER is aligned with the original bit 6 in W. After exclusive ORing the two, with the destination again being in File memory (xorwf NUMBER,f), bit 6 in NUMBER is now B5 B6. Shifting twice left puts this bit in the Carry flag. Finally rotating the original pseudo-random number in W moves that pattern once left with the new least-significant bit being the Carry flag, that is B5 B6 as specified in the diagram. The first 32 hexadecimal values output are:

02 04 08 10 20 41 83 06 0C 18 30 61 C2 85 0A 14