Page 1 of 2

[Solved] Use timer for precise interrupt

Posted: Tue Jan 14, 2020 8:17 pm
by Step73
I need to use an interrupt every 50 ms to control a stepper motor.
I'm able to do this with the standard Arduino board (AVR-based) but I'm too new to STM32 to do the same.

I searched in the forum, but I'm also not sure if I need to find something suitable for my Nucleo F429ZI board.
Would you please put me on the right way? It's not clear if I have to manually set the CPU registers (after reading the huge manual) or there's a framework function to help me.

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 8:39 pm
by Step73

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 8:40 pm
by fpiSTM
Step73 wrote: Tue Jan 14, 2020 8:39 pm Perhaps this might be useful?

https://github.com/stm32duino/STM32Exam ... llback.ino
You find the right example ;)

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 8:44 pm
by fpiSTM
Here you will find further reading on the HardwareTimer API:
https://github.com/stm32duino/wiki/wiki ... er-library

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 9:03 pm
by Step73
Thanks. Just a clarification. In the README I read:
Some instances are used by Servo, Tone and SoftSerial (see TIMER_SERVO, TIMER_TONE and TIMER_SERIAL) but only when they are used. Just be sure there is no conflict with your own usage.
Well, is there a simple way to check such a conflict? I use several libraries (servo, stepper, etc...). I have to manually check their source code?

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 9:24 pm
by fpiSTM
They are defined in the variant.h.

But If you do not use Servo, Tone and softwareSerial libraries then it is ok.

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 9:56 pm
by Step73
I cannot get it to work.
Here my minimal example, almost the same of the linked one:

Code: Select all

void setup()
{
  pinMode(LED_RED, OUTPUT); 
  digitalWrite(LED_RED, HIGH);

  TIM_TypeDef *Instance = TIM1;
  HardwareTimer *timerBase = new HardwareTimer(Instance);
  timerBase->setOverflow(50, HERTZ_FORMAT);
  timerBase->attachInterrupt(timer_callback);
  timerBase->resume();
}

void loop()
{
}

void timer_callback(HardwareTimer *)
{
  digitalWrite(LED_RED, !digitalRead(LED_RED));
}
I have no activity on the pin - expected 25 Hz toggling.
The pin is working, because writing `HIGH` or `LOW` turns on and off the built-in led.
I also tried with different timers (`TIM1`, `TIM1`, `TIM3`, etc...) with no differences.

Am I missing something obvious?

Re: Use timer for precise interrupt

Posted: Tue Jan 14, 2020 10:28 pm
by fredbox

Code: Select all

#define LED_RED LED_BUILTIN
add

Code: Select all

timerBase->setMode(2, TIMER_OUTPUT_COMPARE);
as the first timerBase line.

Change Hertz from 50 to 5 so you can see it blink clearly.

Code: Select all

timerBase->setOverflow(5, HERTZ_FORMAT);

Re: Use timer for precise interrupt

Posted: Wed Jan 15, 2020 1:40 am
by fredbox
Here is the simplest way that I know to blink an LED using an interrupt:

Code: Select all

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
}
// blink the led once per second using 1 millisec systick interrupt
void HAL_SYSTICK_Callback(void) {
  static volatile uint32_t ledCount = 0;
  if (++ledCount == 500) {
    ledCount = 0;
    digitalToggleFast(digitalPinToPinName(LED_BUILTIN));
  }
}
For 50 Hz you would use a count of 10.

Re: Use timer for precise interrupt

Posted: Wed Jan 15, 2020 1:41 am
by Bakisha
You also need

Code: Select all

  timerBase->setMode(1, TIMER_OUTPUT_COMPARE); // 1 is channel number 1, can be 1,2,3 or 4 
in your setup.