Файл: 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:

D_LOOP

addlw

-1

; Decrement

:

(255

x 1)˜

btfss

STATUS,Z

; Until zero

:

(255

X

1) + 1˜

goto

D_LOOP

;

:

(255

X

2)˜

return

;

:


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.