Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 5356
Скачиваний: 0
CHAPTER 5
The Instruction Set
If you like to think of writing a program as analogous to preparing an elaborate meal, then for any given cooking appliance, such as a microwave oven or electric stove (the hardware) there are a range of processes. These processes – for example, steaming, frying, boiling – are analogous to the instruction set which can be implemented by the CPU. The various ingredients that can be handled by a process are the instruction’s data. Such data may lie in an internal register or out in the Data store. There are several di erent ways of specifying the e ective address (ea) of an operand. These are known as address modes.
In keeping with the PIC microcontrollers’ RISC-like philosophy, the mid-range core have a total of only 35 instructions. Each instruction code is contained in a 14-bit word which holds the instruction operation code, address or data and destination bit. We have covered most of these instructions and address modes when discussing our BASIC computer back in Chapter 3; now would be a good time to go over this material. As we will begin this chapter by examining PIC’s address modes and how they are incorporated into an instruction’s binary word, we will use BASIC’s instruction set listed in Table 3.1 on page 53 for our illustrative examples. The latter part of the chapter looks at the full instruction set in some detail.
After reading this chapter you will:
•Know that an address mode is the way an instruction pin-points its data.
•Understand how Inherent, Literal, Register Direct, File Direct, File Indirect, Bit and Absolute address modes permit an instruction to target an operand for processing.
•Know that Movement instructions, copying data in-between the Working register and the Data store, are the most used of the instruction categories.
•Appreciate that the processor can directly implement the common arithmetic operations of Addition, Subtraction, Incrementation and Decrementation.
•Know that data in the Data store can be rotate-shifted through the C flag.
106 The Quintessential PIC Microcontroller
•Understand how to use the four basic logic instructions to invert, set, clear, toggle, bit test and di erentiate data.
•Know how to compare or test data for di erences and relative magnitude, and take appropriate action.
•Understand how the program flow can be diverted, based on the state of any bit or a zero value in a Data file.
•Recognize how the binary structure of the instruction word impacts on the usage of instructions.
Virtually all instructions act on data; either outside in its Data or Program memory space, or inside in an internal CPU register. Thus the 14bit instruction code must include bits which inform the CPU’s instruction decoder where this data is being held. The exception to this are the few Inherent instructions, such as nop (No Operation) and return (RETURN from subroutine). Before looking at the instruction set we will discuss the various techniques used to specify the location of any operands.
The general symbolic form of an instruction is:
instruction mnemonic <operand A>,<operand B>
where operand A is the source data or its location and operand B the destination. For example movf 20h,w (MOVe File) which copies data source out of File 20h to its destination in the Working register.
There are some variations on this structure. 212 -operand instructions are common. For example, addwf FILE,d adds the W register’s contents to the specified file’s contents and deposits the result either in W or back in the file register itself. Thus addwf 20h,f means “add the contents of W to that of File 20h and put the outcome in File 20h” or in Register Transfer Language (rtl, see page 49) (f20) <- W + (f20). Of course this is not a true 3-operand instruction as the destination must be one of the two source locations; that is W or File 20h. A few instructions have only a destination specified; for example, clrf 20h, and the inherent instructions have no explicit operands.
Instructions can be classified by their address mode.
Inherent
0000000 ???????
The instructions listed in Appendix A, clrwdt (CLeaR WatchDog Timer), retfie (RETurn From Interrupt and Enable), nop, return and sleep do not explicitly refer to operands in memory or in the Working register. At the binary code level, all these instructions are coded with the upper seven bits zero. For example, clrwdt has a machine code of 00000000000100b.
THE ESSENCE OF THE PIC MICROCONTROLLER 107
Register Direct
?????? 0 ???????
The PIC series has only one CPU register that can be explicitly specified by an instruction; the Working register. Where the destination is to be W then bit 7 of the instruction code is always 0. For example clrw is coded as 0000000000011b. Many instructions can either use W or the source file as the destination, and this is coded by setting bit 7 to 0 or 1 respectively. In Appendix A, bit 7 is marked as d for destination (see also File Direct addressing) for applicable instructions.
Where W is one of the source operands, the instruction normally shows this as part of the mnemonic. Thus movwf f copies W to the specified file register.
Literal
11 ???? LLLLLLL
Literal instructions use the lower eight instruction word bits to specify a source operand which is constant data rather than data in a register. For example addlw 06 is coded as 11111000000110b. The destination of this type of instruction is always the Working register, and this is shown in the mnemonic. Thus in our example, the sum W +6 is copied back into W. In rtl this is expressed as W <- W + #6 where the # (pound or hash) symbol denotes that the following number is a constant or literal rather than a file address.
File Direct
00 ???? d f
Instructions that specify that their source or destination operand lies in a file register use this address mode. The value of the file address is coded into the lower seven bits; denoted as f. For instance the code for clrf 20h is 00 0001 1 0100000.
Most instructions altering the contents of a file register can ‘dump’ the outcome either in the Working register or else back in the file. Bit 7 of the instruction code, labelled d, can specify the destination as in the following example:
incf 20h,w ; Coded as 00 1010 0 0100000 incf 20h,f ; Coded as 00 1010 1 0100000
In both cases the contents of File 20h (File 01000000b) are incremented. In the former instance, the outcome is put in W leaving the file contents unchanged (d = 0), whilst in the latter the original data is overwritten (d = 1).
108 The Quintessential PIC Microcontroller
The main characteristic of this type of address mode is that the location of the operand is fixed as an integral part of the program, and thus cannot be altered as the program progresses. In some cases, such as in Program 5.1, this technique is rather inflexible.
As only seven bits of the instruction code are reserved for the file address, only files from 00 – 7Fh may be directly accessed using this technique. However, from Fig. 4.6 on page 92 we see that the PIC16F84’s Data store maps the register files in the range 00 – FFh, requiring an 8-bit address. The PIC16F84 gets round this by employing the RP0 bit in the Status register as a surrogate most-significant address bit – see Fig. 4.5 on page 89. This Register Page control bit can be altered, like any other read/write file register bit, to switch back and forth between Bank 0 (RP0 = 0) and Bank 1 (RP0 = 1).
The full 14-bit core CPU model has the capability of interacting with a 512-register file Data store. Devices with this size of Data store, such as the PIC16F87X line, have to deal with four banks of up to 128 register files. This requires a 9-bit address. Here the Status register, shown in Fig. 5.1, has two page select bits, RP1:RP0 which must be set up prior to using the File Direct address mode. For example, in such a Data store with a file address range 000 – 1FFh, in order to clear File 17Fh (File 10 111 1111b) we need to set RP1:RP0 to 10:
bsf |
STATUS,6 |
; Make RP1 |
= |
1 |
||
bcf |
STATUS,5 |
; |
Make RP0 |
= |
0 |
(Bank 2) |
clrf |
17Fh |
; |
Clear File |
17Fh |
||
Program 15.4 on page 442 is an example making use of this extended bank switching.
File Indirect
00 ???? d 0000000
Where data in the Data store is to be accessed, specifying its location directly as an address constant seems the obvious way to go; for example, clrf 20h. However, as we saw back in Program 3.1 on page 56, this may not always be the most e cient approach. This is especially the case when an array of data, such as a sequential set of readings, is to be processed.
Most MPU/MCU devices have one or more Address registers, sometimes known as Index registers. These are designed to hold the address in memory of the operand; that is they act as a pointer. Such processors use one or more Indexed or Indirect address modes which look to the appropriate pointer register to specify the operand location, rather than have the address as a fixed part of the instruction code. The advantage of this indirect approach of addressing a data operand is that the address can easily be altered as the program progresses. Thus, for example, an
THE ESSENCE OF THE PIC MICROCONTROLLER 109
Bank 3 |
(File 180 - 1FFh) |
X/Y |
|||||||||||||||
3 |
|||||||||||||||||
Bank 2 |
(File 100 - 17Fh) |
2 |
|||||||||||||||
Bank 1 |
(File 080 - 0FFh) |
1 |
Status |
register (SR) |
|||||||||||||
Bank 0 |
(File 000 - 07Fh) |
0 |
|||||||||||||||
1 |
|||||||||||||||||
0 |
File 3 |
||||||||||||||||
Register |
File Bank |
Select |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|||||||
decoder |
IRP |
RP1 |
RP0 |
TO |
PD |
Z |
DC |
C |
|||||||||
(R/W 0) |
(R/W 0) |
(R/W 0) |
(R 1) |
(R 1) |
(R/W ?) |
(R/W ?) |
(R/W ?) |
||||||||||
Indirect Register File Bank Select |
|||||||||||||||||
Carry/Borrow |
|||||||||||||||||
Bank 0/1 |
(File 000 - 0FFh) |
0 |
|||||||||||||||
Digit Carry/Borrow |
|||||||||||||||||
Bank 2/3 |
(File 100 - 1FFh) |
1 |
|||||||||||||||
Zero
Time-Out Watchdog time-out 0 clrwdt/sleep instructions 1
Power Down
By sleep instruction 0
By clrwdt instruction 1
Fig. 5.1 General 14-bit core Status register.
array of data may be cleared by using an address register to point to the target location, and repeating in a loop while incrementing that pointer register.
The PIC family does not have dedicated CPU Address/Index registers to perform this indirect holding function. Instead, the pointer address is that contained in the File Select Register (FSR), which is File 4 in the Data store, see Fig. 4.6 on page 92. To activate the indirect mechanism, the normal File Direct address mode is used, but with File 0 as the target
directly |
||
instructionreferencing |
this |
|
Any |
||
INDF
F0 actually
virtual location
sends
File |
store |
||||||
the |
|||||||
FSR |
to |
||||||
out |
|||||||
F4 |
|||||||
this address |
|||||||
Pointer
Fig. 5.2 The indirect mechanism.
110 The Quintessential PIC Microcontroller
location. File 0, the INDF (INDirect File) register, is a virtual location, that is it is not physically implemented. Its sole use is to trigger the use of the contents of the FSR as the operand address, as shown in Fig. 5.2. Thus the instruction clrf 0 will actually clear the file whose 8-bit address is that in File 4. Of course the contents of the Special-Purpose Register (SPR) FSR can be altered at any time, for example incremented on each pass through a loop. This is the approach taken in Program 3.2 on page 57, which clears an array of Data-store memory. Although this approach to indirect addressing may seem rather convoluted, it does not require additional clock cycles to execute, unlike the alternative techniques used by other MPU/MCUs.
A more sophisticated example than that of Program 3.2 involves the sampling of temperature hourly over a daily period. With the assumption that the resulting array of 24 byte values are in situ in the Data store between File 30h and File 47h, we are required to scan through the array looking for the maximum temperature. By the end of the routine this is to be in File 48h.
To implement this procedure we first need a strategy or task list. One possibility would be:
1.Initialize Maximum as Temp[0].
2.IF Temp[1] > Maximum THEN Maximum = Temp[1].
3.IF Temp[2] > Maximum THEN Maximum = Temp[2].
4.IF Temp[3] > Maximum THEN Maximum = Temp[3]…….
5.…etc.
6.IF Temp[23] > Maximum THEN Maximum = Temp[23].
7.End.
How can we code Temp[i] > Maximum? If we subtract Maximum from Temp[i], that is Temp[i] − Maximum, then if a borrow is not generated (C flag set) we know that the former is higher than the latter and Maximum needs updated. Based on this, a possible coding is given in Program 5.1.
In this linear coding the comparison is implemented by first bringing the current maximum into the Working register (movf MAXIMUM,w), then subtracting it from the appropriate direct address, eg. for Temp[2] or File 32h, subwf TEMP_0+2,w. This subtraction will set the C flag (that is N) if there is no borrow out, and in that situation the instruction btfss will skip to the update sequence. This simply copies down the appropriate temperature byte and copies it again up to the register file holding
Maximum, eg. movf TEMP_0+2,w – movwf MAXIMUM.
The process outlined here has to be coded 24 times, with some small saving in the initial setting of Maximum to Temp[0] and the fact that this value is already in W for the Temp[1] comparison. This gives a total of 139 instructions. Execution time depends a little on the number of times Maximum has to be updated. However, taking a worse-case scenario and remembering that goto takes two cycles to implement as does btfss
THE ESSENCE OF THE PIC MICROCONTROLLER 111
Program 5.1 Finding the maximum temperature the linear way.
STATUS |
equ |
3 |
; |
Status register is File 3 |
TEMP_0 |
equ |
30h |
; |
Array starts @ File 30h |
MAXIMUM |
equ |
48h |
; |
Maximum value to be in File 48h |
NB |
equ |
0 |
; |
Carry/Not Borrow flag is bit0 |
; Task1: Initialize Maximum |
as Temp[0] |
|||
MAX_DAILY movf |
TEMP_0,w |
; |
Get it |
|
movwf |
MAXIMUM |
; |
and put it in as first maximum |
|
; Task2: Check is Temp[1] > |
Maximum? |
|||
subwf |
TEMP_0+1,w |
; |
Temp[1] - Maximum |
|
btfss |
STATUS,NB |
; |
IF no borrow (NB==1) THEN update |
|
goto |
TASK3 |
; |
Skip update |
|
movf |
TEMP_0+1,w |
; |
Update by getting Temp[1] |
|
movwf |
MAXIMUM |
; |
which is the new maximum |
|
; Task3: Check is Temp[2] > |
Maximum? |
|||
TASK3 |
movf |
MAXIMUM,w |
; |
Get current maximum |
subwf |
TEMP_0+2,w |
; |
Temp[2] - Maximum |
|
btfss |
STATUS,NB |
; |
IF no borrow (NB==1) THEN update |
|
goto |
TASK4 |
; |
Skip update |
|
movf |
TEMP_2,w |
; |
Update by getting Temp[2] |
|
movwf |
MAXIMUM |
; |
which is the new maximum |
|
; Task4: Check is Temp[3] > |
Maximum? |
|||
TASK4 |
movf |
MAXIMUM,w |
; |
Get current maximum |
subwf |
TEMP_0+3,w |
; |
Temp[3] - Maximum |
|
btfss |
STATUS,NB |
; |
IF no borrow (NB==1) THEN update |
|
goto |
TASK5 |
; |
Skip update |
|
movf |
TEMP_0+3,w |
; |
Update by getting Temp[3] |
|
movwf |
MAXIMUM |
; |
which is the new maximum |
|
; Task5 |
and so |
on |
||
TASK5 |
..... ...... |
|||
; Task24: Check |
is Temp[23] > |
Maximum? |
||
TASK24 |
movf |
MAXIMUM,w |
; |
Get current maximum |
subwf |
TEMP_0+23,w |
; |
Temp[23] - Maximum |
|
btfss |
STATUS,NB |
; |
IF no borrow (NB==1) THEN update |
|
goto |
FINI |
; |
Skip update |
|
movf |
TEMP_0+23,w |
; |
Update by getting Temp[23] |
|
movwf |
MAXIMUM |
; |
which is the new maximum |
|
FINI |
..... ...... |
|||
when a skip occurs, then this gives 188 clock cycles to execute; that is 188 µs for a 4 MHz crystal.
Now Program 5.1 is rather a long program for a small task. This is because the complete sequence of compare-update instructions have to be implemented 23 times. Each sequence is identical, except the next ele-