Interrupts are unexpected events in a sequence of execution of instructions causing an interruption of the normal programme flow. The causes of interrupts can be different. For the family of dsPIC30F microcotrollers, in the transducer or general purpose applications, 41 interrupt sources and 4 types of traps, ranked according to the priority schematic, have been specified.
For each specified interrupt or trap the microcontroller (MCU) has a clearly defined further programme sequence specified by the interrupt vector table (IVT). The IVT contains the initial addresses of interrupt routines for each interrupt source or trap. IVT is located in the programme memory starting at location 0x000004 up to location 0x00007E. In addition to the interrupt vestor table, in the family of dsPIC30F microcontrollers, the alterante interrupt vector table (AIVT) is also specified. The purpose of the AIVT is to enable the realization of alternate interrupt routines. The AIVT is also located in the programme memory starting at location 0x000084 up to location 0x0000FE. On the basis of the priorities specified by the special function registers, the interrupt controller is responsible for the preparation and preprocessing of interrupts:Attention! If an interrupt is assigned priority level 0, it is the same as if no interrupt is allowed by the bits set in IECx.
Natural order priority is specified by the position of an interrupt in the vector table (IVT). It is used only to resolve conflicts between simultaneous pending interrupts with the same user assigned priority level. Then, the interrupt of the higher natural level of priority is executed first. As an example, table 3-1 shows for the microcontroller dsPIC30F4013 the interrupt vector table (IVT) with all sources of interrupts, interrupt number in the vector table, and the number which defines the natural order priority.INT NUM | VECTOR NUM | IVT ADDRESS | AIVT ADDRESS | INTERRUPT SOURCE |
---|---|---|---|---|
Highest Natural Order Priority | ||||
0 | 8 | 0x000014 | 0x000094 | INT0 - External Interrupt 0 |
1 | 9 | 0x000016 | 0x000096 | IC1 - Input Capture 1 |
2 | 10 | 0x000018 | 0x000098 | OC1 - Output Compare 1 |
3 | 11 | 0x00001A | 0x00009A | T1 - Timer 1 |
4 | 12 | 0x00001C | 0x00009C | IC2 - Input Capture 2 |
5 | 13 | 0x00001E | 0x00009E | OC2 - Output Compare 2 |
6 | 14 | 0x000020 | 0x0000A0 | T2 - Timer 2 |
7 | 15 | 0x000022 | 0x0000A2 | T3 - Timer 3 |
8 | 16 | 0x000024 | 0x0000A4 | SPI1 |
9 | 17 | 0x000026 | 0x0000A6 | U1RX - UART1 Receiver |
10 | 18 | 0x000028 | 0x0000A8 | U1TX - UART1 Transmitter |
11 | 19 | 0x00002A | 0x0000AA | ADC - ADC Convert Done |
12 | 20 | 0x00002C | 0x0000AC | NVM - NVM Write Complete |
13 | 21 | 0x00002E | 0x0000AE | SI2C - I2C Slave Interrupt |
14 | 22 | 0x000030 | 0x0000B0 | MI2C - I2C Master Interrupt |
15 | 23 | 0x000032 | 0x0000B2 | Input Change Interrupt |
16 | 24 | 0x000034 | 0x0000B4 | INT1 - External Interrupt 1 |
17 | 25 | 0x000036 | 0x0000B6 | IC7 - Input Capture 7 |
18 | 26 | 0x000038 | 0x0000B8 | IC8 - Input Capture 8 |
19 | 27 | 0x00003A | 0x0000BA | OC3 - Output Compare 3 |
20 | 28 | 0x00003C | 0x0000BC | OC3 - Output Compare 4 |
21 | 29 | 0x00003E | 0x0000BE | T4 - Timer 4 |
22 | 30 | 0x000040 | 0x0000C0 | T5 - Timer 5 |
23 | 31 | 0x000042 | 0x0000C2 | INT2 - External Interrupt 2 |
24 | 32 | 0x000044 | 0x0000C4 | U2RX - UART2 Receiver |
25 | 33 | 0x000046 | 0x0000C6 | U2TX - UART2 Transmitter |
26 | 34 | 0x000048 | 0x0000C8 | Reserved |
27 | 35 | 0x00004A | 0x0000CA | C1 - Combined IRQ for CAN1 |
28-40 | 36-48 | 0x00004C – 0x000064 | 0x0000CC – 0x0000E4 | Reserved |
41 | 49 | 0x000066 | 0x0000E6 | DCI - CODEC Transfer Done |
42 | 50 | 0x000068 | 0x0000E8 | LVD - Low Voltage Detect |
43-53 | 51-61 | 0x00006A – 0x00007E | 0x0000EA – 0x0000FE | Reserved |
Lowest Natural Order Priority |
void IntDetection() org 0x0014{ //Interrupt on INT0 LATD++; IFS0.F0 = 0; //interrupt flag cleared } void main(){ TRISD = 0; //portd is output TRISF = 0xFFFF; //portf is input IFS0 = 0; //interrupt flag cleared IEC0 = 1; //Interrupt is set on a rising edge at INT0 (RF6) while(1) asm nop; }Let us summarize the algorithm how dsPIC processes interrupts in this example. Two ports are used, PORTD as the output to display the number of interrupt events and PORTF as the input; this means that an interrupt will occur when at INT0 (RF6) logic 0 changes to logic 1. In the register IEC0 the least significant bit (IEC0.0) is set for allowing reaction to interrupt INT0. The meanings of other bits are shown in table 3-7. When an interrupt occurs, the function IntDetection is called. How does dsPIC “know” to call exactly this function? By instruction org in the interrupt vector table (see table 3-1) at the memory location 0x000014 is written the function IntDetection. What does dsPIC do when an interrupt occurs, i.e. when at RF6 logic 1 appears after logic 0? At first, it writes logic 1 in the least significant bit of the register IFS0. Then, it tests if the interrupt INT0 is enabled (the least significant bit of IEC0). If yes, it reads from the interrupt vector table which part of the programme should be executed. mikroC compiler will, at position 0x000014, write the code where function IntDetection starts and dsPIC will execute this function and return to the main program. Two operations are carried out in the interrupt function. At first, the interrupt flag is cleared (dsPIC does not do that automatically, but leaves this to the user software). Then, the value at port D is incremented by 1 with LATD++. What would happen if the interrupt flag in the IFS register was not cleared? If this line is omitted, dsPIC will wait until first interrupt, call and execute the function IntDetection. What is the difference? The register IFS0 will still indicate that an interrupt occured. As soon as the microcontroller returns to the main programme and executes one instruction, it would understand that an interrupt occured again and theIntDetection function would be called again. This means that IntDetection function would be executed after each instruction of the main programme. The reader is encouraged to erase the line
IFS0.F0:=0
; and see what happens.
What is the purpose of while(1) asm nop;? When dsPIC comes to the end of a programme, it starts from the beginning as if reset. However, at the end of the programme the compiler inserts an endless loop to prevent this of happening. This has been inserted here to make the reader aware of the existence of this loop and that reseting dsPIC is not possible.