Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 5294
Скачиваний: 0
Finish current instruction
Interrupt line active?
No
Next instruction
7. Interrupt Handling 175
Yes
Clear GIE
Stack PC
Goto 004h
Interrupt service routine
retfie
Fig. 7.2 Responding to an interrupt request.
3.If both the interrupt flag is set and bit 7 of the INTCON special purpose register (see Fig 7.4) is clear, the next three instruction cycles are involved in moving execution to the interrupt service routine, although the first of these may be the final cycle of a 2-cycle instruction otherwise a dummy cycle, plus two more cycles to flush the pipeline. This 3 to 4-cycle delay from the instant of the hardware INT signal and beginning the execution of the first instruction of the ISR is known as latency. It is impossible to be more precise due to the time-random nature of the external request signal which can occur anywhere in the instruction cycle.
4.During this latency period the PIC does three things:
(a)Bit 7 of the INTerrupt CONtrol register (INTCON at File 0Bh) is zeroed. This bit is labelled in Fig. 7.4 as General Interrupt Enable (GIE). Once GIE is cleared all further requests for interrupts from whatever source are locked out, so an interrupt service process cannot be further interrupted. GIE is an example of an Interrupt mask as it is able to mask out interrupt activity. After reset GIE is cleared, so by default interrupt activity is disabled.
176The Quintessential PIC Microcontroller
(b)The state of the 13-bit Program Counter is pushed into the hardware stack in exactly the same manner as for a call instruction
– see Fig. 6.3 on page 141. As for subroutines, this is to allow the processor to return to the interrupted background program after the interrupt service routine. As the mid-range PICs have an 8-deep hardware stack, subroutines nested to depth of seven can be called from an ISR.
(c)The first instruction of the ISR is always in location 004h in the Program store. Thus the final step of the sequence is to overwrite the PC with this instruction address, known as the Interrupt vector. If the interrupt handling software is elsewhere in Program memory then this entry instruction can of course be a goto instruction; see Program 7.1.
5.Like a subroutine, an ISR must be terminated by a Return instruction. However, in this case not only has the PC to be pulled out of the hardware stack to move execution back to the interrupted program but the GIE bit in the INTCON register must be set to re-enable the interrupt capability. This counteracts the resetting of this bit in 4(a) above on entry to the ISR. The Return instruction relevant to this situation is retfie (RETurn From Interrupt and Enable). Thus on reentry to the background program any pending or future interrupts can be serviced.
An ISR di ers from a subroutine in more subtle ways than the use of the retfie instruction of item 5 above. Some of these di erences relate to the logic of the interrupt system and some are due to the pseudo random nature of the interrupts. Discussing the former first, let us examine the logic circuitry relating to the interrupt process.
Interrupt flag |
To PIC control circuitry |
|||
Interrupt mask |
||||
Fig. 7.3 The flag:mask pair.
Each of the four PIC16F84 interrupt sources interact with the processor via two associated control register bits, as shown in Fig. 7.3. The flag bit is set when the related source device requests service. For example, if the Timer 0 overflows FFh → 00h then bit 2 of the INTCON register, labelled T0IF (Timer 0 Interrupt Flag) is set to 1. If the local mask bit is 1 (bit 5 of INTCON labelled T0IE for Timer 0 Interrupt Enable) then the request will go forward to the next layer of interrupt logic. Note that the state of the mask bit does not a ect the setting of the associated interrupt flag. Thus if the mask bit is zero, a polling technique can still be
7. Interrupt Handling 177
used to determine if an event has occurred by checking the state of the appropriate interrupt flag.
The local mask bit can be written to in the normal way by software. On reset it is zeroed and thus the interrupt from the a liated source disabled. To set it to one, use the bsf instruction. For example, bsf INTCON,5 to set the T0IE mask. The interrupt flag can also be written to by software, as well as being externally set by the requesting device. The ISR must clear it, eg. bcf INTCON,1, before return to cancel the request otherwise an endless series of interrupts will occur. This is because on return the interrupt flag will still be set and another interrupt will immediately be set in train.
As there are four sources of interrupt, each flag:mask AND gate must be ORed to give a composite request signal, which when active initiates the CPU’s interrupt response. In Fig. 7.4 this ORing process is further gated with the Global mask bit GIE, which is located in bit 7 of INTCON. However, the raw, i.e. pre-globally masked, request signal is used to awaken the processor if it is in a power-down or sleep state. As we will see in Chapter 10 the current consumption of the device can be considerably reduced to typically 1 µA if processing is stopped and the PIC is put in a state of suspended animation. For example, monitoring the temperature profile at the bottom of a lake over a period of a year at one hour intervals using a battery-powered data logger requires processing for a tiny proportion of the time. Placing the PIC in this power-down mode after each sample has been taken and stored will reduce the necessary battery capacity. The sleep instruction initiates this mode. An interrupt from an outside source, in this case a low-power hourly oscillator, is used to wake the PIC up. As shown, this awakening is independent of the setting of the General mask.
The Timer 0, External and Port B Interrupt flags are located in the INTCON register at bits 2, 1, 0 respectively. These peripherals are common across all mid-range PICs and appear in the same location for these devices. That for the internal Data EEPROM is separately located in the EECON1 Special Purpose Register (SPR) in Bit 4 – see Fig. 15.2 on page 434. Bit EEIF is set whenever a write-data action has been completed.
The Data EEPROM is peculiar to the PIC16F83/4 devices. Other PICs substitute alternative flags for their specialized peripheral devices. For example, the PIC16C71 uses bit 1 of its ADCON0 (A/D CONtrol 0) as the ADIF flag to show that the internal A/D converter has finished its conversion. More sophisticated PICs have more than one interrupting device beyond the three standard ones – INT, Timer 0 and Port B. For instance, the PIC16C74 has eight (plus the standard three) interrupt sources, including two additional timers, a multichannel A/D converter and two serial ports. In this case each such peripheral has its own interrupt flag
178 The Quintessential PIC Microcontroller
INTerrupt |
CONtrol |
||||
7 |
6 |
5 |
4 |
3 |
2 |
GIE |
EEIE |
T0IE |
INTE |
RBIE |
T0IF |
(R/W 0) |
(R/W 0) |
(R/W 0) |
(R/W 0) |
(R/W 0) |
(R/W 0) |
|
0)(R/W |
4 EEIF |
3 overflow Timer0 |
||||||||||||
|
4 write EEPROM |
||||||||||||||
|
88h File |
EECON1 |
|||||||||||||
|
S |
1 |
INTF
(R/W 0)
2 interrupt Hardware
INT
0 |
|||||||||
RBIF |
INTCON |
||||||||
(R/W ?) |
File 0Bh/8Bh |
||||||||
|
changePORTB |
1) (R/W |
6 INTEDG |
|||||||
|
81h File |
OPTION |
||||||||
|
1 |
REG |
||||||||
|
CPU to Interrupt |
mode) sleep in (if up Wake |
Fig. 7.4 The PIC 16F84’s interrupt logic.
together in a Peripheral Interrupt Register, as shown in Fig. 14.10(b) on page 408.
The INTCON register also holds the four local mask bits corresponding to the PIC16F84’s standard peripherals, besides the Global mask. The programmer can selectively disable or re-enable one or more interrupting source as desired. Thus if it is undesirable for Timer 0 to interrupt a section of code dealing with, say, multiple-precision arithmetic (see Ex-
7. Interrupt Handling 179
ample 7.2) then T0IE can be cleared for the duration of that routine. Other PIC devices replace the EEIE mask by one appropriate to their additional peripheral. Thus the PIC16C71 has ADIE (Analog to Digital Interrupt Enable) as bit 6 of INTCON. PICs with more than one additional peripheral use this bit to enable all these extra requests as a single group, called PEIE (PEripheral Interrupt Enable). However, all these extra devices have their own local masks together in a Peripheral Interrupt Enable register, giving three layers of mask – see Fig. 14.10(b) on page 408.
As there is only one common interrupt vector, i.e. at 004h, then one of the first tasks the ISR has to do is check which peripheral is calling for help. All interrupt flags can be read, so these can be polled in turn until the one that is set is found. Based on this approach a typical polling sequence could be:
STATUS |
equ 03 |
; The Status register |
|||
INTCON |
equ 0Bh |
; The INTerrupt CONtrol register |
|||
RP0 |
equ 5 |
; bit 5 of which is the RP0 bit |
|||
EECON1 |
equ 88h |
; The EEPROM CONtrol 1 register |
|||
bsf |
STATUS,RP0 |
; |
Change to Bank 1 registers |
||
btfsc |
INTCON,1 |
; |
Check for external interrupt |
||
goto |
EXTERNAL |
; |
IF set THEN go to INT handler |
||
btfsc |
INTCON,2 |
; |
Check for Timer0 interrupt |
||
goto |
TIMER0 |
; |
IF set, go to TMR0 handler |
||
btfsc |
INTCON,0 |
; |
Check for change at PortB int |
||
goto |
CHANGE_B |
; |
IF set, go to correct handler |
||
btfsc |
EECON1,4 |
; |
Check EEPROM write-to inter |
||
goto |
EEPROM_WR |
; |
IF set, go to EEPROM handler |
||
IRQ_EXIT |
bcf |
STATUS,RP0 ; |
Return to Bank 0 registers |
||
retfie |
; |
and return |
|||
The order of polling gives a priority level if more than one interrupt request should coincide. Thus if both the external hardware and Timer 0 interrupts are active, the former will be processed first. In this case, on return the pending Timer 0 interrupt requests will then be processed
– unless another higher-priority interrupt request has occurred. In all instances the appropriate interrupt flag should be cleared, otherwise the interrupt will be generated indefinitely!
Where masks are set, this same polling technique can be used to check on the status of events without using the PIC’s interrupt processes. For example, when a byte is written to the Data EEPROM (see Program 15.2 on page 436) the program typically checks the state of EEIF (bit 4 of EECON1) until it is set, then clears it and continues on.
180 The Quintessential PIC Microcontroller
W_LOOP btfss |
EECON1,EEIF |
; |
Check state of the |
EEIF flag |
goto |
W_LOOP |
; |
IF still zero THEN |
try again |
; ELSE continue after clearing the write-to EEPROM flag bcf EECON1,EEIF
Figure 7.4 shows additional logic particular to the external INT pin. INTF is set on a falling edge. By interposing an XOR gate as a programmable inverter, as described on page 14, the active edge on the INT pin can be controlled from bit 6 of the Option register – see also Fig. 13.2 page 363. If INTEDG is 0 then INTF will be set on a falling edge at INT whilst a rising edge is active when INTEDGE is 1, which is the default on reset.
Interrupts happen randomly as viewed by the software and thus, unless masked out, may happen at any part of the background software, including in the middle of a subroutine. An ISR foreground routine uses the internal processor registers in the same way as any other software, so conflict over such resources will exist. For example, the background program could just be testing an object when an interrupt occurs. The Skip instruction which follows the test could be dependent on, say, the state of the Zero flag in the Status register. However, the ISR will in all probability alter Z and thus on return the background program will execute the skip, oblivious of the fact that execution has been transferred in the interregnum. Any change to Z would cause an erroneous branch in the background program. Trying to debug this sort of problem is virtually impossible because the e ect of such an interrupt is sporadic as the particular bug depends on the interrupt occurring at just this wrong time and wrong place – something it may do perhaps once a week – and thus is di cult to reproduce.
Another example is illustrated in the polling listing on page 179. Here on entry to the ISR, bit RP0 of the STATUS register (see Fig. 4.6 on page 92) was set to allow access to Bank 1 SPRs. This was necessary as the EEPROM control registers only appear in this bank, whilst both the STATUS and INTCON SPRs are shadowed in both banks. At the exit point, RP0 is cleared to move back to Bank 0. However, this assumes that the background program was in Bank 0 when interrupted. Clearly this is erroneous if an interrupt occurs during an access to Bank 1.
All but the most elementary ISR will need to, at the very least, save the STATUS and Working registers. Generally the programmer sets aside two File registers as temporary storage and for no other use. Traditionally such locations are named with a leading underscore to show that they are used for system purposes and are not to be tampered with by the User’s program. In Program 7.1 File 1Ch and File 1Dh are labelled _work and _status to conform to this convention.
7. Interrupt Handling 181
Program 7.1 Background program for the pea canning packer.
STATUS |
equ |
03 |
; The STATUS register |
Z |
equ |
2 |
; and bit2 is the Zero flag |
RP0 |
equ |
5 |
; and bit5 is the Register Page bit |
PORTA |
equ |
05 |
; Port A |
TRISA |
equ |
85h |
; whose direction register is in Bank1 |
INTCON |
equ |
0Bh |
; INTerrupt CONtrol register |
INTF |
equ |
1 |
; in which bit1 is the INTerrupt Flag |
INTE |
equ |
4 |
; and the associated mask is bit4 |
GIE |
equ |
7 |
; and the global mask is bit7 |
_work |
equ |
1Ch |
; Place for the background Working register |
_status |
equ |
1Dh |
; and the background STATUS register |
EVENT |
equ |
20h |
; Keeps count of cans of peas |
; **************************************************************
org |
0 |
; |
Resets here |
||
MAIN |
goto BACKGND |
; |
Go to start |
of background routine |
|
; **************************************************************
org |
04 |
; |
The interrupt vector |
goto |
CAN_COUNT |
; |
Go to start of foreground ISR |
;**************************************************************
;Background program starts by setting up and initialization
BACKGND |
bsf |
STATUS,RP0 |
; |
Change to Bank1 |
bcf |
TRISA,0 |
; |
Make bit RA0 an o/p by clearing TRIS0 |
|
bcf |
STATUS,RP0 |
; |
Go back to Bank0 |
|
movlw |
d’23’ |
; |
Very first value is a dummy dec 23 |
|
movwf |
EVENT |
|||
clrf |
INTCON |
; |
Zero any set interrupt flags |
|
bsf |
INTCON,GIE ; |
Enable all interrupts |
||
bsf |
INTCON,INTE; |
Enable external INT-pin interrupts |
||
; WHILE event count is less than one DO nothing |
||||
LOOP |
movf |
EVENT,w |
; |
Get event count |
sublw |
1 |
; |
Compare with one |
|
btfss |
STATUS,Z |
; |
Is it equal? |
|
goto |
LOOP |
; |
IF not THEN try again ELSE skip |
|
; Now wait until count is back to zero |
||||
M_LOOP |
movf |
EVENT,f |
; |
Test for zero |
btfss |
STATUS,Z |
; |
Skip IF Zero |
|
goto M_LOOP
; Pulse on the 24th can bsf PORTA,0
call DELAY bcf POTRA,0
goto LOOP
;ELSE try again
;Bring line RA0 high
;Wait for one millisecond
;and go low again
;DO forever
; **************************************************************
; * Subroutine delays for a nominal millisecond at 4MHz * ; **************************************************************
DELAY |
movlw |
0FFh |
; Count down from 255d: |
1˜ |
||||
D_LOOP |
addlw |
-1 |
; Decrement |
: |
(255 |
x 1)˜ |
||
btfss |
STATUS,Z |
; Until zero |
: |
(255 |
X |
1) + 1˜ |
||
goto |
D_LOOP |
; |
: |
(255 |
X |
2)˜ |
||
return |
; |
: |
2˜ |
|||||
182 The Quintessential PIC Microcontroller
Taking as a simple example, consider a conveyer belt in a pea-canning factory. As part of the automatic packing system, a photocell generates a single short pulse for each passing can. The packing machine requires a nominal 1 ms high-going pulse / \ after each batch of 24 cans passes the photocell. Using a PIC16F84 with the photocell sensor connected to the INT pin and the Port A’s pin 0 (RA0) driving the packing machine, design both the background and foreground software. Assume that the PIC is being clocked using a 4 MHz crystal.
A suitable background routine is shown in Program 7.1. There are three distinct phases in the code.
Initialization
This phase begins just after the Interrupt vector at 004h. The PIC always resets to the first instruction in the Program store, i.e. 00h, the Reset vector. The first instruction is simply goto BACKGND where BACKGND is the instruction at 005h. Notice how the org directive is used to place this label at 005h.
As interrupts are automatically disabled on reset, the various File registers and ports are normally set to their initial value at the beginning of the background program before interrupts are enabled. This eliminates the possibility of servicing an interrupt before the initialization code has been completed. The initialization schedule is:
1. All parallel port lines are configured as inputs on reset. To change Port A bit 0 to an output, the associated bit in the TRISA SPR must be cleared. As TRISA is located in Bank 1, RP0 in STATUS is used to switch banks – see page 93. More details are given in Chapter 11.
2.The file register used by the ISR to hold the photocell pulse count is set to an initial value of 23. When the first can passes the sensor, the ISR will set this back to zero thinking that 24 cans have now passed.
3.Clearing all bits in the INTCON register clears all interrupt flags that may have been set since reset. This is important as such flags may be set irrespective of the state of the associated mask bits. Setting the Global Interrupt Enable mask bit now enables the interrupt system and specifically setting INTE enables interrupts from the INT pin.
Main routine
The core of the background software repetitively checks the state of the EVENT file register, which is incremented behind the scenes in the ISR. Initially it waits until EVENT passes a count of one. It then checks for a subsequent zero, which occurs when the ISR detects the first can following event 23. That is the count rolling over 22 → 23 → 0. When a zero is detected RA0 is set high, a 1 ms delay subroutine is called, and then RA0 is brought low again.
The sequence is then repeated indefinitely. The initial wait until EVENT is one ensures a ratchet action, with only one outcome / \ for each zero count in EVENT.
7. Interrupt Handling 183
Delay subroutine
The delay subroutine immediately follows the endless loop main routine. The hold o is implemented by decrementing from FFh to zero, with W holding the count. This takes 1026 cycles including the launching call, which at 1 µs per cycle is nominally 1 ms.2
Program 7.2 Event counting foreground software.
CAN_COUNT |
||||||
movwf |
_work |
; Save current |
W reg. in Data |
memory |
||
swapf |
STATUS,w |
; |
Get |
current Status, don’t change flags |
||
movf |
_status |
; |
and |
put away |
in Data memory |
|
; *************************************************************
bcf |
INTCON,INTF |
; Clear the hardware interrupt flag |
incf |
EVENT,f |
; Record one more event |
movf |
EVENT,w |
; Get count |
sublw |
d’23’ |
; Compare with 23 (23 - EVENT) |
btfss |
STATUS,NB |
; IF lower or same THEN skip to finished |
clrf |
EVENT |
; ELSE zero can count |
; *************************************************************
swapf |
_status,w |
; Untwist |
& get original Status from mem |
||
movwf |
STATUS |
||||
swapf |
_work,f |
; Now |
get |
original Working register from |
|
swapf |
_work,w |
; |
Data memory without altering flags |
||
retfie |
; |
and |
return to interrupted background |
||
When an interrupt occurs the PIC always executes the instruction located at 004h, the Interrupt vector. We see from phase 1 of the background program that this causes execution to transfer to the instruction labelled CAN_COUNT, the first instruction in Program 7.2; that is
Interrupt 004h → CAN_COUNT.
The foreground program, or interrupt service routine, can also be divided into three phases.
Context switching
Both the Working and Status register are saved in the Data store. Firstly, W is copied out to _work. Fortunately movwf does not alter any of the status flags, so the state of STATUS is is still that of the interrupted background program.
Saving this STATUS register is more di cult. The obvious approach is to copy it into W and then out to _status. However, the movf instruction alters the Z flag. Instead, we use swapf to copy the datum into W. swapf does not a ect the flags but does of course interchange the top and bottom halves of the byte. However, we can untwist them on restoration.
2Of course the delay subroutine can be interrupted which will randomly slightly lengthen the delay. In time-critical situations GIE should be zeroed before calling the delay subroutine and set on return.