
- •Table of Contents
- •Preface
- •Additional Material
- •Basic Electronics
- •1.0 The Atom
- •1.1 Isotopes and Ions
- •1.2 Static Electricity
- •1.3 Electrical Charge
- •1.4 Electrical Circuits
- •1.5 Circuit Elements
- •1.6 Semiconductors
- •Number Systems
- •2.0 Counting
- •2.1 The Origins of the Decimal System
- •2.2 Types of Numbers
- •2.3 Radix Representations
- •2.4 Number System Conversions
- •Data Types and Data Storage
- •3.0 Electronic-Digital Machines
- •3.1 Character Representations
- •3.2 Storage and Encoding of Integers
- •3.3 Encoding of Fractional Numbers
- •3.4 Binary-Coded Decimals (BCD)
- •Digital Logic, Arithmetic, and Conversions
- •4.0 Microcontroller Logic and Arithmetic
- •4.1 Logical Instructions
- •4.2 Microcontroller Arithmetic
- •4.3 Bit Manipulations and Auxiliary Operations
- •4.4 Unsigned Binary Arithmetic
- •4.5 Signed Binary Arithmetic
- •4.6 Data Format Conversions
- •Circuits and Logic Gates
- •5.0 Digital Circuits
- •5.1 The Diode Revisited
- •5.2 The Transistor
- •5.3 Logic Gates
- •5.4 Transistor-Transistor Logic
- •5.5 Other TTL Logic Families
- •5.6 CMOS Logic Gates
- •Circuit Components
- •6.0 Power Supplies
- •6.1 Clocked Logic and Flip-flops
- •6.2 Clocks
- •6.3 Frequency Dividers and Counters
- •6.4 Multiplexers and Demultiplexers
- •6.5 Input Devices
- •The Microchip PIC
- •7.0 The PICMicro Microcontroller
- •7.1 PIC Architecture
- •Mid-range PIC Architecture
- •8.0 Processor Architecture and Design
- •8.1 The Mid-range Core Features
- •8.2 Mid-Range CPU and Instruction Set
- •8.3 EEPROM Data Storage
- •8.4 Data Memory Organization
- •8.5 Mid-range I/O and Peripheral Modules
- •PIC Programming: Tools and Techniques
- •9.0 Microchip’s MPLAB
- •9.1 Integrated Development Environment
- •9.2 Simulators and Debuggers
- •9.3 Programmers
- •9.4 Engineering PIC Software
- •9.5 Pseudo Instructions
- •Programming Essentials: Input and Output
- •10.0 16F84A Programming Template
- •10.1 Introducing the 16F84A
- •10.2 Simple Circuits and Programs
- •10.3 Programming the Seven-segment LED
- •10.4 A Demonstration Board
- •Interrupts
- •11.0 Interrupts on the 16F84
- •11.1 Interrupt Sources
- •11.2 Interrupt Handlers
- •11.3 Interrupt Programming
- •11.4 Sample Programs
- •Timers and Counters
- •12.0 The 16F84 Timer0 Module
- •12.1 Delays Using Timer0
- •12.2 Timer0 as a Counter
- •12.3 Timer0 Programming
- •12.4 The Watchdog Timer
- •12.5 Sample Programs
- •LCD Interfacing and Programming
- •13.0 LCD Features and Architecture
- •13.1 Interfacing with the HD44780
- •13.2 HD44780 Instruction Set
- •13.3 LCD Programming
- •13.4 Sample Programs
- •Communications
- •14.0 PIC Communications Overview
- •14.1 Serial Data Transmission
- •14.2 Parallel Data Transmission
- •14.4 PIC Protocol-based Serial Programming
- •14.5 Sample Programs
- •Data EEPROM Programming
- •15.0 PIC Internal EEPROM Memory
- •15.1 EEPROM Devices and Interfaces
- •15.2 Sample Programs
- •Analog to Digital and Realtime Clocks
- •16.0 A/D Converters
- •16.1 A/D Integrated Circuits
- •16.2 PIC On-Board A/D Hardware
- •16.3 Realtime Clocks
- •16.4 Sample Programs
- •Index
Interrupts |
217 |
Multiple External Interrupts
One of the practical applications of the port-B line-change interrupt is in handling several different interrupt sources; for example, a circuit containing four push-button switches that activate four different circuit responses. If the switches are wired to the corresponding pins in Port-B (RB4 to RB7) and the line-change interrupt is enabled, the interrupt takes place when any one of the four switches changes level, that is, when any one of the interrupt lines go from high to low or from low to high. The interrupt handler software can easily determine which of the switches changed state and if the change took place on the signal’s rising or falling edge. The corresponding software routines then handle each case.
Later in this chapter we develop a sample program that uses the Port-B line-change interrupt to respond to action on four pushbutton switches.
11.1.4 EEPROM Data Write Interrupt
The origin of this interrupt relates to the relative slowness of the EEPROM data write operation, which is of 10 ms. The interrupt serves no other function than to allow the microcontroller to continue execution while the data write operation is in progress. The interrupt service routine informs the microcontroller when writing has ended through the EEIF bit located in the EECON1 register. The use of this interrupt is considered in Chapter 15, in the context of EEPROM data memory access and programming.
11.2 Interrupt Handlers
The interrupt handler, also called the interrupt service routine or the ISR, is the code that receives control upon occurrence of the interrupt. Most of the programming that goes into the service routine is specific to the application; however, there are certain housekeeping operations that should be included. The following list describes the structure of an interrupt service routine for the mid-range PICs:
1.Preserve the value in the w register.
2.Preserve the value of the STATUS register.
3.Execute the application-specific operations.
4.Restore the value of the STATUS register at the time of the interrupt.
5.Restore the value of the w register at the time of the interrupt.
6.Issue the RETFIE instruction to end the interrupt handler.
In the PIC 16F84, the interrupt service routine must be located at offset 0x004 in code memory. A simple org directive takes care of ensuring this location, as in the following code fragment:
org |
0x000 |
; Beginning of code area |
|
goto |
start |
; |
Jump to program start |
org |
0x004 |
; |
Start of Service routine |
. |
|
. |
; SERVICE ROUTINE GOES HERE |
. |
|
218 |
|
Chapter 11 |
retfie |
; |
End of ISR |
start: |
; |
Program starts here |
Alternatively, code can place a jump at offset 0x004 and locate the Service Routine elsewhere in the code. In this case, it is important to remember not to call the Service Routine, but to access it with a goto instruction. The reason is that the call opcode places a return address in the stack, which then polls for the retfie instruction.
11.2.1 Context Saving Operations
The only value automatically preserved by the interrupt mechanism is PC (the Program Counter), which is stored in the stack. Applications often need to restore the processor to the same state as when the interrupt took place, so the first operation of most interrupt handlers is saving the processor’s context. This usually includes the w and the STATUS registers and occasionally others used by the specific implementation.
Saving w and STATUS Registers
Saving the w and the STATUS registers requires using register variables, but the process requires special care. Saving the w register is simple enough: its value at the start of the Service Routine is stored in a local variable from which it is restored at termination. But saving the STATUS register cannot be done with the MOVF instruction, since this instruction changes the zero flag. The solution is to use the SWAPF instruction which does not affect any of the flags. Of course, SWAPF inverts the nibbles in the operand, so it must be repeated so as to restore the original state. The following code fragment assumes that file register variables named old_w and old_status were previously created.
save_cntx: |
|
|
|
movwf |
old_w |
; |
Save w register |
swapf |
STATUS,w ; STATUS to w |
||
movwf |
old_status |
; |
Save STATUS |
;
; Interrupt handler operations go here
; |
|
swapf |
old_status,w ; Saved status to w |
movfw |
STATUS ; To STATUS register |
;At this point all operations that change the
;STATUS register must be avoided, but swapf does not.
swapf |
old_w,f |
; |
Swap file register in itself |
swapf |
old_w,w |
; |
reswap back to w |
retfie |
|
|
|
11.3 Interrupt Programming
In the sections that follow, we discuss programming interrupts that originate in Port-B, line 0, and those that originate in changes of port-B lines RB4 to RB7. Interrupts that relate to the Timer0 overflow or to EEPROM data write operations are cov-

Interrupts |
219 |
ered in the chapter on Serial Communications and the one on EEPROM Data Operations, respectively.
11.3.1 Programming the External Interrupt
Port-B, line 0, is referred to as the External Interrupt source. The name is not the most adequate since other interrupts can also have external sources. One of the important uses of this interrupt source is to wake the processor from the SLEEP mode. This allows developing applications that can run on a small power source (such as batteries) since the program uses almost no power until some action associated with the interrupt source wakes up the PIC. A sample program using the RB0 interrupt is developed later in this chapter. Our first sample program is a simple demonstration of the installation and action of the interrupt. The program is based on the circuit in Figure 11-4.
|
|
|
|
|
|
|
2x470 Ohms |
|
|
4 MHz |
|
|
|
|
|
|
|
|
|
Osc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
green |
red |
|
|
|
|
+5 V |
|
|
|
|
|
18 |
17 |
16 |
15 |
14 |
13 |
12 |
11 |
10 |
|
RA1 RA0 OSC1 OSC2 Vdd RB7 RB6 RB5 RB4
16F84
RA2 RA3 T0Tkl MCLR Vss RB0/INT RB1 RB2 RB3
|
|
|
|
|
|
|
|
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
+5 V
10K Ohms
4.7K Ohms
+5 V
Figure 11-4 Circuit for RB0 Interrupt Demonstration
In the circuit of Figure 11-4, a pushbutton switch is wired to the RB0 port. It is this switch which produces the interrupt when pressed. A red LED is wired to port RB1 and a green LED to port RB2. The main program flashes the green LED on and off at a rate of approximately one-half second. The red LED is toggled on and off when the pushbutton switch is pressed. The switch contains a 4.7K Ohm resistor that keeps the port high until the contact is made and sent to ground. This makes the
220 |
Chapter 11 |
switch active low and the interrupt is programmed on the falling edge of the signal, which takes place when the contact is made.
RB0 Interrupt Initialization
In order to initialize the RB0 interrupt, the following operations must take place:
1.Port-B, line 0, must be initialized for input.
2.The interrupt source must be set to take place either on the falling or the rising edge of the signal.
3.The external interrupt flag (INTF in the INTCON Register) must be initially cleared.
4.Global interrupts must be enabled by setting the GIE bit in the INTCON Register.
5.The External Interrupt on RB0 must be enabled by setting the INTE bit in the INTCON Register.
The following code fragment, from the program RB0Int in the book’s online software package, performs these operations:
;============================= ; interrupt handler ;=============================
org 0x04 goto IntServ
;=============================
;main program ;============================= main:
;Set up interrupt on falling edge
;by clearing OPTION register bit 6 movlw b’10111111’
option
movlw |
b’11111111’ |
; Set Port-A |
for input |
tris |
porta |
; (not necessary for this program) |
|
movlw |
b’00000001’ |
; Port-B bit |
0 is input |
tris |
portb |
; all others |
are output |
clrf |
portb |
; All Port-B |
to 0 |
; Initially turn on LED |
|
|
|
bsf |
portb,0 |
; Set line 0 |
bit |
;============================ |
|
;setup interrupts ;============================
;Clear external interrupt flag (intf = bit 1)
bcf |
INTCON,intf |
; Clear flag |
;Enable global interrupts (gie = bit 7)
;Enable RB0 interrupt (inte = bit 4)
|
bsf |
INTCON,gie |
; |
Enable |
global int (bit |
7) |
|
bsf |
INTCON,inte |
; |
Enable |
RB0 int (bit 4) |
|
;============================ |
|
|
|
|
||
; |
flash LED |
|
|
|
|
Interrupts |
221 |
;============================
; Program flashes LED wired to Port-B, line 2 lights:
movlw |
b’00000010’ |
; Mask with bit 1 set |
xorwf |
portb,f |
; Complement bit 1 |
call |
long_delay |
; Local delay routine |
call |
long_delay |
|
call |
long_delay |
|
goto |
lights |
|
RB0 Interrupt Service Routine
The Service Routine for the RB0 interrupt depends on the specific application. Nevertheless, the following processing steps should be considered:
1.Determine if the source is an RB0 interrupt.
2.Clear the RB0 interrupt flag (INTF bit) in the INTCON Register.
3.Save the context. Which registers and variables need to be saved depends on the specific application.
4.Perform the interrupt action.
5.Restore the context.
6.Return from the interrupt with the retfie instruction.
In addition, the interrupt handler may have to perform operations that are specific to the application. For example, debounce a switch or initialize local variables. The following Interrupt Service routine is from the program RB0Int in the book’s online software:
;=======================================================
; |
Interrupt Service Routine |
;=======================================================
;Service routine receives control when there is
;action on pushbutton switch wired to port-B, line 0 IntServ:
;First test if source is an RB0 interrupt
btfss |
INTCON,INTF |
; INTF flag |
is RB0 interrupt |
goto |
notRB0 |
; Go if not |
RB0 origin |
; Save context |
|
|
|
movwf |
old_w |
; Save w register |
|
swapf |
STATUS,w |
; STATUS to |
w |
movwf |
old_status |
; Save STATUS |
;=========================
;interrupt action ;=========================
;Debounce switch
;Logic:
;Debounce algorithm consists in waiting until the
;same level is repeated on a number of samplings of the
222 |
Chapter 11 |
;switch. At this point the RB0 line is clear since the
;interrupt takes place on the falling edge. The routine
;waits until the low value is read several times.
movlw |
D’10’ |
; |
Number of repetitions |
movwf |
count2 |
; |
To counter |
wait:
;Check to see that port-B bit 0 is still 0
;If not, wait until it changes
btfsc |
portb,0 |
; |
Is |
bit set? |
|
goto |
exitISR |
; |
Go |
if |
bit not 0 |
; At this point RB0 bit is clear |
|
||||
decfsz |
count2,f ; |
Count |
this iteration |
||
goto |
wait |
|
|
|
; Continue if not zero |
;Interrupt action consists of toggling bit 2 of
;port-B to turn LED on and off
movlw |
b’00000100’; Xoring with a 1-bit produces |
||
|
; |
the complement |
|
xorwf |
portb,f ; |
Complement bit |
2, port-B |
;=========================
;exit ISR ;========================= exitISR:
;Restore context
swapf |
old_status,w |
; Saved status to w |
|
movfw |
STATUS |
; To STATUS register |
|
swapf |
old_w,f |
; Swap file register in itself |
|
swapf |
old_w,w |
; re-swap back to w |
|
notRB0: |
|
|
|
; Reset interrupt |
|
|
|
bcf |
INTCON,intf |
; Clear INTCON bit 1 |
|
retfie |
|
|
|
Note that the interrupt handler listed previously contains a debouncing routine that cleans the switch’s signal. In this particular implementation the detection of a signal of the wrong value determines that the interrupt is aborted. For the particular switch used in the test circuit this approach seemed to work better. Alternatively, the routine can be designed so that if a wrong edge is detected, execution continues in the wait loop. In any case, the entire complication of software debouncing can be avoided by debouncing the switch in hardware.
11.3.2 Wakeup from SLEEP Using the RB0 Interrupt
The PIC microcontroller sleep mode provides a useful mechanism for saving power. It is particularly useful in battery-operated devices.
The sleep mode is activated by executing the SLEEP instruction; it suspends all normal operations and switches of the clock oscillator.
Interrupts |
223 |
The sleep mode is suitable for applications that are not required to run continuously. For example, a device that records temperature at daybreak can be designed so that a light-sensitive switch generates an interrupt that turns the device on each morning. Once the data is recorded, the device goes into the sleep mode until the next daybreak.
Several events can make the device wake up from the sleep mode:
1.A device reset on the !MCLR pin
2.Watchdog timer wake-up signal, if WDT is enabled
3.Interrupt on RB0 line
4.Port change interrupt on RB4 to RB7 lines
5.EEPROM write complete interrupt
In the sleep mode, the device is placed on a power-down state that generates the lowest power consumption. The system clock is turned off in the sleep mode so signals that depend on the clock cannot be used to terminate the sleep. If enabled, the Watchdog Timer is cleared by the sleep instruction but keeps running. The PD bit in the STATUS register is also cleared and the TO bit is set. The ports maintain the status they had before the SLEEP instruction was executed.
The TO and PD bits in the STATUS register can be used to determine the cause of wake-up, since the TO bit is cleared if a Watchdog Timer wake-up took place. The corresponding interrupt enable bit must be set for the device to wake-up up due to an interrupt. Wake-up takes place regardless of the state of the General Interrupt Enable (GIE) bit. If the bit is clear, the device continues execution at the instruction following SLEEP. Otherwise, the device executes the instruction after the SLEEP instruction and then branches to the interrupt address. If the execution of the instruction following SLEEP is undesirable, the program should contain a NOP instruction after the SLEEP instruction.
The SleepDemo Program
The program named SleepDemo in the book’s online software package is a trivial demonstration of using the RB0 interrupt to wake the processor from sleep mode. The program can be tested using the circuit in Figure 11-4. SleepDemo flashes the green LED at ½ second intervals during 20 iterations and then goes into sleep mode. Pressing the pushbutton switch on line RB0 generates an interrupt that wakes the processor from sleep mode. The following code fragment shows the coding of the main loop in the program:
;============================
;flash LED 20 times ;============================ wakeUp:
;Program flashes LED wired to port-B, line 2
;20 times before entering the sleep state
movlw |
D’20’ |
; |
Number of iterations |
movwf |
count2 |
; |
To counter |
224 |
|
Chapter 11 |
lights: |
|
|
movlw |
b’00000010’; Mask with bit 1 set |
|
xorwf |
portb,f |
; Complement bit 1 |
call |
long_delay |
|
call |
long_delay |
|
call |
long_delay |
|
decfsz |
count2 |
; Decrement counter |
goto |
lights |
|
; 20 iterations have taken place |
||
clrwdt |
|
; Clear WDT |
sleep |
|
|
nop |
|
; Recommended! |
goto |
wakeUp |
; Resume execution |
In the SleepDemo program the Interrupt Service Routine does nothing. Its coding is as follows:
;=======================================================
;Interrupt Service Routine ;=======================================================
;The interrupt service routine performs no operation IntServ:
bcf |
INTCON,INTF |
; Clear flag |
retfie
The initialization of the RB0 interrupt is identical to the one in the RB0Int program previously listed.
11.3.3 Port-B Bits 4-7 Status Change Interrupt
In the PIC 16F84 microcontroller, a change of input signal on Port-B, lines 4 to 7, generates an interrupt. This interrupt sets the RBIF bit in the INTCON Register to indicate that at least one of the ports have changed value. The port change takes place when the port’s previous value changes from logic one to logic zero or vice versa. In order for port pins to recognize this interrupt, they must have been defined as input. If any one of the port pins (4 to 7) is defined as output the interrupt takes place. The status change of the ports is in reference to the last time port-B was read.
The principal application of this interrupt source is in detecting several different interrupt sources. Its principal disadvantage is that it forces the declaration of four port-B lines as input, although during processing not all lines need be recognized as interrupt sources. The conclusion is that applications that only need a single external interrupt source should use the RB0 interrupt described in previous sections. Only applications that require more than one external interrupt should use the Port-B lines 4 to 7 interrupt on change source.

Interrupts |
225 |
Since the interrupt takes place on any status change (high-to-low or low-to-high) the service routine executes on both signal edges. If interrupt processing is required on only one edge, that is, either when the port goes high or low, then the filtering must be performed in software. The circuit in Figure 11-5 allows testing the Port-B Status Change Interrupt.
+5 V |
+5 V |
4 MHz |
|
|
|
|
|
|
|
|
|
4.7K Ohm |
|
|
|
|
|
|
|
|
|
|
|
4.7K Ohm |
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
Osc |
|
|
|
|
|
|
|
|
|
|
|
|
+5 V |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
16 |
|
15 |
|
14 |
|
|
|
|
|
|
|
|
|
|
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
18 |
|
|
|
|
|
13 |
|
12 |
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
RA1 |
RA0 |
OSC1 OSC2 |
Vdd |
|
RB7 |
|
RB6 |
|
RB5 |
RB4 |
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
green |
|
|
|
|
|
|
|
16F84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
red |
|
|
|
|
RA2 |
|
|
T0Tkl |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
RA3 |
MCLR Vss |
RB0/INT RB1 |
|
RB2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
RB3 |
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
2x470 Ohm
+5 V
10K Ohm
Figure 11-5 Circuit for Testing the Port-B Status Change Interrupt
In the circuit of Figure 11-5, a pushbutton switch is wired to the RB7 port and another one to RB4. Both of these switches produce the interrupt when pressed. A red LED is wired to port RA1 and a green LED to port RA0. The red and green LEDs are toggled on and off when the corresponding pushbutton switches are pressed. The switches contain a 4.7K Ohm resistor that keeps the port high until the contact is made and sent to ground. This makes both switches active low and the interrupt is programmed on the falling edge of the signal.
RB4-7 Interrupt Initialization
In order to initialize the RB4-7 change interrupt the following operations must take place:
1.Port-B lines 4 to 7 must be initialized for input.
2.The interrupt source must be set to take place either on the falling or the rising edge of the signal.
226 |
Chapter 11 |
3.The RB port change interrupt flag (RBIF in the INTCON Register) must be initially cleared.
4.Global interrupts must be enabled by setting the GIE bit in the INTCON Register.
5.The RB port change interrupt must be enabled by setting the RBIE bit in the INTCON Register.
6.Internal pull-ups on port-B should be disabled in the OPTION register.
The following code fragment from the program RB4to7Int in the book’s online software package shows the required processing:
;=============================
;main program ;============================= main:
;Disable port-B internal pull-ups
;Interrupts on falling edge of pushbutton action
|
Movlw |
|
|
|
|
b’10111111’ |
|||
|
option |
|
|
|
|
|
|
||
; Wiring: |
|
|
|
|
|
|
|
|
|
; |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
<= port-B |
; |
| |
|
|
|_______________ red pushbutton |
|||||
; |
|________________________ black pushbutton |
||||||||
; |
|
|
|
|
|
|
|
|
|
; |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
<= Port-A |
; |
|
|
|
|
|
|
| |
|_____ red LED |
|
; |
|
|
|
|
|
|
|________ green LED |
||
; |
|
|
|
|
|
|
|
|
|
|
movlw |
|
b’00000000’ |
|
; Set Port-A for ouput |
||||
|
tris |
|
porta |
|
|
|
|
||
|
movlw |
|
b’11110000’ |
|
; Port-B bit 0-3 are output |
||||
|
|
|
|
|
|
|
|
|
; bits 4-7 are input |
|
tris |
|
portb |
|
|
|
; all others are output |
||
|
clrf |
|
portb |
|
|
|
; All port-B to 0 |
||
|
movlw |
|
b’00000000’ |
|
; Zero to w |
||||
|
movwf |
|
bitsB47 |
|
|
; Store in local variable |
|||
; Initially turn on LEDs |
|
|
|
||||||
|
bsf |
|
porta,0 |
|
|
; Set LEDs on line 0 |
|||
|
bsf |
|
porta,1 |
|
|
; and on line 1 |
;============================
;setup interrupts ;============================
;Clear external interrupt flag (intf = bit 1)
bcf |
INTCON,rbif |
; Clear flag |
;Enable global interrupts (gie = bit 7)
;Enable RB0 interrupt (inte = bit 4)
bsf |
INTCON,gie |
; |
Enable |
global int (bit |
7) |
bsf |
INTCON,rbie |
; |
Enable |
RB0 int (bit 3) |
|
Interrupts |
227 |
RB4-7 Change Interrupt Service Routine
The Service Routine for the RB4-7 change interrupt depends on the specific application. Nevertheless, the following processing steps should be considered:
1.Determine if the source is an RB4-7 change interrupt.
2.Clear the RBIF interrupt flag in the INTCON Register.
3.Save the context. Which registers and variables need to be saved depends on the specific application.
4.Perform the interrupt action.
5.Restore the context.
6.Return from the interrupt with the retfie instruction.
In addition, the interrupt handler may have to perform operations that are specific to the application; for example, debounce a switch or initialize local variables. The following Interrupt Service routine is from the program RB4to7Int in the book’s online software:
;=======================================================
; |
Interrupt Service Routine |
;=======================================================
;Service routine receives control whenever any of
;port-B lines 4 to 7 change state
IntServ:
; First test: make sure source is an RB4-7 interrupt
btfss |
INTCON,rbif |
; RBIF flag is interrupt |
goto |
notRBIF |
; Go if not RBIF origin |
; Save context |
|
|
movwf |
old_w |
; Save w register |
swapf |
STATUS,w |
; STATUS to w |
movwf |
old_status |
; Save STATUS |
;=========================
;interrupt action ;=========================
;The interrupt occurs when any of port-B bits 4 to 7
;have changed status.
movf |
portb,w |
; Read port-B bits |
|
movwf |
temp |
; Save reading |
|
xorwf |
bitsB47,f |
; |
Xor with old bits, |
|
|
; |
result in f |
; Test each meaningful bit (4 and 7 in this example)
btfsc |
bitsB47,4 |
; Test bit 4 |
goto |
bit4Chng ; Routine for changed bit 4 |
|
; At this point bit 4 did not change |
||
btfsc |
bitsB47,7 |
; Test bit 7 |
goto |
bit7Chng ; Routine for changed bit 7 |
|
; Invalid port line change. Exit |
|
|
goto |
pbRelease |
|
228 |
Chapter 11 |
;========================
;bit 4 change routine ;========================
;Check for signal falling edge, ignore if not bit4Chng:
btfsc |
portb,4 |
; Is bit |
4 high |
goto |
pbRelease |
; Bit is |
high. Ignore |
; Toggling bit 1 of Port-A turns LED on and off |
|||
movlw |
b’00000010’ |
; Xoring |
with a 1-bit produces |
|
|
; the complement |
|
xorwf |
porta,f |
; Complement bit 1, Port-A |
|
goto |
pbRelease |
|
|
;======================== |
|
|
;bit 7 change routine ;========================
;Check for signal falling edge, ignore if not bit7Chng:
btfsc |
portb,7 |
; Is bit 7 high |
goto |
exitISR |
; Bit is high. Ignore |
; Toggling bit 0 of Port-A turns LED on and off |
||
movlw |
b’00000001’ |
; Xoring with a 1-bit produces |
|
|
; the complement |
xorwf |
porta,f |
; Complement bit 1, Port-A |
; |
|
|
pbRelease: |
|
|
call |
delay |
; Debounce switch |
movf |
portb,w ; Read port-B into w |
|
andlw |
b’10010000’ ; Eliminate unused bits |
|
btfsc |
STATUS,z ; Check for zero |
|
goto |
pbRelease |
; Wait |
;At this point all port-B pushbuttons are released ;=========================
;exit ISR
;========================= |
|
||
exitISR: |
|
|
|
; Store new value of port-B |
|
||
movf |
temp,w |
|
; This port-B value to w |
movwf |
bitsB47 |
|
; Store |
; Restore context |
|
|
|
swapf |
old_status,w |
; Saved status to w |
|
movfw |
STATUS |
; To STATUS register |
|
swapf |
old_w,f |
; Swap file register in itself |
|
swapf |
old_w,w |
; re-swap back to w |
|
; Reset,interrupt |
|
|
|
notRBIF: |
|
|
|
bcf |
INTCON,rbif |
; Clear INTCON bit 0 |
|
retfie |
|
|
|