cancel
Showing results for 
Search instead for 
Did you mean: 

Which Pin is triggering an interrupt How do I count them not multiple time?

MKoza.2
Associate II

Hello everybody,

how can I count which pin triggers an interrupt, but not multiple times? I have written the following ISR.

INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
{
	data = (uint8_t)GPIOB->IDR& 0xF;
	
	if((GPIO_PIN_0 & data )== GPIO_PIN_0) {
		counter_Pin0++;
	}
	if((GPIO_PIN_1 & data )== GPIO_PIN_1) {
		counter_Pin1++;
	}
}

I first store the first four bits from GPIOB port in data and then I mask the bit form the pin. But as you can see in the picture, it is also counted when Pin 1 triggers an interrupt. The sensors have a small delay to each other, but are LOW for a certain time. I actually have 4 sensors, each of which are sometimes LOW at the same time, but trigger an interrupt at different times. Then I do not count 4 interrupts at Pin0 but 11 for example.0693W00000FAFeGQAX.pngBest Regards

Michael

6 REPLIES 6
Peter BENSCH
ST Employee

I'm sorry I didn't see the question sooner. Is the problem solved or do you still need help?

Regards

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
MKoza.2
Associate II

I have helped myself with this function. Since the interrupts are never triggered at the same time in my application, but only one after the other, I helped myself with an XOR and saving the old value. But I still had sometimes not correct results.

INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
  hall1 = (uint8_t)GPIOB->IDR& 0xF;
  
  switch(hall1^hall_alt) // 
  {
    case 0x1: h1_counter++; break; // Pin0
    case 0x2: h2_counter++; break; // Pin1
    case 0x4: h3_counter++; break; // Pin2
    case 0x8: h4_counter++; break; // Pin3
    default: break;
  }
  
  counter_IT++; // ISR Counter nur zu Testzwecken
  hall_alt = hall1;  // alter Wert wird gespeichert
}

Maybe you have a better solution? To be honest, it is not relevant anymore, but good to know how to do it for the future.

Best Regards

Michael Koza

Peter BENSCH
ST Employee

There could be several reasons for the problem, but it seems to me that the interrupts are arriving faster than they can be processed?

Without more detailed information on the clock frequency, interrupt priorities and the settings of the interrupt controller, as well as other interrupt sources, it will be difficult to find a better answer than your workaround you've already found.

Regards

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
MKoza.2
Associate II

I have built a kind of encoder with Hall sensors as you can see in the picture in the attachment. But the interrupts from the Hall sensors do not trigger simultaneously as you may see in the picture. 

The MCU runs with 16 MHz and I have added the interrupt vector with the priorities. I have modify the lin_slave_app from the ST LIN example 5.1.

void clk_setup()
 {
	 CLK_CCO |= 0x08; /* select fcpu for CCO output */
	CLK_CKDIV = 0x00; /* HSI = 16MHz*/
	CLK_ICKC = 0x01;
	while(!(CLK_ICKC&0x02));  /**Wait until HSI is Ready**/ 
}

The GPIOSs from port B are initialized as follow:

GPIO_Init(GPIOB, GPIO_PIN_0, GPIO_MODE_IN_PU_IT); //HALL M1_1 

GPIO_Init(GPIOB, GPIO_PIN_1, GPIO_MODE_IN_PU_IT); //HALL M1_2

GPIO_Init(GPIOB, GPIO_PIN_2, GPIO_MODE_IN_PU_IT); //HALL M1_3

GPIO_Init(GPIOB, GPIO_PIN_3, GPIO_MODE_IN_PU_IT); //HALL M2_4

GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_PU_IT); //HALL M2_1

GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_PU_IT); //HALL M2_2

GPIO_Init(GPIOB, GPIO_PIN_6, GPIO_MODE_IN_PU_IT); //HALL M2_3

GPIO_Init(GPIOB, GPIO_PIN_7, GPIO_MODE_IN_PU_IT); //HALL M2_4

//-------------------------------------------------------------------//         

EXTI_DeInit();

EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY);

enableInterrupts();

But as I said, it's not that important anymore and I don't want to bother you with trivial problems ;)

Best Regards

Michael Koza

Peter BENSCH
ST Employee

Well, that is indeed interesting, but I have currently no suggestion to completely avoid the problem.

But I would like to point out one more thing: it looks like you are using the STM8A?

I do not want to neglect to point out that all STM8A (automotive variants) have been set to NRND (Not Recommended for New Design), are guaranteed to be available for another 10 years, but will be delivered for the last time at the beginning of 2031. You should therefore look around early for alternatives, although you can definitely find something within the STM32 family, which, however, can not be operated with 5V.

Regards

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Cristian Gyorgy
Senior III

Hi Mkoza,

I think your function with xor-ing the current value with the old one is not really correct. You can still have more than1 bit change it's level until you read the new values, so I would do the following:

change = hall1 ^ hall_alt;
if (change & 0x01) {
// pin0 toggle
}
if (change & 0x02) {
// pin1 toggle
}
if (change & 0x04) {
// pin2 toggle
}
if (change & 0x08) {
// pin3 toggle
}
   

This way you catch changes on multiple pins.