incorrect micros() value for stm32f411re
Posted: Mon Nov 23, 2020 9:57 pm
I am unable to retrieve a correct value of micros(), following my setup:
- STM32F411RE mcu
- external frequency generated by a pwm 50% duty connected to PC2
- in the hardware interrupt routine I save delta of micros() into a E1_period_us variable
- for testing purpose I setup PC10 output pin when interrupt happens
In following scope D7 is the signal generated externally while D0 is the signal generated by digitalWrite inside the interrupt, as seen perfectly aligned with RAISING

but the problem is that measured period is wrong ( 1241us instead of expected 1221us ) as seen in follow serial output
period:1241.00 freq:805.80
Note
Following ArduinoNano equivalent code where external pwm need to be attached on digital pin 2
- STM32F411RE mcu
- external frequency generated by a pwm 50% duty connected to PC2
- in the hardware interrupt routine I save delta of micros() into a E1_period_us variable
- for testing purpose I setup PC10 output pin when interrupt happens
In following scope D7 is the signal generated externally while D0 is the signal generated by digitalWrite inside the interrupt, as seen perfectly aligned with RAISING
but the problem is that measured period is wrong ( 1241us instead of expected 1221us ) as seen in follow serial output
period:1241.00 freq:805.80
Note
- the problem not appears if using stm32f103
- an equivalent code running on Arduino Nano produces expected results like follow:
period:1220.00 freq:819.67
Code: Select all
#include <limits.h>
unsigned long timeDiff(unsigned long now, unsigned long start)
{
if (start <= now)
return now - start;
else
return (ULONG_MAX - start) + now + 1;
}
#define SERIAL_BAUD 115200
#define E1_PIN PC2
#define M1_PIN PC10
volatile bool E1_started = false;
volatile float E1_period_us = 0.0;
volatile uint32_t E1_m = micros();
volatile bool state = false;
void ISR_E1()
{
if (!E1_started)
{
E1_started = true;
E1_m = micros();
}
else
{
uint32_t m = micros();
E1_period_us = timeDiff(m, E1_m);
E1_m = m;
}
digitalWrite(M1_PIN, state ? HIGH : LOW);
state = !state;
}
void setup()
{
Serial.begin(SERIAL_BAUD);
Serial.println("SETUP");
pinMode(E1_PIN, INPUT);
pinMode(M1_PIN, OUTPUT);
attachInterrupt(E1_PIN, ISR_E1, RISING);
}
uint32_t m = millis();
void loop()
{
uint32_t m2 = millis();
if (timeDiff(m2, m) > 1000)
{
m = m2;
Serial.print("period:");
Serial.print(E1_period_us);
Serial.print(" freq:");
Serial.println(1.0 / ((float)E1_period_us * 1e-6));
}
}
Code: Select all
#include <limits.h>
#define PWM_PIN 2
unsigned long timeDiff(unsigned long now, unsigned long start)
{
if (start <= now)
return now - start;
else
return (ULONG_MAX - start) + now + 1;
}
volatile bool E1_started = false;
volatile float E1_period_us = 0.0;
volatile uint32_t E1_m = micros();
void int0_isr()
{
if (!E1_started)
{
E1_started = true;
E1_m = micros();
}
else
{
uint32_t m = micros();
E1_period_us = timeDiff(m, E1_m);
E1_m = m;
}
}
void setup()
{
Serial.begin(115200);
Serial.println("SETUP");
pinMode(PWM_PIN, INPUT);
attachInterrupt(0, int0_isr, RISING);
}
uint32_t m = millis();
void loop()
{
uint32_t m2 = millis();
if (timeDiff(m2, m) > 1000)
{
m = m2;
Serial.print("period:");
Serial.print(E1_period_us);
Serial.print(" freq:");
Serial.println(1.0 / ((float)E1_period_us * 1e-6));
}
}