Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 5336
Скачиваний: 0
112 The Quintessential PIC Microcontroller
TEMP[i] - MAXIMUM
skip |
No |
btfss |
STATUS,NB |
|||
Borrow? |
goto |
NEXT |
||||
(TEMP[i]>=MAXIMUM) |
{MAXIMUM=TEMP[i]} |
|||||
NEXT
MAXIMUM = TEMP[i]
Yes (TEMP[i]<MAXIMUM) goto
NEXT
Fig. 5.3 The ith section of the compare-update sequence.
ment in the temperature array is tested each time. A much more e cient approach is to execute this sequence inside a loop and use an advancing pointer to target Temp[i] as the process unfolds. This technique leads to the task list:
1.Clear Maximum.
2.Point to Temp[0] (i = 0).
3.DO
(a)IF Temp[i] > Maximum THEN Maximum = Temp[i].
(b)Increment i.
(c)Repeat WHILE i < 24.
4.End.
The implementation of Program 5.2 uses the same compare-update sequence, but this time with the Indirect address mode to access the data byte Temp[i]. The contents of the File Select Register here holds the address of Temp[i] and is initialized in Task 2. After each loop pass, this pointer is incremented and then compared by subtraction from the first address beyond the array; that is TEMP_0 + 24. If they are equal then the Z flag will be set and the goto LOOP instruction skipped over out of the loop.
This Indirect mode coding takes 14 instructions; that is 10% of the linear version. However, it does take rather longer to execute, due to the overhead of incrementing the pointer1 and checking for range on each
1The PIC 17CXXX and 18CXXX series have auto incrementing and decrementing versions of Indirect addressing and more than one Indirect pointer register.
THE ESSENCE OF THE PIC MICROCONTROLLER 113
Program 5.2 Finding the maximum temperature using a loop structure.
INDF |
equ |
0 |
; INDirect File register |
STATUS |
equ |
3 |
; Status register is File 3 |
FSR |
equ |
4 |
; File Status Register |
TEMP_0 |
equ |
30h |
; Array starts @ File 30h |
MAXIMUM |
equ |
48h |
; Maximum value to be in File 48h |
Z |
equ |
2 |
; Zero flag is bit2 of STATUS |
NB |
equ |
0 |
; Carry/Not Borrow flag is bit0 |
; Task1: Clear maximum |
|||
MAX_DAILY |
clrf |
MAXIMUM |
|
; Task2: Point to Temp[0] |
|||
movlw |
TEMP_0 |
; Put address of first temp byte |
|
movwf |
FSR |
; in the pointer register |
|
;Task3: DO
;Task3A: IF Temp[i] > Maximum THEN Maximum = Temp[i]
LOOP |
movf |
MAXIMUM,w |
; Get current maximum temperature |
subwf |
INDF,w |
; Temp[i] - Maximum |
|
btfss |
STATUS,NB |
; IF no borrow (NB==1) THEN update |
|
goto |
NEXT |
; Skip update |
|
movf |
INDF,w |
; Update by getting Temp[i] |
|
movwf |
MAXIMUM |
; which is the new maximum |
|
; Task3B: Increment i |
|||
NEXT |
incf |
FSR,f |
; i++ |
; Task3C: REPEAT WHILE i < |
24 |
||
movf |
FSR,w |
; Get pointer address |
|
sublw |
TEMP_0+18h |
; Take away end address (Temp[24]) |
|
btfss |
STATUS,Z |
; IF equal THEN end |
|
goto |
LOOP |
; ELSE repeat |
|
; Task4: END
loop pass. The worst-case run time is 291 µs against 188 µs, assuming a 4 MHz crystal.
One advantage of the Indirect address mode is that the pointer address is eight bits wide. Thus it is not necessary to use the RP0 bit to switch between Bank 0 and Bank 1 of the Data store. The full 14-bit core model allows for four 128-byte banks of register files. The Status register of Fig. 5.1 shows the IRP (Indirect Register Page) bit which is used for family members with three or four register file banks. In such a device, if the temperature array of Program 5.2 were located in File 130h through File 147h then IRP would need to be set to 1 at the beginning of the routine (bsf STATUS,7) and cleared at the end. The rest of the code is unaltered. Microchip recommend that the IRP (and RP1) bits in
114 The Quintessential PIC Microcontroller
the Status register are left in their zero reset state in family members, such as the PIC16F84, that do not have data storage above Bank 1.
Bit
01 ?? nnn f
Four instructions (as specified by the two ?? bits above) either alter or test the state of a single bit within a register file. In this situation the instruction word has an embedded 3-bit code nnn defining the bit number from 0 through 7, as well as the file address coded in the normal way. Thus the instruction bcf 20h,7 (Bit Clear bit 7 in File 20h) is coded as 01 00 111 0100000. The other instructions are bsf (Bit Set in File, coded as 01), btfsc (Bit Test File and Skip if Clear, coded as 10) and btfss (Bit Test File and Skip if Set, coded as 11).
Absolute
10 ? aaaaaaaaaaa
Two instructions allow the program to jump to another instruction anywhere in the Program store. These are goto and call (CALL or goto a subroutine, see Chapter 6). The 14-bit core allocates eleven bits of the instruction word to this absolute instruction address2 in the Program store. Thus goto 400h would be coded as 10 1 10000000000. Similarly call 530h is 10 0 10100110000.
12 11 |
0 |
Program Countera a a a a a a a a a a
goto aaaaaaaa
7 |
4 |
3 |
0 |
PCLATH
File 0Ah
Fig. 5.4 Generating a 13-bit Program-store address for the goto and call instructions.
This 11-bit address can directly locate any instruction in a Program store of up to 211 = 2 Kbyte capacity. However, the mid-range core has
2Don’t confuse this with the register file address in the Data store – in the Havard structure the two stores are logically distinct with di erent address spaces.
THE ESSENCE OF THE PIC MICROCONTROLLER 115
a 13-bit Program Counter which can potentially address a Program store of up to 8 Kbyte instructions; for example the PIC16C74 has a 4 Kbyte store. To cope with this situation, when a goto or call instruction is executed, the absolute 11-bit address is transferred into the PC together with bits 3:4 of the PCLATH (Program Counter LATch High) to make up an e ective 13-bit Program-store address. This process is shown in Fig. 5.4
– see also Fig. 4.3 on page 86.
PCLATH is cleared on Reset, so the goto range is normally 000 – 7FFh. This covers all the address range for a 2 Kbyte store. For members with larger Program stores then a far goto and far call (i.e. beyond 7FFh) has to be implemented by twiddling bits PCLATH[4:3]. For example, in the PIC16C74 a goto 800h is coded as:
bsf |
PCLATH,3 |
; |
Make PCLATH(4:3) = 01 |
bcf |
PCLATH,4 |
||
goto |
800h |
; |
Go to it! |
So far we have classified instructions by the method they pin-point their operands. The alternative approach is to catalog the instruction set by function. On this basis the 14-bit core PIC’s instruction set can conveniently be divided into six groups, of which four will be examined here. Those relevant to subroutines and interrupts are listed in the next two chapters, and control instructions pertaining to internal operation of the MCU hardware are left to Chapter 10. The complete instruction set is given for reference in Appendix A on page 475.
Movement instructions
Around one in three instructions move data around without alteration. With this in mind the instructions in Table 5.1 will be the most used in the repertoire.
All three Move instructions can copy byte data to or from the Working register.
Table 5.1: Move instructions.
Flags |
||||||||
Operation |
Mnemonic |
Z |
DC |
C |
Description |
|||
Move |
• |
• |
• |
Copies a datum byte |
||||
Literal to W |
movlw |
k |
[W] <- #kk |
|||||
File |
movf |
f,d |
√ |
• |
• |
[d] <- [f] |
||
W to file |
movwf |
f |
• |
• |
• |
[f] <- [W] |
||
Swap |
• |
• |
• |
Interchanges file nybbles |
||||
File |
swapf |
f,d |
[d] <- [F(3:0)][F(7:4)] |
|||||
• Flag not a ected W Working register [ ] Contents of
#kk 8-bit constant
√ Flag operates in the normal way
fFile register
dDestination, W or a file register
116 The Quintessential PIC Microcontroller
•movlw copies the specified 8-bit constant (or literal) to W. For example, movlw 80h initializes W to 10000000b. This instruction only a ects the Working register and thus cannot be used directly to set up a file register to a constant value.
•movwf is used to copy out or store the contents of W into a register file. For example, the following code fragment will initialize the contents of
File 22h to 80h:
movlw 80h ; Set contents of W to 80h movwf 22h ; and copy to File 22h
•movf can copy (or load) the contents of any register file into W. For example, movf 22h,w loads W with the contents of File 22h.
The destination of this instruction can also be the file itself, giving rise to seemingly useless instructions, such as movf 22h,f which copies the contents of File 22h back on top of itself! However, the process does activate the Z flag, which will be set if the file contents are zero, and of course this datum is not a ected by the instruction. Thus movf FILE,f is equivalent to the missing tstf FILE instruction; that is TeST File for zero, that is commonly available in other MPU/MCUs. Thus the contents of any file register can be checked for zero by this means using a single instruction. An alternative technique needs to be used to test the contents of the Working register for zero.
Given that most instructions acting on a file can specify either the same file or the Working register as the destination, then a Move operation can be considered an implicit part of such instructions. As an example, for some situations to increment the contents of a file and then move it to W could be coded either as:
incf |
22h,f |
; |
Increment File 22h’s contents |
movf |
22h,w |
; |
and copy it into W |
or
incf 22h,w ; Copy the incremented File 22h’s contents to W
Of course the latter does not actually change the state of the file.
The final instruction swapf swaps the top and bottom 4-bit nybbles in a file. Thus, for example, if File 22h was 1001 0111b then swapf 22h,f will yield 0111 1001b. If desired, the outcome destination could be specified as W, eg. swapf 22h,w. As swapf does not a ect any flag, this latter form can be used as a transparent replacement for movf 22h,w which does alter the Z flag. Of course it does interchange the two nybbles in the process. Program 7.2 on page 183 shows this swap instruction used in this role.
Arithmetic
The PIC processors implement the normal byte-sized binary Add and Subtract instructions, as discussed on page 47, to add or subtract register
THE ESSENCE OF THE PIC MICROCONTROLLER 117
file contents to/from the Working register. In addition the W register may be added to or subtracted from an 8-bit constant.
Table 5.2: Arithmetic.
Flags |
||||||||||
Operation |
Mnemonic |
Z |
DC |
C |
Description |
|||||
Add |
√ |
√ |
√ |
Binary addition |
||||||
Literal to W |
addlw k |
[W] <- [W] + #kk |
||||||||
W to File |
addwf f,d |
√ |
√ |
√ |
[d] <- [W] + [f] |
|||||
Clear |
√ |
Zeroes destination byte or bit |
||||||||
File |
clrf |
f |
• |
• |
[f] <- #00 |
|||||
W |
clrw |
√ |
[W] <- #00 |
|||||||
• |
• |
• |
||||||||
Bit |
bcf |
f,n |
• |
• |
[fn] <- #0 |
|||||
Decrement |
√ |
• |
• |
Subtract one, produce no borrow |
||||||
File |
decf |
f,d |
[f] <- [f] - #01 |
|||||||
Increment |
√ |
• |
• |
Add one, produce no carry |
||||||
File |
incf |
f,d |
[f] <- [f] + #01 |
|||||||
Set |
• |
• |
• |
Sets any bit in a file to one |
||||||
Bit |
bsf |
f,n |
[fn] <- #1 |
|||||||
Subtract |
√ |
√ |
√ |
Binary subtraction |
||||||
W from literal |
sublw k |
[W] <- #kk - [W] |
||||||||
W from File |
subwf f,d |
√ |
√ |
√ |
[d] <- [f] - [W] |
|||||
#0 |
Single zero bit |
#1 |
Single one bit |
|||||||
#00 |
Zero byte |
#01 |
Byte 01h |
|||||||
#kk |
8-bit constant |
n |
3-bit bit specifier 0 – 7 |
|||||||
fn |
Bit n of file |
|||||||||
As an example that uses most of the instructions in Table 5.2 consider the problem of dividing the contents of File 24h by an 8-bit divisor in W. The simplest way of doing this is to continually subtract the divisor from the dividend, keeping a count until a borrow is generated. The residue left after this last subtraction is the remainder with one divisor subtraction to many. Thus adding the divisor once can restore the remainder if this is needed.
A possible implementation based on this approach is given in Program 5.3. Here the quotient is cleared before entering the loop, using the clrf instruction. The loop itself simply increments the quotient using the incf instruction and then subtracts W (the divisor) from File 24h – subwf 24h,f. Both Subtract instructions 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 |
||||
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 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 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 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.
THE ESSENCE OF THE PIC MICROCONTROLLER 119
Example 3.2 on page 64 gives a practical implementation of this algorithm. Multiple-precision subtraction is carried out in a similar manner, using the Not-Borrow flag. Example 5.4 implements a 16-bit − 8-bit subtraction.
Data in memory can be incremented or decremented apparently in situ, although in reality it is transferred from the Data store into a temporary 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 magnitude 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 magnitude 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 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 gives: