pic interrupt secrets

83

Click here to load reader

Upload: reinaldo-alves

Post on 23-Nov-2015

438 views

Category:

Documents


70 download

TRANSCRIPT

  • Effective PIC Interrupts

    How to Make Projects FlyUsing Interrupts

    http://www.best-microcontroller-projects.com Page 1 of 83.

  • Effective PIC Interrupts

    1 Other Resources1.1 PIC C Course

    A Complete C course for PIC micros in 11 parts.

    CLICK the image above.

    Or Click Here

    http://www.best-microcontroller-projects.com Page 2 of 83.

  • Effective PIC Interrupts

    1.2 Learn To Use state Machines To Maximum Effect.

    How to use state machines to create Solutions to complex problems including fully debugged examples one is coding a scrolling menu on a standard LCD display.

    CLICK the Image Above

    Or Click Here.

    http://www.best-microcontroller-projects.com Page 3 of 83.

  • Effective PIC Interrupts

    How to Make Projects FlyUsing Interrupts

    V1.01

    By John Main

    Copyright John Main 2008

    Understanding How and Why Interrupts

    work lets You Optimize them for any processor.

    Using the techniques in this document you can learnhow to manage and optimize interrupts as well as useprovided C templates that makes using interrupts easy.

    History : V1.01 Nov 08 : Updated for 18F interrupts.

    Copyright 2008 John Main

    http://www.best-microcontroller-projects.com

    All rights reserved. No part of this eBook may be reproduced, stored in a retrieval system or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise without express written, dated and signed permission from the author John Main.

    http://www.best-microcontroller-projects.com Page 4 of 83.

  • Effective PIC Interrupts

    Table of Contents1 Other Resources........................................................................ ..............2

    1.1 PIC C Course........................................... .........................................21.2 Learn To Use state Machines To Maximum Effect....................................3

    2 Legal........................................................................ .............................83 Introduction......................................................................................... ...9

    3.1 From Polling To Interrupts....................................................... ............93.2 Real Time Events................................................... ..........................103.3 Achieving More Using Interrupts........................................................ .113.4 Why Interrupts are Essential for Critical Inputs.................................. ...113.5 Power Saving................................................. .................................12

    4 Interrupts.............................................................................. ...............134.1 The Interrupt Module.................................................................. ......134.2 Polling disadvantages .................................. ....................................134.3 The Power of Interrupts........................................ ............................144.4 How Does An Interrupt Affect The Main Code?................................... ...154.5 How to Ensure Interrupts and Main code Work.....................................164.6 Avoiding Accidental Code Increase In the ISR......................................16

    4.6.1 Data Types............................................................................ ....174.6.2 Hidden Library Code................................................ ...................17

    5 How Interrupts Work........................................................ ......................175.1 Instruction cycle.................................................... ..........................17

    6 Interrupt Service Routine (ISR)............................................................. ...186.1 ISR : Interrupt Service Routine........................................ ..................196.2 Interrupt Vector...................................................................... .........196.3 Interrupt Code..................................... ...........................................206.4 Context Switching........................................................... .................21

    6.4.1 Saving The Current State........................................ ....................216.4.2 Saving the Program Counter............................................ ............216.4.3 Bank Context Saving........................................ ..........................21

    7 Coding PIC Interrupts................................................................ .............217.1 PIC Interrupt Registers.......................................... ...........................227.2 PIR Peripheral Interrupt Register State (Flag)................................... ....237.3 Peripheral Interrupt Enable PIE (Enable).............................................. 23

    7.3.1 Interrupt Masks.................................................. .......................237.4 INTCON Original Interrupt Control Register.......................................247.5 Global And Peripheral Interrupt Enable.................................... ............24

    7.5.1 GIE............................................................................. .............247.5.2 PEIE....................................................................................... ..25

    7.6 Using the Interrupt Flag Registers......................................................257.7 Interrupt Flow Diagram................................................................ .....27

    http://www.best-microcontroller-projects.com Page 5 of 83.

  • Effective PIC Interrupts

    7.8 Interrupt Design Decisions................................ ................................287.8.1 Processing / Interrupt Time Analysis.............................................297.8.2 Three Interrupt Design Solutions .................................... .............307.8.3 Effect of using a 20MHz clock..................................................... ..30

    8 Design techniques.............................................................................. ....318.1 Using FLAGS to communicate from ISR to main Program ......................318.2 'Interrupt Cascade'.......................................................... ..............328.3 Measuring the ISR time.............................. ......................................34

    8.3.1 Direct Pin Monitoring....................................... ...........................348.3.2 Simulating Interrupts.................................................................34

    8.3.2.1 Using #define Macros............................... ............................358.3.3 Using A Timer.......................................................................... ..35

    8.3.3.1 Viewing the Timer Value..................................................... ...369 An Error You Must Avoid.............................. ...........................................3710 18F Series Interrupts................................................................... .........39

    10.1 High or Low Priority Interrupts: Reason for Usage...............................3910.2 Hardware for Prioritized Interrupts.............................................. ......3910.3 Prioritized Interrupt Mechanism.............................................. ..........4010.4 Priority Enable Control Bit (backwards compatibility)...........................4110.5 18F Series Registers.................................................. .....................4210.6 18F Context Saving............................................. ...........................42

    10.6.1 Fast Register Stack....................................................... ............4310.6.1.1 Using the Fast Register Stack for normal function calls.............43

    11 Examples.............................................................................. ..............4311.1 Hardware & Software ......................................................... ............43

    11.1.1 Hardware................................................................ ................4311.1.2 Serial port configuration............................................ ................4411.1.3 16F88 Hardware Diagram.......................................... ................4511.1.4 18F2550 Hardware Diagram......................................................4611.1.5 Software Downloads.......................................... .......................46

    11.1.5.1 C Compiler download.................................. ........................4611.1.5.2 ICPROG........................................... .................................4611.1.5.3 WinPic (for the 18F2550 and many others)............................47

    11.2 Interrupt Template........................................... ..............................4711.2.1 Interrupt Template Code Action.............................. ....................4811.2.2 Interrupt Template C Code....................................................... ..48

    11.3 16F Heartbeat Timer................................................................... ....5111.3.1 16F Heartbeat Timer Code Action...............................................5111.3.2 16F Heart Beat Timer C Code....................................... ..............51

    11.4 Transmit Interrupts (no code but some important information).............5611.5 RS232 Interrupt Reception..............................................................57

    11.5.1 16F RS232 Interrupt Reception Code Action.................................57

    http://www.best-microcontroller-projects.com Page 6 of 83.

  • Effective PIC Interrupts

    11.5.2 16F RS232 Interrupt Reception C Code................................ ........5711.6 Simple Flag Example............................... .......................................62

    11.6.1 16F Simple Flag Interrupt Code Action........................................6211.6.2 16F Simple Flag Interrupt C Code...............................................62

    11.7 Interrupt Simulation using Macros....................................................6611.7.1 16F Interrupt Simulation Code Action..........................................6611.7.2 16F Interrupt Simulation C Code................................................68

    11.8 18F Interrupt Driven Blinking LED Example........................................7111.8.1 18F Interrupt Driven Blinking LED Code Action.............................7111.8.2 18F Interrupt Driven Blinking LED C Code....................................72

    11.9 18F Prioritized Interrupt Example.....................................................7511.9.1 18F Prioritized Interrupt Code Action................................. ..........7611.9.2 Priority Effect on LED at PORTB..................................................7711.9.3 18F Changing the interrupt priority.............................................7711.9.4 18FPrioritized Interrupt C Code..................................................77

    12 Highlights........................................................ ...................................82

    http://www.best-microcontroller-projects.com Page 7 of 83.

  • Effective PIC Interrupts

    2 Legal Copyright 2008 John Main

    http://www.best-microcontroller-projects.com

    All rights reserved. No part of this eBook may be reproduced, stored in a retrieval system or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise without express written, dated and signed permission from the author John Main.

    DISCLAIMER AND/OR LEGAL NOTICES:

    The information presented herein represents the view of the author as of the date of publication. Because of the rate with which conditions change, the author reserves the right to alter and update his opinion based on the new conditions. The report is for informational purposes only. While every attempt has been made to verify the information provided in this report, neither the author nor his affiliates/partners assume any responsibility for errors, inaccuracies or omissions. Any slights of people or organizations are unintentional. If advice concerning legal or related matters is needed, the services of a fully qualified professional should be sought. This report is not intended for use as a source of legal or accounting advice. You should be aware of any laws which govern business transactions or other business practices in your country and state. Any reference to any person or business whether living or dead is purely coincidental.

    http://www.best-microcontroller-projects.com Page 8 of 83.

  • Effective PIC Interrupts

    3 IntroductionInterrupts are used in all systems from simple microcontroller projects up to PC based desktop processors but each processor is only capable of performing one instruction at a time. It's important to note this since computers seem capable of any number of actions simultaneously (In fact they can only achieve this trick using interrupts).

    The magic of interrupts is their ability to make it appear that:

    A Single-Instruction-At-A-Time Processor

    Can Perform Multiple Processes ALL at the Same Time

    An interrupt allows the main processor code to be halted while a sub process takes over the device and performs a small task. It then returns control to the main program without the main program being aware that it was interrupted.

    Because the interrupt code is small (Note: you must ensure that it is kept small!) the time used by the interrupt is small and it looks like both the main program and the interrupt code are working at the same time.

    Note: Factors such as the size of the interrupt code, device processing power and affect the speed of the main code and you have to balance out these factors to find a workable solution for your design problem See Chapter 7.8.

    Interrupt magic really does work if the processing speed of the device is fast because when main code and interrupt code are executed quickly, it looks like simultaneous execution.

    In fact you could say that if the processor is working fast enough then these processes really are happening at the same time (within a finite time frame) i.e. if all these processes are happening within a millisecond then they are happening at the same time (within the discrete time unit of a millisecond!).

    3.1 From Polling To InterruptsPolling means looking at a signal at regular intervals i.e. it's what you do before you use interrupts and it's the most natural way to start programming a microcontroller. It is a useful method but interrupts provide a superior technique in solving your programming problem because they allow large and complex programs to work while many smaller tasks are handled directly by the interrupt code.

    http://www.best-microcontroller-projects.com Page 9 of 83.

  • Effective PIC Interrupts

    Without interrupts the only way that an external event (signal change on a pin or internal peripheral update) can be detected is for the program to periodically look at the input pin (known as polling) but this must be done while fitting in all the other program actions e.g. calculations/update screens etc.

    Polling is a suitable method only if the processing load is low i.e. Only if you can go round the loop fast enough to ensure that you will never miss an input event. This is a design decision either the event must be slow enough compared to the processor execution time or the event must be non critical i.e. You can afford to wait a while before processing it or possibly miss it altogether.

    For critical systems if an event happens while the processor is busy processing other instructions it is ignored and this can have implications for your program because missing data can cause the program to hang or your system to fail.

    Note: If you do not want to use interrupts for some reason it is still possible to interrogate the state of internal peripherals because each peripheral that generates an interrupt sets a flag to indicate that the interrupt action occurred (even when the the real interrupt is not enabled). If you poll this flag then you will be able to detect the event and do not need any interrupt code e.g. for receiving RX serial data poll the RX module continuously reading the RX flag. This method is only recommended for testing using small sections of code and is not the best way you really should use interrupts for best performance and ease of coding (as a program gets bigger polling gives problems whereas interrupt code is not affected by the main program size).

    3.2 Real Time EventsA Real Time Event is an event that is not synchronized to the processor clock so it can happen at any random time e.g. a key press is a Real Time Event. To detect it reliably you either have to poll an input pin continuously (wasting processing power and battery power) or you use an interrupt (using one of the input pins that has an interrupt associated with it e.g. PORTB, or INT on a PIC microcontroller).

    Interrupts mean that a processor can run a main program and at the same time process multiple critical signals including Real Time Event signals. For instance it could receive a byte from the RS232 port as well as from an signal change on an external pin (and/or other internal modules). Typically the interrupting module will store the data/event until the processor can service the interrupt.

    Note: Interrupts can occur at the same time since each peripheral module has it's own hardware register(s) that store the data and you can service multiple interrupts in the same interrupt code.

    So real time events can easily be captured using interrupts even while the

    http://www.best-microcontroller-projects.com Page 10 of 83.

  • Effective PIC Interrupts

    processor is executing other code in a very efficient way without a huge processing overhead i.e. without wasting time.

    Interrupts are the only feasible way that a processor can react to real time events i.e. external signal changes on pins or internal events; when you code up large and complex programs.

    3.3 Achieving More Using InterruptsSome hardware modules (with interrupts outputs i.e. Most internal peripheral modules in the PIC microcontrollers) allow you to measure real world parameters that you could not possibly measure using only a 'polling' processing method. For instance the Capture Compare module can measure very small time differences between input edges of a signal and then give an interrupt to tell the processor to store the values captured. These timing intervals are much finer than using the equivalent 'software code' to read the input port state because the software can only run at the processor speed and not at the discrete speed of the hardware i.e. the speed of standard logic gates.

    Note: There are about 15 interrupt sources in a PIC and most of these are triggered from within an internal peripheral hardware module at the completion of each hardware task. All of these can be used together and even at the same time using interrupts to manage them.

    3.4 Why Interrupts are Essential for Critical InputsCapturing a real time event can be crucial for a system to operate safely since it is the only fast and reliable way for an event to be detected especially if the main code is large and complex (slow).

    To illustrate why interrupts can be essential for critical system operations consider making a program using only the polling method without using interrupts.

    Consider a normal linear program that must do multiple tasks such as processing a screen, then the keyboard, then the rs232 interface and then computing a complex calculation.

    At any given moment the processor will be engaged in any one of these tasks and it is a matter of luck whether or not a key press is detected at the keyboard. If the tasks are small and the computation is easy then the processor could whizz around the code and the key would be detected but if not, i.e. if the computation is complex then the main program could be stuck for some time and not get around to checking the keyboard.

    In some cases this may not matter but if you are making a critical real time system where you must ensure that some piece of machinery must be turned off

    http://www.best-microcontroller-projects.com Page 11 of 83.

  • Effective PIC Interrupts

    for safety then an interrupt would be the best method (for a life threatening system you would employ extra fail safe hardware). You would create a system with an interrupt from a keyboard so that this real-time-event could be serviced immediately saving the system from disaster.

    Interrupts are useful in detecting Real Time Events Because:

    They are actioned immediately (within a few instruction cycles).

    They do not require large overhead of code.

    They avoid potential problems such as code lock up (crash) in the main code (the interrupt code can not easily lock up unless you really mess up the interrupt software!).

    Note: Code lock up can also be mitigated by using the watch dog timer (WDT). The purpose of the WDT is to reset the processor if the WDT is not cleared within a certain amount of time. N.B. Never clear the WDT from within the ISR (interrupt code) as it's cheating and makes the WDT useless but always clear the WDT periodically from within the main code. This way when or if the main locks up the WDT triggers and the processor resets restarting the code from the beginning. It is a crude way of ensuring that the processor does not lock up forever and is really only a fallback method since it does not save the current state of the program. The advantage is that the system will recover from unforeseen software errors

    The interrupt code will still operate even if the main code locks up because main code even when locked up is still executing individual machine code instructions that can still be interrupted e.g. if main code is stuck in a loop waiting for an input or a computation to complete. This is why the interrupt code will continue even if it looks like the system has died and it is why critical input monitoring can be safely performed using interrupts as long as the critical action (that must be performed as a result of the interrupt) is performed in the ISR itself not in the main code.

    Note: It does assume that you thoroughly test and simulate the interrupt code to ensure that it is correct but since it should be a small piece of code this should not be a problem.

    3.5 Power SavingAnother use for interrupts is creating low power systems, since some interrupts can wake the processor from low power sleep mode so saving power until you need the processor to do some work. Compare this to polling where the processor is continuously active, doing no real work wasting battery power.

    Note: Some of the PIC processors employ Nanowatt technology meaning they can

    http://www.best-microcontroller-projects.com Page 12 of 83.

  • Effective PIC Interrupts

    run for the standard shelf life of a battery if they are put into this low power mode e.g. 16F88.

    4 Interrupts

    4.1 The Interrupt ModuleThe Interrupt module is a module attached to the processor that stops the processor after it finishes the current machine code instruction and forces a jump (via the interrupt vector) to another program (the ISR Interrupt Service Routine).

    Note: You won't find the Interrupt module shown on the PIC data sheet diagrams because interrupts affect (and are attached to) many of the internal peripherals and pins and it would make the diagrams too complex.

    Note: Instructions in PIC microcontrollers are pipelined so the interrupt latency (the time before the ISR is called) is not one instruction time it is in fact from 3 instructions (internal interrupt) and from 3 to 3.75 instructions (external). In addition for external interrupts the latency depends on when the signal occurs in the current instruction cycle i.e. Because the input signal is unsynchronized with the processor clock. Latency occurs because the pipeline must be cleared before executing the new instructions in the ISR.

    Compared to simple pin polling to detect a signal change, interrupts appear complex and difficult to use. It's true that you do need more code and you do need to understand more details but this document explains interrupts in a general sense (applicable to any processor) and shows you template code that you can use in your PIC projects to easily manage any interrupt and its associated hardware module.

    This means you will be able to easily use interrupts and interrupts make complex operation easier because they separate processes into instantly executed code located in the ISR i.e. they separate out small blocks of easily managed code which is more robust than having code blocks executed one after another in the main code.

    4.2 Polling disadvantages For a simple system you may decide Not to use interrupts instead polling the resource .e.g the keypad, then the RS232 interface and then the sensor input. You would do this continuously in a loop of code repeatedly checking each resource until something happens i.e. A key is pressed, data received or and input from the sensor is received. This quite often happens when you develop a

    http://www.best-microcontroller-projects.com Page 13 of 83.

  • Effective PIC Interrupts

    simple system since it's easy to do and it does work.

    The problem comes when you have to do something else or react to more inputs or when you make the program larger. All of these increase the execution time of the loop so it takes longer to get around to processing each input.

    Polling does work if the processing time is coded carefully to keep it to a minimum compared to the expected rate of input data from the input resources but you have to very carefully design the system and if you change or add resources you will need to think again and possibly re-design.

    It is in fact easier to use interrupts since the main program can be altered without affecting the operation of the whole system. But this is only true if the ISR time is small compared to the main code execution time i.e. you must keep the ISR code as short as possible - in general keep the interrupt code a short as possible and make every attempt to move any complex processing operation out of the interrupt and into the main code i.e. Use flags to move code out of the ISR (page 31).

    If the ISR is too long and so long that the main code does not have enough time to do it's job then continuous interrupts can overload the main code before it has finished processing data from the previous interrupt and this will lock up the system i.e. it will crash.

    Note: As with all system design it is a balancing act where you have to decide on the correct size of ISR and main code size and it all depends on the problem to be solved and other system features - see Chapter 7.8 for system design trade off decisions that you can use to improve system performance.

    4.3 The Power of InterruptsInterrupts allow you to create small pockets of code that do a specific small task while the main program continues operating.

    For example if you use an RS232 interrupt module; when a byte of data is received by the module an interrupt is generated to interrupt the processor from it's current task. The module triggers an RS232 RX (receive) data interrupt.

    This tells you that some data is ready to be processed in the RS232 RX module and that you should do something about it within the ISR code. In the ISR you write some code that takes the data from the module and stores it for later processing by the main program (when it is ready to do so) or you can set a flag telling main code to read the module's data (as long as you know that the main code is capable of processing the data before the next byte is received at the serial port).

    Note: For complex systems a circular buffer will often be used to gather the

    http://www.best-microcontroller-projects.com Page 14 of 83.

  • Effective PIC Interrupts

    received RS232 data and this saves the main code from having to decode and store each byte of data typically the ISR circular buffer code will set a flag when a specific byte is received e.g. 'line return' this way the main code just has to recognize a complete text string. Circular buffers are more complex requiring use of pointers and code to ensure no data overruns within the buffer itself.

    Interrupts mean that the main program does not have to stop it's current operation to immediately process the incoming data it effectively happens in the background and the main program can processes the data when its ready.

    4.4 How Does An Interrupt Affect The Main Code?It appears to the main program that interrupts are serviced in the background with no effect on the main program but it is important to understand there is an effect on the operation of the main code. To understand why it's a good idea to see how interrupts work.

    The interrupt works like this:

    After completing the current instruction (plus pipeline delay),

    The the current location and state is stored,

    The interrupt code is executed,

    The original location and state is restored,

    The main program continues as before.

    When thinking about an interrupt you could say that the currently executing program is unaware of the interrupt code's action but it means the current code looses a few instruction cycles.

    In fact, the effect of the interrupt is to insert a delay into the main program and this delay is dependent on which parts of the interrupt code are executed and this will vary depending on the actual interrupts that are triggered i.e. The delay time due to the interrupt is unknown and random (unless you analyze the interrupt code very carefully or it has only one easy to analyze code section i.e. without multiple interrupts).

    This is why code that executes normally i.e. code outside of the interrupt function must be code that is timing insensitive i.e. You must not make code (outside the interrupt code) that depends on executing code in a specific fixed time; for instance if you created a delay routine carefully coded in assembler (in the main code area) to operate at a fixed delay time of 100us if interrupts were enabled then the 100us delay would be interrupted making it longer by a random amount depending on the and length of the interrupt routine itself.

    Note: This is why the seven segment frequency counter on site does not use

    http://www.best-microcontroller-projects.com Page 15 of 83.

  • Effective PIC Interrupts

    interrupts. The main code is carefully timed to allow a specific length execution time regardless of the path of execution of the code. Using interrupts would change this causing errors in frequency measurement.

    4.5 How to Ensure Interrupts and Main code WorkThe key problem with processors having low processing MIPS i.e. PICs is that you can not afford to throw away processing time. Interrupts do maximize your use of this time but you must be careful to design the code to share out processing time between the main code and interrupt code.

    If you think of the processing power of a device as a single bar below in blue.

    This box represents a visualization of the device code/MIPS.

    The red box represents the ideal interrupt code/MIPS.

    The above situation would be ideal where most of the processing time is spent performing main code actions and a highly optimized interrupt routine is small and efficient.

    The last diagram shows processing power shared out in the wrong way since more time/MIPS is spent in the interrupt routine than doing main code processing. If interrupts occurred at a high rate then the processor would be overloaded and would crash due to constant interrupts never allowing the main code to operate. On the flip side this design can work if you know that interrupts are infrequent and that's your design decision.

    See also Chapter 7.8 for other design decision trade off information.

    4.6 Avoiding Accidental Code Increase In the ISRIt is easy to accidentally make ISR fail by coding it wrongly but there are more subtle ways of making it fail and these are trickier to detect arise as a result of the convenience of the use of a high level language. The two main culprits are:

    Choosing the wrong data types.

    Hidden code libraries.

    http://www.best-microcontroller-projects.com Page 16 of 83.

  • Effective PIC Interrupts

    4.6.1 Data TypesSometimes you can accidentally make the interrupt routine large by something as simple as using the wrong data type or function in C which pulls in some library code that is far too long (but it is not visible in the code because it is done in the background for you). Examples of this are the floating point type which 8 bit processors are not good at and consequently require large amounts of code to support.

    4.6.2 Hidden Library CodeOn a project that I worked on a software designer used sprintf to debug output all within an interrupt and this caused intermittent operation because the actual sprintf code took different amounts of time depending on variables being output.

    It sounds like the most obvious way to debug code after all it is one way to debug embedded code i.e. by sending serial information out to a PC RS232 port. In the main code this technique does work well because it is simple, easy and convenient.

    The problem is that sprintf does a huge amount of work behind the scenes (i.e. it has a huge underlying code base) and when you use it parts of that library will be included in the code depending on the exact task you want it to do i.e. display a long as a formatted text string etc. So depending on which variable type you are currently debugging the time taken will vary. If you use it within the ISR then the variable time taken can cause the interrupt to take too long and fail.

    The solution was to remove the sprintf code then the interrupts worked perfectly!

    Note: Some compilers allow you to call functions from within the ISR (allowing easier partitioning of the ISR code) so watch out that you don't use hidden code or too big data types when coding these functions because those functions will look exactly like other 'normal' functions

    5 How Interrupts WorkTo understand interrupts it's a good idea to review the instruction cycle of the PIC processor as the interrupt mechanism must fit perfectly within it for interrupts to operate at all.

    5.1 Instruction cycleAll processors can only do one thing at a time i.e. They fetch an instruction, process it and then increase the program counter ready for the next repetition of this cycle. Moving to different code areas e.g. By jump or call is achieved by

    http://www.best-microcontroller-projects.com Page 17 of 83.

  • Effective PIC Interrupts

    manipulating the program counter (memory address) during the processing cycle.

    Whatever happens the processor must follow this simple scheme:

    DECODE : Instruction decode cycle

    READ : Read data cycle

    PROCESS : Data process cycle

    WRITE : Data write cycle

    Note: The Data Processing (PROCESS) part of the cycle will update the Program Counter increasing it by 1 for a normal instruction (to move to the next instruction) and increasing it by the data value(s) for a jump instruction) updated after the write cycle.

    This is why the PIC instruction frequency is times the main clock frequency since there are four actions completed in one instruction cycle e.g. A clock running at 4MHz lets instructions run at 1Mz (4MHz/4) or 1us. Each of the above actions takes 1 main clock period to perform.

    This cycle repeats endlessly with the program counter updated at the end of every instruction so all the processor can do is linearly execute sequential instructions or jump to a different address to execute another instruction.

    Designers realized that this system by itself does not allow a processor to react immediately to an external event making the processor fairly useless! So they added the ability to stop the processor mid-way through a program and jump to a different program i.e the Interrupt this jump address is known as the interrupt vector.

    The basic way that the interrupt works is by storing the current value of the program counter on the stack and then changing the program counter to the value held in the interrupt vector. On return from the ISR the Program counter is set back to the value on the stack so the program continues from exactly where it was previously.

    6 Interrupt Service Routine (ISR)There are two parts to an ISR (although strictly the ISR is just the interrupt code but the vector is tied directly to the ISR so they are treated as one here).

    The Interrupt Vector.

    The Interrupt Code.

    http://www.best-microcontroller-projects.com Page 18 of 83.

  • Effective PIC Interrupts

    6.1 ISR : Interrupt Service RoutineThe Interrupt Service Routine (ISR) is the only entry point (or function) called when an interrupt jump is triggered. This happens when an enable register bit is unmasked and when the corresponding interrupt flag is set by the hardware module that generates the interrupt when the module completes its action.

    The most important point about an interrupt routine is that it must be kept short unless you have a very good reason for doing otherwise.

    In general you need to keep it short so that:

    1. You can service many interrupts (as many as needed).

    2. You allow the main program to continue processing.

    Keeping the ISR short is another way of ensuring that there is enough time for the main program to have enough processing cycles to do it's job.

    6.2 Interrupt VectorAn interrupt vector is a dedicated hardware address that contains a jump location which is called when an interrupt occurs.

    The problem in understanding interrupts is that there is only one interrupt vector but multiple interrupts. The question is how do you service many interrupts using only one jump location (and consequently only one piece of interrupt code)?

    The short answer is to use a hardware solution using internal hardware registers.

    You have to detect exactly which interrupts were triggered by reading registers that store the interrupt state when the interrupt triggered and you do this as part of the Interrupt Service Routine code for all interrupts that will be active in your system.

    The interrupt vector is simply a location that contains an address and this address is programmed to contain the starting point of the ISR or the Interrupt Service Routine (your interrupt code function). In a PIC when any interrupt is triggered the contents of this vector location replaces the program counter i.e. the interrupt code is 'called' as an Interrupt Service Routine (ISR) the return address is also stored on the stack.

    Note: In the PIC 16 series the interrupt vector is at physical address 0x0004. You load this address with the address of your ISR so whenever the interrupt triggers then your ISR code is called. Often a high level language will do all the hard work for you and you don't even have to know this address since qualifying the function with the word 'interrupt' will tell the compiler that this function is to be an ISR. Remember some compilers require different notation as interrupts are not a part of the ANSI standard C specification. For instance MikroC looks for a

    http://www.best-microcontroller-projects.com Page 19 of 83.

  • Effective PIC Interrupts

    function named 'interrupt'.

    Note: Other processors may have more interrupt vectors but they all work in a similar way to a single interrupt vector. For instance others will have an NMI interrupt which means Non-Maskable-Interrupt this is simply an interrupt that can not be ignored and is reserved for absolutely critical system actions e.g. the device is about to be powered down (the PICs do not have this type of interrupt since the brown out device acts automatically if enabled). Also more interrupt vectors add more and more complexity to a device and require more code to service those interrupts.

    6.3 Interrupt CodeThe interrupt code (or ISR) is the single program function that you write to manage (or service) any interrupt that is triggered. It is the action point for any hardware modules that generate these interrupts and although it is a single piece of code (one function), it must contain code for each interrupt in use.

    For each interrupt that you enable (unmasked) there are three actions to be made in the ISR:

    Detect if the interrupt has triggered (test the flag bit in a PIR register).

    If the interrupt triggered clear the same flag bit to re-enable this interrupt.

    Perform actions that you want to execute due to this interrupt.

    Note: It is not necessary to re-enable the mask register (PIE) as this is not changed by the interrupt action so once enabled the interrupt is in use until the specific bit in the enable register (PIE) is cleared.

    The ISR is just another piece of code but you have to have some extra code surrounding the core ISR code to perform essential housekeeping tasks (or Context Switching). This includes a special machine code instruction RETFIE (RETurn From Interrupt Enable) as the very last instruction. This is why an interrupt function can never simply be a normal piece of code the routine you use must be flagged as an interrupt routine so that Context Switching can take place automatically for you.

    Note: Personal Computers use Software Interrupts which are triggered using a machine code instruction to generate an interrupt which causes execution of an ISR. There are no software interrupts in a PIC since it is a hardware centric device so all interrupts are generated by actions of hardware events e.g. a timer timeout (hardware timer becomes zero) or a signal change on an input pin e.g. PortB.

    http://www.best-microcontroller-projects.com Page 20 of 83.

  • Effective PIC Interrupts

    6.4 Context Switching

    6.4.1 Saving The Current StateTo make an interrupt useful it has to work seamlessly with the code that has been interrupted and to do this the state of the processor must be saved and restored before and after executing the interrupt.

    Fortunately the PIC micro only has a few registers that need saving (these are the ALU registers and not the file registers i.e. The internal registers W, PCLATH register and the STATUS register). In different processors there will be many more registers to preserve. This action is also known as context saving.

    6.4.2 Saving the Program CounterAs well as saving the register state the program counter must be stored so that the interrupt can return to the original code execution point.

    This is the only action the the 16F series processor will do for you all other actions must be done by writing more code around the interrupt routine itself. The PIC device will automatically push the Program Counter (PC) value to the stack when an interrupt is triggered. And at the end of an ISR you must execute the RETFIE (RETurn From Interrupt Enable) instruction which pops the Return address from the stack and enables the Global Interrupt flag.

    6.4.3 Bank Context SavingThe only other critical thing to look out for in the 16F series is that the segmented memory using bank switching must also be saved and restored. This is because an interrupt routine could make use of a different bank compared to the main program.

    Note: Most high level compilers will take care of Context Switching (including bank context switching) for you and this makes using interrupts even easier.

    7 Coding PIC InterruptsSee Chapter 11.2 for the Interrupt code template.

    The diagram below shows a generic hardware diagram of interrupt registers the mask or flag register (PIR) and the enable register (PIE).

    http://www.best-microcontroller-projects.com Page 21 of 83.

  • Effective PIC Interrupts

    7.1 PIC Interrupt RegistersBecause PIC devices have been around for quite some time and the new ones must be backwards compatible with the original (to allow as much code re-use as possible) the interrupt registers have been designed incrementally.

    In fact the new interrupt register layout is far easier to use because it is logically arranged whereas the original interrupt flags are squashed into a single register.

    So initially we'll talk about interrupts using the new register set and then backtrack to the original register.

    Note: From here on the term module refers to interrupts generated from internal hardware modules as well as external interrupts generated at a pin.

    For each peripheral module within the PIC microcontroller that generates an interrupt there are two register flags associated with it:

    The state flag - PIR register The enable flag PIE register

    http://www.best-microcontroller-projects.com Page 22 of 83.

  • Effective PIC Interrupts

    7.2 PIR Peripheral Interrupt Register State (Flag)

    Each of these is a single bit within a specific register - newer registers are labeled PIR Peripheral Interrupt Register (Flag) with a number on the end to allow multiple sets of these registers. Each bit in a PIR register is a flag telling you if the module generated an interrupt signal i.e. if the module was activated since the last time that the register bit was cleared.

    Note: Important : PIR flag bits are set even if the enable flags are not set i.e. interrupt flags show the (interrupt) state of the module even when all enables are not active (including GIE, PIE and PEIE). This allows software polling of the module even when no interrupt is actioned for the module.

    7.3 Peripheral Interrupt Enable PIE (Enable)Each of the PIE bits is a single bit within a specific register labeled in the same way as the PIR register except this is labeled PIE (E for enable). Each bit in a PIE register enables the corresponding hardware module to cause an interrupt action i.e. it makes the interrupt from the associated hardware module active so that it will cause a jump to the interrupt vector.

    Note: PIR and PIE registers are aligned so that the same bit position in each register services the hardware module allowing convenient bitwise operations. This is different to the original PIC devices that put all interrupt enables and flags into the INTCON register.

    7.3.1 Interrupt MasksThe PIE register can also be thought of as a mask register where each bit can be set or reset using bitwise operators and this allows you to enable or disable individual interrupt sources.

    Note: The process of setting (enabling) an individual interrupt enable bit is known as unmasking an interrupt.

    http://www.best-microcontroller-projects.com Page 23 of 83.

  • Effective PIC Interrupts

    For instance you may want to turn off a capture interrupt because at that particular time you are not ready to capture a trigger time value. Only when other code has executed e.g. you turn on a transducer, will you want to enable that interrupt. These flags allow that to happen but they also allow other interrupts to continue e.g. a timer interrupt can still count time as a background task.

    7.4 INTCON Original Interrupt Control RegisterThis is a single 8 bit register that exists on all the old and new PIC devices. Originally it was probably thought that there would not be many interrupts so all the enables and flags were placed in this register. As the range of devices has increased and the number of internal peripherals (with interrupt capability) has also increased so more interrupt space was needed hence the creation of PIR and PIE registers for interrupt expansion. A spare position in INTCON has been used to allow enabling of all other internal peripheral interrupts and is labeled PEIE just set this bit high if you are using any of the other internal peripheral interrupts (other than the three original ones detailed below).

    The existing interrupt flags and enables in this register are:

    Enables

    TIMER0IE (bit5)

    INT0IE (bit4)

    RBIE (bit3)

    Flags

    TIMER0IF (bit2)

    INT0IF (bit1)

    RBIF (bit0)

    These are for timer 0, external pin interrupt and PORTB interrupt respectively.

    7.5 Global And Peripheral Interrupt EnableThere's two registers for global control of interrupts and these both allow interrupts to cause a jump to the ISR routine.

    7.5.1 GIEThe first global interrupt flag is the GIE control flag or Global Interrupt Enable control). It is from the original PIC series and it is contained in the INTCON register. When set it allows all interrupts to operate and when cleared it prevents

    http://www.best-microcontroller-projects.com Page 24 of 83.

  • Effective PIC Interrupts

    all interrupts from operating (Note: This bit overrides the Peripheral Interrupt control PEIE).

    GIE is automatically cleared when the ISR is executed so that no more interrupts trigger the ISR. It is not automatically enabled at the end of your interrupt code and you must ensure that there is a RETFIE instruction (RETurn From Interrupt and Enable and GIE bit) at the very end of your code (normally high level compilers will automatically do this for you).

    Note: You can control GIE yourself just like any other register flag at any point in your code; for instance if you want to turn off interrupts while you do some critical code that must not be interrupted (of course you may miss interrupts and it's up to you to ensure that the system still works!).

    Note: GIE is automatically turned off when an ISR is called so that the interrupt code itself is not interrupted!

    7.5.2 PEIEThe second global interrupt flag is the PEIE control flag or Peripheral Interrupt Enable. This fits into a spare register position that was left free for future expansion in the INTCON register and is a enable control for all peripheral hardware interrupts. When you clear this it means that the hardware operates only with interrupts that were created for the original series of PIC chips.

    Practically PEIE is not much use so just leave it set high and use GIE to control all interrupts.

    Note: GIE overrides PEIE.

    7.6 Using the Interrupt Flag RegistersOnce the GIE bit and PEIE bits are enabled the PIE (interrupt enable) registers come into play and any bits that are set will allow the associated interrupt to fire and trigger the ISR code.

    It is important to note that the flag registers (PIR) tell you the state of the interrupt from the associated hardware module but they work independently from the enable registers i.e. the flag register will reflect the state of the interrupt signal from the associated module regardless of whether the PIE OR GIE bits are set or not. This means you can poll the hardware module to detect a change of state of the module (not recommended but useful if you are caught out).

    The flag bit is set by the hardware module to indicate that the hardware has generated an interrupt condition i.e. it triggers an interrupt that will cause a jump

    http://www.best-microcontroller-projects.com Page 25 of 83.

  • Effective PIC Interrupts

    to the ISR (if the corresponding enable bit in the PIE register and associated enables are active; PEIE and GIE).

    After the interrupt has triggered, the same flag registers will store the state of the hardware so by reading the flag register (PIR) you can detect which hardware module triggered the interrupt.

    After this you must write a zero to this individual bit to reset it and allow the module to generate this interrupt again after the ISR has completed.

    See Chapter 11.2 for the Interrupt code template.

    http://www.best-microcontroller-projects.com Page 26 of 83.

  • Effective PIC Interrupts

    7.7 Interrupt Flow DiagramThe following flow diagram shows how to initialize and use interrupts correctly.

    See Chapter 11.2 for the Interrupt code template.

    http://www.best-microcontroller-projects.com Page 27 of 83.

    Initialize_Interrupts

    Enable_Interrupts

    For each hardware peripheral that you want to use set it's 'Enable' flag i.e. the PIE bit. and clear its state flag i.e. the PIR bit

    Add code here that sets up each hardware module ready for use.

    Turn on the GIE bit and the PEIE bit (you could turn on the PEIE bit in the initialize code as GIE overrides PEIE so PEIE is not really useful but has to be set high somewhere).

    Perform Main Code Actions

    (and repeat in loop)

    'Enable_Interrupts' is placed before the main code loop (not within it).Code then operates as normal while interrupts are active i.e. interrupts are active within the main code loop.

    Disable_Interrupts

    'Disable_Interrupts' is used (with discretion) anywhere within the main code.

  • Effective PIC Interrupts

    7.8 Interrupt Design DecisionsAn interrupt constitutes a break in the normal operation of executing code but you can alter the effect of the interrupt on that code by understanding three factors.

    1. The interrupt rate (either from external or internal sources).

    2. The length of the interrupt code (the ISR).

    3. The processing power of the processor.

    These factors control how effective your project will be so you must have some idea of them when creating your project. For instance if you were measuring the rate of a signal changing on a pin (and using an external interrupt to detect it). If the signal was firing the interrupt at a rate of 1kHz or 1ms then you can work out that you would have 1000 machine code instructions before the next interrupt fires (assuming a 4MHz Crystal and consequent internal instruction rate running at 1MHz so 1ms/1e-6 = 1000 instruction cycles).

    Obviously the interrupt routine must take a short enough time so that it completes well before the next interrupt because you can not have multi threaded interrupts i.e. the interrupt must be fully completed before the next interrupt occurs. Also you need the interrupt to complete in a short time so that there is enough processing time left over for the main code.

    Note: In practice you would probably use a different method to detect the signal e.g. by using a prescaler in front of the signal or use an internal timer with built in prescaler.

    In general the ideal situation is to make the ISR as short as possible so that the main tasks of the processor (all other code) can be executed as well. In general the best design will have the interrupt routine taking significantly less time than the main code execution loop.

    To work out the processing time just subtract the ISR time form the fastest interrupt repeat rate so for example perhaps you have an ISR time of 100 instruction cycles end up with an approximate value of 900 cycles i.e. 900 instruction cycles for the main program to operate before the next interrupt fires.

    If the input frequency increases to 2kHz then you would only have 400 cycles for main code execution. At 4kHz and you only have 150 cycles. So seemingly small changes in the input frequency will cause the maximum (main code) processing time to rapidly decrease.

    This may or may not be important and it depends on the main code processing task. For instance if a simple LCD display was to be updated then it may be OK to

    http://www.best-microcontroller-projects.com Page 28 of 83.

  • Effective PIC Interrupts

    be continuously interrupted as the display would be updated eventually. If however there was a time constraint where some actions had to be performed then it would not be OK for the interrupts to continuously fire. Eventually the repeat rate of the interrupt could become too large halting the system completely i.e. the processor will spend all it's time servicing the interrupt routine doing no useful work.

    Note: This system is dependent on an external signal over which you may not have control so the problem is actually a complete design problem where you must characterize the complete project i.e. the expected maximum signal input rates

    7.8.1 Processing / Interrupt Time Analysis

    Interrupt Rate Instruction Cycles Available (before next interruptPIC using 4MHz Xtal)

    Interrupt routine length

    Cycles Available To Main Code(before next

    interrupt)

    1kHz 1000 100 900

    2kHz 500 100 400

    4kHz 250 100 150

    8kHz 125 100 25

    The real point about this problem is that the available processing time is reduced as the interrupt rate increases. Lets assume that the 1kHz rate is the 'real' design point i.e. the rate that you have designed the system to work around. So your total expected cycles available to do main code work is 900 cycles.

    The Interrupt code routine is fixed (note: It will change depending on which actual interrupts and their associated code are executed but just take the 100 cycles as your typical interrupt code length/time) so lets assume that 100 cycles are used at every interrupt call.

    The table above shows the available processing time left for use in the main code (total machine instruction cycles between interrupts at the design interrupt rate of 1kHz minus the time used in the interrupt). As the interrupt rate increases so less main code instruction cycles are left for use.

    http://www.best-microcontroller-projects.com Page 29 of 83.

  • Effective PIC Interrupts

    Comparison of Instruction Cycles Available as Interrupt Rate Increases

    Interrupt rate Cycles calculation Total Cycles Available

    To Main Code

    Percentage of Main code cycles available compared to cycles at 1kHz design rate

    1kHz 1000-(1*100) 900 100%

    2kHz 1000-(2*100) 800 89%

    4kHz 1000-(4*100) 600 67%

    8kHz 1000-(8*100) 200 22%

    7.8.2 Three Interrupt Design Solutions Here's three ways to combat the problem by design choice:

    1. Increase the main system clock (more processing power).

    2. Place a divider in front of the signal source i.e. a discrete chip.

    3. Use an internal Timer and its prescaler (feeding into an internal counter).

    The important point is that you must figure out if the system is capable of working correctly before committing to any particular design (and/or do some breadboarding tests).

    7.8.3 Effect of using a 20MHz clockThe table above shows what happens when you you increase the processing power of a device. Because the interrupt code size remains the same there are far more processing clock cycles available to the main code so the ISR has less effect (uses less cycles compared to the total available) on main code operation.

    Note: Instead of just changing the clock you could change the device e.g. use a 18F series with built in PLL i.e. extremely high internal clock rate and remember changing a device over is a big job but it is made much easier when you use a high level language such as C. Also the interrupt code templates presented here are generic just change some register names if the new device uses different ones.

    Calculations:

    Xtal = 20MHz, processor clock = 20e6/4 = 5MHz, T=200ns

    Cycles within 1kHz period = 1/1kHz = (1/1e3)/200e-9 = 5000

    http://www.best-microcontroller-projects.com Page 30 of 83.

  • Effective PIC Interrupts

    Effect of Increasing the Processor Clock to 20MHz

    Interrupt rate Cycles calculation Total Cycles Available

    To Main Code

    Percentage of Main code cycles available compared to cycles at 1kHz design rate

    1kHz 5000-(1*100) 4900 100%

    2kHz 5000-(2*100) 4800 98%

    4kHz 5000-(4*100) 4600 94%

    8kHz 5000-(8*100) 4200 86%

    8 Design techniques

    8.1 Using FLAGS to communicate from ISR to main Program Flags are boolean variables used to indicate that an action should be taken and you can use them to transfer actions from the ISR to the main code.

    Note: You can save space by using bit variables in C and use them as boolean flags.

    In C you can also declare a variable as a 'static' within a file and it has what is known as file scope (it is only visible to functions that are declared within the file itself). This means that any function in the same file, including the ISR function, can 'see' the variable.

    You can use this variable as a flag variable which can be set within the ISR and actioned within the main code. In this way a non critical actions can be performed when instigated by an interrupt trigger flag from within the ISR.

    So why would you want to do this?

    The reason is that you can reduce the ISR time which is one way of improving performance of your system. You can take code that would otherwise have to be performed within the ISR itself and delegate it to be performed by the main code when it goes around its processing loop.

    The penalty is that you won't know exactly when the delegated code is executed so you have to ensure that this does not matter i.e. it must not have a critical execution time requirement.

    The benefit is that the ISR has to only execute a few instructions i.e. setting a

    http://www.best-microcontroller-projects.com Page 31 of 83.

  • Effective PIC Interrupts

    variable, instead of executing a whole lot of code within the ISR. This means that the interrupt is shorter and you may be able to increase the interrupt rate and this can mean better performance.

    See Chapter 11.6 for a simple example using this flag technique this is only a skeleton code example but illustrates the structure of code to use.

    A more real example would be storing received RS232 data into a buffer (in the ISR) and when full setting a flag to indicate that the main code should go and interpret the contents. This means the ISR can be kept small and lean and the main code is only executed when needed i.e. there is no data interpretation within the ISR itself.

    8.2 'Interrupt Cascade'

    An 'interrupt cascade' is a simple concept of calling and starting one interrupt from within another. It's a technique that is useful for not only precise repeated interrupts but precise repeated interrupts that have a resulting precise repeatable output of different duration to the main interrupt rate i.e. it's good for creating a PWM type signal when you have run out of PWM modules or you don't have one in the first place.

    It is also useful in reacting to an interrupt event of any kind but reacting at a precise (controlled) delayed time period after the original event. For instance it could be useful to check for a return signal in an ultrasonic ranger. If you made the second interrupt delay time even longer you could use it as a courtesy light delay.

    http://www.best-microcontroller-projects.com Page 32 of 83.

  • Effective PIC Interrupts

    Obviously there are hundreds of ways of solving these kind of problems and this is an extra technique which you could choose if it fits the problem.

    To create an output using this method use one timer interrupt and get it going at a suitable rate e.g. 20ms. (a good rate for servo control).

    When the first 20ms interrupt fires re-enable it but also set the enable flag of a second (different) timer module. At the same time set an output high. When the second interrupt fires set the output low and DONT re-enable the second interrupt its done by the first interrupt. This generates a pulse output high for the duration of the second timer interrupt setting.

    To control the duration of the pulse, control the second timer value from within the first timer interrupt code. By controlling this value using a variable the duration of the pulse can be manipulated from within the main code e.g. use a static variable in C code.

    This means you get a repeated pulse signal at the 20ms rate due to the 1st timer and you also get a controlled pulse duration due to the time length of the second timer.

    http://www.best-microcontroller-projects.com Page 33 of 83.

  • Effective PIC Interrupts

    8.3 Measuring the ISR timeThere are two easier ways to measure the ISR time using a scope or a simulator and one more difficult way using a timer.

    One of the easiest ways to measure the execution time of an ISR is to use an oscilloscope and monitor a pin for signals set from within interrupt.

    Another method is to use a simulator. It is more laborious but it is possible to check different conditional paths within the ISR by setting variables after you have stopped the simulator just at the entry to the ISR.

    The third way is to use internal timer hardware and store start and end times of the interrupt from the timer. The problem then is to send the timer values out so you have to choose from available hardware e.g. RS232 or LCD etc.

    8.3.1 Direct Pin MonitoringThe easy way to check the ISR time is to set a pin high at the start and low at the end of the interrupt code you want to monitor. This way you can see the interrupt duration by measuring it directly on an oscilloscope and because setting a pin high or low uses one instruction the method has minimal impact on the execution time of the interrupt.

    Note: This method will increase the actual time but only by two instruction cycles.

    The disadvantage is that you have to have a spare pin available for monitoring.

    8.3.2 Simulating InterruptsSimulating interrupts is difficult because simulators are based on discrete time systems and not real time actions. This in itself does not present a problem. The problem is that a real time event can be scheduled some time in the future for instance at 1ms intervals. To simulate this you would want a real time event at the 1ms simulation time but simple discrete time simulators do not allow you to specify these types of event because they are based solely on the processor, it's inputs and outputs and internal code operation i.e. there is usually no provision for timed external events or operation of internal hardware peripherals. All you can simulate is the registers that are, in real life, controlled by the discrete hardware modules.

    To illustrate the problem consider simulating a 1ms interval timer with a 1kHz signal on an external pin and using a 4MHz main clock (instructions at 1MHz or 1us period).

    This would mean that you have to simulate 1000 discrete time intervals i.e. 1000 cycles of simulation time before the interrupt code is activated and this also

    http://www.best-microcontroller-projects.com Page 34 of 83.

  • Effective PIC Interrupts

    assumes that you can use the simulator to assign timed events to processor inputs which is not possible with most of these simulators. But just for illustration assume that you can do this.

    Note: There is one way to fake it and that's by using a counter (written in more C code) to count down the number of times the main code loop is executed and at the approximate time (count) calls the interrupt code (which you have to copy as a normal function). The problem with this is that you are introducing lots of code that you do not really want because this new code could have more new bugs within it!

    Assuming that you do have a method to trigger the interrupt.

    Since simulation time is very slow because the simulation model uses code to simulate the actions of internal registers i.e. the whole processor. It will take a long time before you reach the 1000 simulation discrete time event meaning that it will take so long that you won't want to bother. Even if it takes 600ms repeated testing will mean it takes a very long time to debug. The ideal situation is to test the target code (interrupt) immediately.

    8.3.2.1 Using #define MacrosThe solution is not to use the simulation time of 1000ms but to alter the code using C macros to trigger the interrupt code immediately (after some initialization code) in the main part of the program. Using macros is convenient because you can set a '#define' control for example '#define TEST_INTERRUPT 1' and this would enable the relevant code throughout.

    It means you can place a break instruction (i.e. halt the simulator) just before the interrupt code is called and then setup any registers you need to set e.g. interrupt flag registers etc to test out a specific part of the interrupt routine.

    See Chapter 11.7 for an example of this method.

    8.3.3 Using A TimerThis technique is a more complex way of measuring an interrupt time but offers the advantages of being non intrusive (no external pins are required) and quick (once set up it's instant there's no poring over simulation code/tools to get an answer).

    The disadvantage is that you use internal memory resources (but not too much!) and existing display interfaces to do the job It all depends on what hardware is available.

    Note: You can make a very simple software coded serial output at a pin and use a standard level translator chip to generate the required RS232 levels at a PC e.g.

    http://www.best-microcontroller-projects.com Page 35 of 83.

  • Effective PIC Interrupts

    a MAX232 (use the A version to use the smaller 0.1uF capacitors).

    The method also assumes you have a timer running and in most complex code you will be using one anyway. Even if you are not you can enable the timer and not the interrupts so it does not affect currently running code.

    All you do is poll the timer at the beginning and end of the interrupt storing these values (and assuming that the timer has not rolled over i.e. passed through zero) subtract the first from the second value to get the time period of the interrupt. In the main code these values are converted to ASCII and the result sent to your chosen display interface.

    Even if the timer passes through zero, between the first and second readings, it will more often be the case that it does not roll over, so the values measured will on average be the right ones. This is important since you only really want a guide to the interrupt time and when you get the value out of the device you will see the same value most of the time and this is the one to take note of.

    Note: It's not worth spending time correcting the operation of the code as it will take more and more time to get it perfect. Good enough is OK.

    8.3.3.1 Viewing the Timer ValueOnce you have obtained the timer value you need to display it and here's two easy hardware interfaces to use:

    RS232

    LCD

    In order to display values on these devices you will need to output it in ASCII format and that means translating the value from the type in use (probably an integer) into ASCII.

    A commonly used C conversion routine is ltoa() (found in stdlib.h) and that uses the long type which you can cast into any other integer type (byte, char, int etc.).

    Note: The ltoa() function is not included in all microcontroller compilers but it's useful to know about anyway because in different environments e.g. on a PC you can use it to convert any integer type to a string and it also allows you to specify the radix so it's useful for conversions to hex and binary.

    The problem is that long's use up more internal resources (bigger library code is imported). Another factor is that the maximum string size is dependent on the type (and conversion radix) used so ltoa() uses more string space i.e. when a long is converted to ASCII there are more resulting digits for the maximum output value.

    To get round this, compiler manufacturers will make simple small routines to do a

    http://www.best-microcontroller-projects.com Page 36 of 83.

  • Effective PIC Interrupts

    specific conversion job e.g. ByteToStr() or WordToStr() which are optimized for each 'type' and occupy less space in memory because these routines do not need to allow for an arbitrary output string length.

    Note:All these routines (or similar) can be found on the web, so if your compiler manufacturer does not supply them just create a source file and header file and compile the code so you can use it that's the great power of using C; you can never get really stuck.

    9 An Error You Must AvoidInterrupts are tricky and I did make a mistake while coding them for this document. The only reason I found the problem was that I was re-checking the heartbeat timer interrupt code by turning off the enable controls for individual interrupts.

    Guess what I turned off enables for both timer 0 and 2 but the LEDs still indicated that timer 0 and 2 they were still running. Very puzzling since when an enable is off the interrupt should not fire at all BUT looking at the code I saw that I had not checked for the enable being active while checking the interrupt flag.

    The code looked like this (within the ISR itself) : if (INTCON & (1

  • Effective PIC Interrupts

    // Note count to overflow uses 2 when updating hence 133 not 131 TMR0 = 133; // From PIC Timer 0 calculator.

    T0time++; }

    }

    The problem with this error is that it is subtle since you can get away with it if you don't need to disable an interrupt (quite common) - they will always be correctly actioned. The problem comes if you try to turn off an interrupt (and you find out that you can't). Using the above code solves the problem but remember if you don't need to turn off the enable (e.g. For a heartbeat timer) then you don't need the extra code which will just increase the interrupt action time.

    http://www.best-microcontroller-projects.com Page 38 of 83.

  • Effective PIC Interrupts

    10 18F Series InterruptsAs you would expect from the more advanced 18F devices the interrupt structure has been considerably enhanced compared to the mid range devices. In fact a complete copy of the existing (mid-range-device) interrupt system gives you a completely new feature: Prioritized Interrupts.

    In essence it allows Low Priority Interrupts (just think of these as normal interrupts since they are equivalent to the mid range interrupts) to be interrupted. It adds a complete layer of new interrupt capability onto all existing interrupts Low priority interrupts themselves can now be interrupted hence these new interrupts are called High Priority Interrupts.

    10.1 High or Low Priority Interrupts: Reason for UsageUsing Prioritized Interrupts is a specialized concept and is really for advanced usage so you probably won't need it for standard programs.

    The reason you might want to use them is when you have built up a critical piece of code that either you are worried may not always capture an interrupt (because there are too many other interrupts all needing servicing at the same time since your code is getting larger) or a specific interrupt is absolutely critical and must under no circumstances be missed e.g. Safety Critical Operation.

    10.2 Hardware for Prioritized InterruptsNote: The new interrupt hardware is completely backwards compatible with mid-range (high level) code since there are new register controls to turn it off so this means you can use existing code and slowly transition to the new 18F hardware feature (but only if you want to).

    To allow the priority mechanism to work an extra interrupt vector has been added and this handles the high priority interrupts and to control it there is an additional enable register GIEH Global Interrupt Enable for High Priority Interrupts.

    Note: Check your compiler documentation for exact implementation details.

    This is in addition to the original GIE (or Global Interrupt Enable) which has been re-labeled GIEH/GIE (or Global Interrupt Enable for High Priority Interrupts).

    PEIE has become GIEL - global enable for low priority interrupts.

    GIE has become GIEH global enable for high priority interrupts.

    http://www.best-microcontroller-projects.com Page 39 of 83.

  • Effective PIC Interrupts

    Diagram of interrupt hardware in a typical 18F series device(excerpt from 18F2550 data sheet document 39632b)

    10.3 Prioritized Interrupt MechanismIn the mid-range devices such as 16F or 12F etc you can only prioritize an interrupt in a limited way and that is to place the interrupt that you want executed first in the ISR at the start of the interrupt routine this way if the

    http://www.best-microcontroller-projects.com Page 40 of 83.

  • Effective PIC Interrupts

    associated interrupt fires then you know that the ISR will execute that interrupt first.

    Prioritized interrupts in the 18F series work on the physical hardware level and a low priority interrupt can itself be interrupted by a high priority interrupt. The mechanism works since there are two physical hardware interrupts so you will need two high level interrupt functions to service each of these vectors.

    The two interrupt vectors have the following addresses:

    Low priority interrupt vector at : 000018h (normal use interrupt)

    High priority interrupt vector at : 000008h

    The important point is that a high priority interrupt can execute even while a low priority interrupt is executing i.e. the lower (executing) interrupt can be overridden by the higher priority interrupt. In the mid-range devices the main interrupt can never be interrupted and everything has to stop and wait until the interrupt code (ISR) is finished and until exit from the ISR.

    But in the same way that a normal (mid-range device) interrupt stops the main code working and branches to the ISR so the high priority interrupt will stop the low priority interrupt until the high priority interrupt has finished. It is a nested interrupt structure operating in hardware.

    Each of the interrupt sources (i.e. any of the sources of interrupts within the 18F device) has an enable bit to allow it to become a high priority interrupt so you can decide whether or not to make each interrupt a high priority interrupt or a low priority interrupt.

    Note: This is a design decision and you should assign high priority to those interrupts that absolutely must not be missed i.e. critical ones.

    10.4 Priority Enable Control Bit (backwards compatibility)Overall control of the priority interrupt mechanism is set by using the IPEN bit in the RCON register. Bit 7 is the IPEN or Interrupt Priority ENable bit and when set it enables priority interrupts which means that any of the interrupt sources within the 18F device can be prioritized.

    When IPEN is reset to zero the device interrupt system is compatible with the mid-range PIC devices i.e. prioritized interrupts are off i.e. the interrupt structure behaves in the same way as for the mid range device interrupt system meaning the interrupt hardware looks as though there is only a single interrupt vector.

    http://www.best-microcontroller-projects.com Page 41 of 83.

  • Effective PIC Interrupts

    10.5 18F Series RegistersAs with the mid range devices the 18F series still has the PIR and PIE registers and these work in exactly the same way as the mid range devices but in addition to these the 18F series also has an Interrupt Priority Enable register (The IPE registers).

    The registers that control interrupts are:

    PIR - Peripheral Interrupt Request (Flag).

    PIE - Peripheral Interrupt Enable.

    IPE - Interrupt Priority Enable.

    Additional interrupt control bits are held in INTCON

    INTCON : Original interrupts the same as the mid-range devices + extras.

    Note: In the same way that some original interrupts are located in the INTCON register, extra INTCON registers are available INTCON2 & INTCON3. These house the new external interrupt controls (both enable and Flag bits) but in addition they also house the priority control bits (IPE) for these new interrupts and newly created priority bits for the original interrupts (IPE).

    Here is a list of registers associated with interrupts

    RCON

    INTCON, INTCON2, INTCON3

    PIR1, PIR2

    PIE1, PIE2

    IPR1, IPR2

    (from 18F2550 datasheet)

    10.6 18F Context SavingRecall that for mid range devices only the program counter (PC) is saved on the stack (See Chapter 6.4). In the 18F series you can also have the WREG, STATUS and BSR registers saved but only if you use a fast return from interrupt. If you don't use a fast return from interrupt you may need to save WREG, STATUS and BSR using your own code.

    Note: You still have to be careful as you may need to save other registers anyway.

    http://www.best-microcontroller-projects.com Page 42 of 83.

  • Effective PIC Interrupts

    10.6.1 Fast Register StackThe Fast Return stack is specifically for use in interrupts (but see later) and saves WREG, STATUS and BSR. The problem is that it is only one level deep so you have to be careful with it when using the priority interrupt mechanism since if two interrupts are triggered (one low priority and one high) then the fast stack will be overwritten in that case you have to a manually control saving the register values.

    Warning: It's best not to use the fast return stack if both high and low priority interrupts are active since the f-r-s is only one level deep the second interrupt will overwrite the fast return stack values!

    You will need to check your compiler documentation (and possibly analyze the code output) to check exactly what your compiler does with the stack i.e. whether or not it takes care of context saving when using prioritized interrupts.

    If fast stack and priority interrupts are enabled the during the low priority interrupt you must save the WREG,STATUS and BSR since these will be the ones overwritten by a high priority interrupt event.

    10.6.1.1 Using the Fast Register Stack for normal function callsIf interrupts are not used then you can use the fast return stack during normal function calls (probably difficult in a high level compiler and would be easier in machine code/assembler).

    To do this in assembler you would call the function as follows:

    CALL Func1, FAST

    To return from the function use:

    RETURN FAST

    11 Examples

    11.1 Hardware & Software

    11.1.1 HardwareTo run the example code the hardware is kept to a minimum. All you need is:

    An ICSP programmer.

    A PIC 16F88

    18F2550 or any similar 18F device (adjust setup as necessary).

    http://www.best-microcontroller-projects.com Page 43 of 83.

  • Effective PIC Interrupts

    MAX232A (the A version uses 0.1uF polyester not 1uF electrolytic so it is easier).

    5V power supply

    PSU decoupling capacitor 10uF electrolytic.

    1 decoupling capacitor 0.1uF (attached close to power & ground on 16F88)

    4 MAX232 capacitors 0.1uF

    3 1k resistors

    3 LEDs.

    Solderless breadboard.

    Solid core sheathed connection wire.

    Wire strippers.

    A PC.

    Serial cable Null modem (straight through no crossover) for RS232.

    9 way female D-type (connects to PC serial port).

    11.1.2 Serial port configuration Baud: 9600

    Data: 8 bits

    Parity: None

    Stop bits: 1

    Flow control: None

    http://www.best-microcontroller-projects.com Page 44 of 83.

  • Effective PIC Interrupts

    11.1.3 16F88 Hardware Diagram

    http://www.best-microcontroller-projects.com Page 45 of 83.

  • Effective PIC Interrupts

    11.1.4 18F2550 Hardware Diagram

    11.1.5 Software Downloads

    11.1.5.1 C Compiler downloadCompiler : MikroC download :

    http://www.mikroe.com/en/compilers/mikroc/pic/download.htm

    11.1.5.2 ICPROGDownload ICPROG here : http://www.ic-prog.com/index1.htm

    You need the ICPROG programming software and the MikroC C compiler (although the examples come with precompiled hex file so if you are not going to change the code then you won't need the compiler) the compiler is free for the small

    http://www.best-microcontroller-projects.com Page 46 of 83.

  • Effective PIC Interrupts

    amounts of code used in these examples..

    Programmer Software : ICPROG

    See notes on site for setup instructions. On web page:

    http://www.best-microcontroller-projects.com/c-programming-tutorial-setup.html

    11.1.5.3 WinPic (for the 18F2550 and many others)Although I mainly use ICPROG it does not have regular updates and does not cater for the 18F2550. There is a program that is updated much more regularly and is just as good as and it's called WinPic.

    Note: ICPROG does have some supported 18F devices so check those out before changing to new software e.g. If you use the popular 18F252.

    IMPORTANT: If you do have ICPROG running and then start up WinPic you may need to reboot your computer since ICPROG may not release the ports (LPT PORT) and it will appear that WinPic is not running reading or writing. Reboot will solve this!

    WinPic caters for many different interfaces and I think you can even specify an unsupported programming interface via a configuration file so you are guaranteed to make your programmer work using this software.

    There's also a lot of information on the website on how to configure and use it. Fortunately it has an AN589 programming interface (parallel port) that I use so it was a matter of selecting that interface and just using the program directly in place of ICPROG.

    TIP: When programming (just before hitting the programming button) click the tab labeled Messages as this will then show you how the program is progressing otherwise it looks like the program is hung.

    Note: There are several versions with this (or a similar name) so download your version from : from www.qsl.net/dl4yhf (Note: Similarly to ICPROG, WinPic is free).

    TIP: Allow the configuration to be programmed when programming the 18F2550 it does return a programming failed error because it does not read back the programmed value properly so don't worry about that if anyone finds out why (plus the solution) drop me an email and I'll update the ebook thanks.

    11.2 Interrupt TemplateNote: This technique can be adapted to any system/device.

    This code is extremely boring but I guess that's what's needed as a template.

    http://www.best-microcontroller-projects.com Page 47 of 83.

  • Effective PIC Interrupts

    11.2.1 Interrupt Template Code ActionNote: Even flashing the LED is totally unnecessary but hey it's got to do something!

    11.2.2 Interrupt Template C Code////////////////////////////////////////////////////////////////////////// File: 16F88-interrupt-template.c//// Author: J F Main.//// Description://// Interrupt Template Code//// Compiler : mikroC, mikroElektronika C compiler// for Microchip PIC microcontrollers// Version: 8.2.0.0//// Note Testing://// Tested on 16F88//// Requirements://// Clock : 8MHz (Internal)//// Target : 16F88//// Version:// 1.00 - Initial release.//// Copyright : Copyright John Main 2008// http://www.best-microcontroller-projects.com// For use only if purchased with ebook// "PIC Interrupt Secrets"// available from website above.////////////////////////////////////////////////////////////////////////#include "bit.h"

    //////////////////////////////////////////////////////////////////////// Defines//////////////////////////////////////////////////////////////////////

    http://www.best-microcontroller-projects.com Page 48 of 83.

  • Effective PIC Interrupts

    //////////////////////////////////////////////////////////////////////// file scope variables//////////////////////////////////////////////////////////////////////static unsigned long T1time=0;

    //////////////////////////////////////////////////////////////////////void init(void) {

    OSCCON = 0x70; // b6..4 = 110 = 4MHz, 111 = 8MHz

    ANSEL = 0; // all ADC pins to digital I/O

    // Timer 1 T1CON = (1

  • Effective PIC Interrupts

    static unsigned char LED = 0;

    if(t==0) { // restart time count t = T1time; } else { // toggle delay if ( (T1time - t)>=500 ) { LED = ~LED; if (LED) setBit(PORTA,0); else resBit(PORTA,0); t = 0; // start a new time count }