1
\$\begingroup\$

I have an issue where I want to count how many times I hit a switch using an interrupt. I tried placing the count variable inside the main but it claims that count does not exist. I put count inside the pragma but I know that will reset the count value to 0. How should I approach this problem?

I'm using the STM8S003K3

volatile int count = 0;

#pragma vector = 8
__interrupt void EXTI_PORTD_IRQHandler(void){   
   count++;
   PD_ODR_ODR3 = !PD_ODR_ODR3;
}

void main() {
   __disable_interrupt();
   PD_ODR = 0;             //  All pins are turned off.
   PD_DDR = 0xff;          //  All pins except PD4 are outputs.
   PD_CR1 = 0xff;          //  Push-Pull outputs.
   PD_CR2 = 0xff;          //  Output speeds up to 10 MHz.
   //
   //  Now configure the input pin.
   //
   PD_DDR_DDR4 = 0;        //  PD4 is input.
   PD_CR1_C14 = 0;         //  PD4 is floating input.
   //
   //  Set up the interrupt.
   //
   EXTI_CR1_PDIS = 2;      //  Interrupt on falling edge only.
   EXTI_CR2_TLIS = 0;      //  Falling edge only.
   __enable_interrupt();

   while (1) {
       __wait_for_interrupt();
   }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Declare "volatile int count = 0;" outside of your main and interrupt routine to make it file scope \$\endgroup\$ – Scott Seidman Apr 11 '16 at 14:43
  • 2
    \$\begingroup\$ By the way, make sure you debounce your button/switch, or the results may be unexpected. \$\endgroup\$ – JimmyB Apr 11 '16 at 15:54
3
\$\begingroup\$

Make it a volatile global variable; declare and initialize it outside all functions. Then you increment within your ISR and print the modified value in main(). Something like:

static volatile int count = 0;

isr(){
  count++;
...
}

void main(){
  debug_print(count);
...
}

The volatile keyword is to prevent your compiler from optimizing away the variable, since its not seen to change in the normal program flow.

EDIT: Declaring the variable static, like Lundin suggested, restricts its scope to this particular file, so that the variable is not visible outside this source file. You should use this only if the ISR and main() are defined within the same file.

\$\endgroup\$
  • 1
    \$\begingroup\$ I was taught that global variable is bad programming. or am I wrong? \$\endgroup\$ – G. Han Apr 11 '16 at 14:39
  • 3
    \$\begingroup\$ Its usually recommended to reduce usage of global variables to prevent potential name collisions and unintended modifications. In this case though, since ISRs dont take arguments, its about the only way you can pass data between your main program and the ISR. \$\endgroup\$ – TisteAndii Apr 11 '16 at 14:43
  • \$\begingroup\$ Thanks it works perfectly but I have another issue related to it. I want to count but every time I want to stop the debug to see how many times I press the button I got this error. Failed to stop target: gdi-error. Abort command is not possible in current CPU state. It only works if I have a breakpoint but that is not an ideal. \$\endgroup\$ – G. Han Apr 11 '16 at 14:59
  • 2
    \$\begingroup\$ Global variables are indeed bad and there is never a reason to use them. Use file scope variables instead. static volatile uint32_t count;. \$\endgroup\$ – Lundin Apr 12 '16 at 14:21
  • 1
    \$\begingroup\$ @TisteAndii The interrupt vector table should be in one file. Give it the relevant header file includes, then declare the actual ISRs where they belong. SPI interrupt inside SPI driver, timer interrupt inside timer driver etc. There is no reason why anything in your code but the SPI driver should talk with the SPI interrupt - otherwise your program design is flawed. \$\endgroup\$ – Lundin Apr 12 '16 at 15:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.