506 pág.

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

generate a complement borrow out, which is represented by the C ﬂag in the Status register – labelled NB for Not Borrow in the program. Thus the loop is exited when the Carry ﬂag 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 ﬁle 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 subwf DIVIDEND,f ; DIVIDEND - DIVISOR 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 ﬁle. 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 eﬀectively 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 ﬂag. 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. THE ESSENCE OF THE PIC MICROCONTROLLER 119 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 ﬂag. Example 5.4 implements a 16-bit− 8-bit sub- traction. 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 ﬂag. 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 ﬁle or a literal) from the contents of the Working register [W]. The outcome gives the actual mag- nitude diﬀerence between the operands, but in most cases it is suﬃcient 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 ﬂags 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 ﬂag represents the complement of the borrow after subtraction and the Z ﬂag is set on a zero outcome. This gives: 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 ﬂag 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 ﬂag. 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 ﬂags in the appropriate way, but which ‘throws away’ the diﬀerence outcome; that is does not overwrite the operand. A type of non-destructive subtract. THE ESSENCE OF THE PIC MICROCONTROLLER 121 be initially set to output. In the same manner the bsf instruction could be used to turn oﬀ 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