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 :)
3 Answers 3
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.
-
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.Beacon of Wierd– Beacon of Wierd2020年10月04日 15:33:57 +00:00Commented 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?SoreDakeNoKoto– SoreDakeNoKoto2020年10月04日 21:37:03 +00:00Commented 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 theattachInterrupt()
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 calledattachInterrupt()
somewhere in the code. I verified that I was using the correct register to turn on interrupts by turning them off after callingattachInterrupt()
.Beacon of Wierd– Beacon of Wierd2020年10月05日 13:18:27 +00:00Commented Oct 5, 2020 at 13:18 -
@BeaconofWierd That's weird. To be clear, you did add
adc_enable_irq(ADC1, ADC_EOC);
to replaceattachInterrupt()
, as I mentioned up there? Because with that in place, I see no difference at all with the existingattachInterrupt()
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.SoreDakeNoKoto– SoreDakeNoKoto2020年10月06日 00:30:07 +00:00Commented Oct 6, 2020 at 0:30 -
If it still doesn't work, post your entire sketch. Think I have an STM32 around somewhere...SoreDakeNoKoto– SoreDakeNoKoto2020年10月06日 00:34:46 +00:00Commented Oct 6, 2020 at 0:34
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.
-
If you reverse the call stack in that example you end up with
ADC1->handlers[ADC_EOC] = yourfunction;
, andADC1egs->CR1 |= (1U<<(ADC_EOC +ADC_CR1_EOCIE_BIT));
to enable the IRQ. As far as I can see.Gerben– Gerben2020年09月30日 13:59:28 +00:00Commented Sep 30, 2020 at 13:59 -
1Yeah, 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 :(Beacon of Wierd– Beacon of Wierd2020年09月30日 15:06:50 +00:00Commented Sep 30, 2020 at 15:06
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++.
-
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.Beacon of Wierd– Beacon of Wierd2020年09月30日 08:08:32 +00:00Commented Sep 30, 2020 at 8:08
void ADC_IRQHandler(){ ... }
. Not sure if that's correct though, as I'm not familiar with STM32s.