A maior rede de estudos do Brasil

506 pág.
Quintessential PIC Microcontroller

Pré-visualização | Página 35 de 50

generate a complement borrow
out, which is represented by the C flag in the Status register – labelled NB
for Not Borrow in the program. Thus the loop is exited when the Carry
flag is clear after the subtract, which represents a borrow out.
On leaving the loop, the contents of File 20h needs to be decremented,
as the last subtract was one too many. Using the decf instruction allows
this correction to be applied directly on the file register.
118 The Quintessential PIC Microcontroller
Program 5.3 Division by repetitive subtraction.
STATUS equ 3 ; Status register is File 3
NB equ 0 ; Carry/Not Borrow flag is bit0
QUOTIENT equ 20h ; Quotient is held in File 20h
REMAINDER equ 21h ; The remainder is put here
DIVIDEND equ 24h ; The dividend is here at the start
DIV clrf QUOTIENT ; Zero the loop count
LOOP incf QUOTIENT,f ; Record one loop pass
btfsc STATUS,NB ; IF a borrow (NB==0) THEN exit loop
goto LOOP ; ELSE do another subtract/count
decf QUOTIENT,f ; Compensate for one inc too many
addwf DIVIDEND,w ; Add divisor to residue
movwf REMAINDER ; which gives the remainder
..... ...... ; Next routine
The remainder can be determined from the residue left in the original
dividend file. This represents one divisor subtracted too many. Thus,
addwf DIVIDEND,w cancels this last action and this remainder outcome,
now in W, is copied into File 21h.
The addlw instruction can be used to add an 8-bit constant to W.
Subtraction can also be carried out with this instruction by adding the
2’s complement of the literal subtrahend. For example. addlw F9h or
addlw -7 will effectively subtract seven from the contents of W. Thus if
[W] was 88h before this operation then the state of W after is 81h:
1000 1000 W = 88h
+ 1111 1001 −7 = F9h
1000 0001 81h
Rather confusingly this is not the same as sublw 7 as this subtracts
W from 7, that is [W] <- 7-[W].3
Although the arithmetic instructions act on byte operands, operations
on word sizes of greater than 8-bit precision are possible with the help
of the Carry/Not-Borrow flag. The process for the addition of two n-byte
objects is given by the task list:
1. For = 0 to n− 1 DO
(a) Clear SUM.
(b) SUM[i] = NUM1[i]+ NUM2[i].
(c) IF Carry[i] = 1 THEN increment SUM[i+1].
(d) Increment i.
2. End.
3This foible is a major cause of errors in programming, and you should think carefully
before using this instruction.
Example 3.2 on page 64 gives a practical implementation of this algo-
rithm. Multiple-precision subtraction is carried out in a similar manner,
using the Not-Borrow flag. Example 5.4 implements a 16-bit− 8-bit sub-
Data in memory can be incremented or decremented apparently in
situ, although in reality it is transferred from the Data store into a tempo-
rary register, incremented or decremented using the ALU and transferred
back to the Data store – a type of read-modify-write action. However, it
still takes only one bus cycle to implement.
These instructions are especially useful in counting passes through a
loop, as in Program 5.3 where QUOTIENT is located in the Data store at
File 20h. However, incf is not quite the same as a addlf 1,20h type of
instruction as it does not alter the state of the Carry flag. Thus if you
wanted to increment a 32-bit number in Data memory at File 22:3:4:5h
then this is how you would have to do it:
QP_INC incf 22h,f ; Increment byte 1
btfss STATUS,Z ; IF not overflowed to zero
goto NEXT ; THEN finished
incf 23h,f ; Increment byte 2
btfss STATUS,Z ; again IF not overflowed to zero
goto NEXT ; THEN finished
incf 24h,f ; Increment byte 3
btfss STATUS,Z ; IF not overflowed to zero
incf 25h,f ; increment byte 4
NEXT ..... ...... ; Next code fragment
This depends on the algorithm IF when byte n is incremented it wraps
around from FFh to zero THEN increment byte n+1. See Example 5.1 for
a multiple-precision decrement routine.
One of the more important operations is the comparison of the magni-
tude of the two numbers. Mathematically this can be done by subtracting
the datum (designated [f] for either a register file or a literal) from the
contents of the Working register [W]. The outcome gives the actual mag-
nitude difference between the operands, but in most cases it is sufficient
to determine the relative magnitude of the quantities – eg. is W higher
than the datum? This is determined by checking the state of the C and Z
flags in the Status register.
Working register higher than datum . . . . . . . . . . . . . . . .No borrow, non-zero
Working register equal to datum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Zero
Working register lower than datum . . . . . . . . . . . . . . . . . . . . .Borrow, non-zero
In terms of our processor, the C flag represents the complement of the
borrow after subtraction and the Z flag is set on a zero outcome. This
120 The Quintessential PIC Microcontroller
[W] Higher than or equal [f] : [W]−[f] gives no borrow; (C = 1).
[W] Equal to [f] : [W]−[f] gives Zero; (Z = 1).
[W] Lower than [f] : [W]−[f] gives a borrow; (C = 0).
Consider as an example a fuel tank with a capacity of 255 liters, with a
sensor at the bottom of the tank indicating the remaining volume of fuel
as a linear function of pressure. Assume that the sensor represents the
capacity as a byte that can be accessed at Port B (see page 95), which we
give the name FUEL. We wish to write a routine that will light an ‘empty’
light (at bit 0 at Port A) if the capacity is below 20 liters and ring an alarm
buzzer (bit 1 at Port A) if below 5 liters. Both output peripherals are active
on logic 0. This is how it could be coded:
STATUS equ 3 ; File 3 is the Status register
C equ 0 ; Bit0 is the Carry flag
Z equ 2 ; and bit2 is the zero flag
FUEL equ 6 ; File 6 is Port B
DISPLAY equ 5 ; File 5 is Port A
LAMP equ 0 ; Bit0 of which is the warning lamp
BUZZER equ 1 ; and bit1 is the buzzer
ALARM movf FUEL,w ; Read fuel gauge into W
addlw -5 ; W-5 to compare. IF C==1 THEN
btfss STATUS,C ; no borrow & FUEL HIGHER OR SAME
bcf DISPLAY,BUZZER ; and sound buzzer
movf FUEL,w ; Get fuel gauge again into W
addlw -14h ; W-20 to compare. IF C==1 THEN
btfss STATUS,C ; no borrow & FUEL HIGHER OR SAME
bcf DISPLAY,LAMP ; and light lamp
NEXT: ..... ..... ; Continue
After each subtraction the Carry/borrow flag will be logic 1 (that is no
borrow) if the datum in the Working register (the fuel reading) is higher
or the same as the literal being subtracted – it is being compared with.
The addlw -k instruction can be replaced by the more obvious sublw k.4
Remembering that this subtracts W from the constant, that is k− W, then
the following Skip on Set (btfss) instructions must be replaced by Skip
on Clear (btfsc) to give the same sense of magnitude.
The contents of the Working register can be tested for zero in the
same way, that is addlw 0 or sublw 0. If W were zero then the outcome
of this tstw type of instruction will set the Z flag. We have already seen
that the instruction movf xx,f can be used in the same way as a tst f
instruction to test File xx for zero. Note the use of the bcf (Bit Clear in
File) instruction to clear the appropriate bit in Port A, which we assume to
4The Compare instruction of most MPU/MCUs is a subtract which sets the flags in
the appropriate way, but which ‘throws away’ the difference outcome; that is does not
overwrite the operand. A type of non-destructive subtract.
be initially set to output. In the same manner the bsf instruction could
be used to turn off the lamp and buzzer at the beginning of the routine,
as shown on page 125.
Logic and Shifting instructions
All four basic logic operations are provided, as shown in Table 5.3. The
simplest of these is comf which inverts (or 1’s