C Programming with Interrupts: How to Avoid Polling and Optimize Processor Usage

In summary, the code uses polling for the interrupt flag, which may not be ideal. The use of asm goto is to move the start of the ISR code out of the high/low vector area. The 'volatile' keyword is used to prevent the compiler from optimizing out a variable that changes in the ISR. There is also a suggestion to use a pointer to function to have the interrupt call a different function each time. However, the main program does not have any other tasks to perform, so it will just be looping anyway.
  • #1
fractal01
14
1
Hi everyone~

I think that I have used polling here where I shouldn't have done. Does anyone have any ideas?
Code:
#include "p18f8722.h"
#include "timers.h"

    void configure_PB2_interrupt (void);
    void enable_global_interrupts(void);
    unsigned char PB2_pressed (void);
    void isr (void);

    volatile unsigned char int_occured = 0;
 
    #pragma code vector=0x08       
    void vector (void){
        _asm
        GOTO isr
        _endasm
    }
    #pragma code

    
    void main (void){
        ADCON1  = 0x0F;
        TRISB   = 0xFF;
        TRISF   = 0x00;

        configure_PB2_interrupt();

        while (1){
            while (!int_occured){
                    ;
                }
            int_occured = 1;
            if (PORTBbits.RB0 == 1){
                LATF = 0x00;
                }   
            }           
        }

    void configure_PB2_interrupt (void){
        INTCONbits.GIE  = 1;
        INTCONbits.INT0IE   = 1;
        INTCON2bits.INTEDG0 = 0;
    }
    

     #pragma interrupt isr
     void isr(void){
        INTCONbits.INT0IF = 0;
        LATF = 0x01;
        int_occured = 1;
    }
 
Last edited by a moderator:
Physics news on Phys.org
  • #2
Is the code working (is your interrupt routine getting called) ? I haven't seen the "goto" syntax you're using in vector before (is goto an assembler macro?). Normally you'd have to get the address of your interrupt routine (pointer to function) and store it in the memory location used to branch to interrupt 8. There may be a library function that does this for you.

You could put more of the code in the interrupt routine, but unless this is a multi-tasking operating system, polling for the interrupt flag isn't going to cause problems, and there's nothing else to do. You could use a sleep() in the main polling loop, but again, there aren't any other tasks running unless you have a multi-tasking operating system.
 
  • #3
You should explain what you want this code to do an what it is actually doing. I see you setting int_occured to 1 in the ISR. Should you be clearing it to 0 somewhere?
 
  • #4
The code is supposed to be run on a pic18f8722. When one of the pushbuttons is pressed, then an interrupts should be generated. I am mainly worried about the polling. I shouldn't be doing this I don't think. I wrote this a few months ago and now I am looking I am confused at what I was doing! Is there another way that I could do this so that I am not polling the flags? My while loop looks very iffy since I got the polling which I am not sure if it defeats the objects of the interrupts, also I have the volatile variable in there too and it doesn't seem necessary. The friend I wrote it with is convinced it is fine since it did the task it was supposed to...

The asm bit it fine I think -just something we have been taught to use- it is assembly language. Thanks for your help!
 
  • #5
fractal01 said:
I am mainly worried about the polling.
The polling for the interrupt flag is probably ok. You don't show the code for the main routine, so I'm not sure what the purpose of this program is.

If you wanted to run a series of functions from the interrupt routine (a different function with each interrupt), you could use a pointer to function (pfisr in this example) and update it as needed:

Code:
typedef void (* PFISR)(void);

static void isr0(void);
static void isr1(void);
static void isr2(void);

static volatile PFISR pfisr;

main()
/* .. */
    pfisr = isr0;

isr()
/* .. */
    (*pfisr)();

isr0()
    pfisr = isr1;
/* .. */

isr1()
    pfisr = isr2;
/* .. */

isr2()
    pfisr = isr0;
/* .. */
 
Last edited:
  • #6
fractal01 said:
I have the volatile variable in there too and it doesn't seem necessary. The friend I wrote it with is convinced it is fine since it did the task it was supposed to...

The asm bit it fine I think -just something we have been taught to use- it is assembly language. Thanks for your help!

The 'volatile' is a hint to the compiler not to optimize out a variable that changes outside of normal program flow (in the ISR).

The asm goto is to move the start of the ISR code out of the high/low vector area. It's not really needed if you only have a high pri ISR but if you do have high and low vectors putting code directly at the vector would limit the size of the high ISR before it would overrun the low vector address.

0008H high
0018H low
 
  • #7
rcgldr said:
The polling for the interrupt flag is probably ok. You don't show the code for the main routine, so I'm not sure what the purpose of this program is.

Using interrupts means that polling doesn't have to be used which ties up the processor repeatedly checking. Maybe it is different polling the interrupt flag...Is there any other way of writing the program to NOT include the polling there?
 
  • #8
fractal01 said:
Using interrupts means that polling doesn't have to be used which ties up the processor repeatedly checking. Maybe it is different polling the interrupt flag...Is there any other way of writing the program to NOT include the polling there?
Yes, if you put all the code in the interrupt handler(s). The example I posted above shows how to have the interrupt call a different function each time an interrupt occurs, so that you can step through a sequence of functions, one per interrupt.

Still there's the issue that the main program doesn't have anything else to do, so it's just going to be looping anyway, unless there's a useful sleep() or waitforevent() (normally used by multi-threaded operating systems) type function.
 

1. What is an interrupt in C programming?

An interrupt is a signal sent to the processor from an external device or software to temporarily halt the current program execution and handle a specific task. This allows for multitasking and efficient use of system resources.

2. How do interrupts work in C programming?

Interrupts work through the use of interrupt service routines (ISRs), which are functions that are executed when an interrupt is triggered. These ISRs handle the interrupt by performing the necessary actions and then returning control back to the main program.

3. What is the purpose of using interrupts in C programming?

The purpose of using interrupts is to improve the efficiency and responsiveness of a program. By allowing the processor to handle multiple tasks simultaneously, interrupts can reduce the need for the main program to constantly check for events or inputs, freeing up resources for other tasks.

4. How do you handle multiple interrupts in C programming?

In C programming, multiple interrupts can be handled by setting up a priority system for the ISRs. This ensures that the most important or time-sensitive interrupts are handled first. Additionally, interrupts can be disabled or enabled as needed to prevent conflicts or ensure proper sequencing.

5. What are the potential drawbacks of using interrupts in C programming?

One potential drawback of using interrupts is the added complexity and potential for errors in code. Additionally, if interrupts are not properly managed, they can cause unexpected behavior and potentially crash the program. It is important to carefully plan and test the use of interrupts in a program to avoid these issues.

Back
Top