2

I'm currently using the STM32F1xx boards from http://dan.drown.org/stm32duino/package_STM32duino_index.json To program my blue pill but I can’t find how to write the interrupt for the ADC. I’ve set the registers to output an interrupt when it finishes but I can’t find how to write the code for the interrupt.

I’ve tried the ”ISR(ADC_vect)” function which works for arduino, but the compiler is complaining that ”ISR” is not recognized. I’ve tried to look for the documentation for the STM32duino, but the little I could find didn’t even mention the ADC or any interrupt routines. I’ve searched though the STM32duino forum without any luck. If anyone knows how to solve this or where to find information about interrupt code for the STM32 boards I would be very happy :)

2
  • A quick google gave me void ADC_IRQHandler(){ ... }. Not sure if that's correct though, as I'm not familiar with STM32s.
    – Gerben
    Sep 29, 2020 at 15:45
  • 1
    @Gerben It did not work :( Sep 29, 2020 at 16:20

3 Answers 3

1

As you already found, the function to override is __irq_adc() defined weakly here and bound to the interrupt vector table here.

If you've defined it and it's not working, it's probably because you got rid of the attachInterrupt() call entirely, which does more than just assign an interrupt handler; it also enables the interrupt for that ADC. So:

myADC.calibrate();
myADC.setSampleRate(ADC_SMPR_1_5);
adc_enable_irq(ADC1, ADC_EOC);
myADC.setPins(&pin, 1);

extern "C" void __irq_adc() {
// handle the interrupt
// make sure to check statuses and clear flags as shown in the default handler
}

Not sure if the extern "C" will be needed, probably will be, you'll have to check and find out.

7
  • This worked, though it only worked if I used the "attachInterrupt" on the ADC, did not seem to work using registers only :/ Maybe the attachInterrupt needs to be called to bind the __irq_adc function to the interrupt vector table? Also, extern "C" was required for it to work. Oct 4, 2020 at 15:33
  • @BeaconofWierd I don't understand. You're still using the attachInterrupt() instead of overidding __irq_adc() directly? What exactly is working? Oct 4, 2020 at 21:37
  • I tried to just add the __irq_adc() function, but then it was not called. When I also used the attachInterrupt() the __irq_adc() function was called. I tried to enable and disable intterupts using registers to see if that was the problem, but I was still only able to use __irq_adc() if I first called attachInterrupt() somewhere in the code. I verified that I was using the correct register to turn on interrupts by turning them off after calling attachInterrupt(). Oct 5, 2020 at 13:18
  • @BeaconofWierd That's weird. To be clear, you did add adc_enable_irq(ADC1, ADC_EOC); to replace attachInterrupt(), as I mentioned up there? Because with that in place, I see no difference at all with the existing attachInterrupt() call in STM32ADC.cpp. Also remember that you can't test with an empty __irq_adc(), you need to at least clear the EOC flag as shown in the default handler, else your code will seem hung. Also get rid of every other register-fiddling first. Oct 6, 2020 at 0:30
  • If it still doesn't work, post your entire sketch. Think I have an STM32 around somewhere... Oct 6, 2020 at 0:34
1

I couldn't find the function being called directly, but there's a good example explaining how to attach interrupts to the ADC which works well: https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/libraries/STM32ADC/examples/SingleConversionInterrupt/SingleConversionInterrupt.ino

If anyone knows the actual function being called directly that would be great to add on here, but until then this example does what I need and will hopefully help others having the same problem.

2
  • If you reverse the call stack in that example you end up with ADC1->handlers[ADC_EOC] = yourfunction; , and ADC1egs->CR1 |= (1U<<(ADC_EOC +ADC_CR1_EOCIE_BIT)); to enable the IRQ. As far as I can see.
    – Gerben
    Sep 30, 2020 at 13:59
  • 1
    Yeah, I followed the code back to where the function in ADC1->handlers[ADC_EOC] was run, and it was inside a function called adc_irq if I remember correctly, it was even defined with the __weak keyword, so I was sure I had the right one, but for some reason that function did not work either when I wrote my own version of it :( Sep 30, 2020 at 15:06
0

first you need to enable the interrupt (I don't know if the stm32 wrapper for arduino does it or not):

NVIC_EnableIRQ(ADC1_IRQn);

then you have to write ISR as gerben said:

extern "C" void ADC1_IRQHandler()
{
    //clear ADC flag
}

extern "C" because [as far as I know] the arduino projects are C++.

1
  • Sadly it does not work with the STM32duino library :( I did however find examples of how to attach interrupts to the ADC, for anyone looking to just to that: github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/… Though I want as much speed as possible for my application so I will have to dig deeper to try to find the function that's called by the ISR itself. Sep 30, 2020 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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