Skip to content

STM32F030CCT6 InputCapture Problem #2339

@xiezhoubin

Description

@xiezhoubin

Chip:STM32F030CCT6

Core Version:2.7.1

Example:https://github.com/stm32duino/STM32Examples/blob/main/examples/Peripherals/HardwareTimer/InputCapture/InputCapture.ino

My Code:

#include <Arduino.h>
HardwareSerial mySerial(PA10, PA9);

#define pin PB15

uint32_t channel;
volatile uint32_t FrequencyMeasured, LastCapture = 0, CurrentCapture;
uint32_t input_freq = 0;
volatile uint32_t rolloverCompareCount = 0;
HardwareTimer* MyTim;

void InputCapture_IT_callback(void) {
  CurrentCapture = MyTim->getCaptureCompare(channel);
  /* frequency computation */
  if (CurrentCapture > LastCapture) {
    FrequencyMeasured = input_freq / (CurrentCapture - LastCapture);
  } else if (CurrentCapture <= LastCapture) {
    /* 0x1000 is max overflow value */
    FrequencyMeasured = input_freq / (0x10000 + CurrentCapture - LastCapture);
  }
  LastCapture = CurrentCapture;
  rolloverCompareCount = 0;
}

/* In case of timer rollover, frequency is to low to be measured set value to 0
   To reduce minimum frequency, it is possible to increase prescaler. But this is at a cost of precision. */
void Rollover_IT_callback(void) {
  rolloverCompareCount++;

  if (rolloverCompareCount > 1) {
    FrequencyMeasured = 0;
  }
}

void setup() {
  mySerial.begin(115200);

  // Automatically retrieve TIM instance and channel associated to pin
  // This is used to be compatible with all STM32 series automatically.
  pinMode(pin, INPUT_PULLUP);
  TIM_TypeDef* Instance = (TIM_TypeDef*)pinmap_peripheral(digitalPinToPinName(pin), PinMap_PWM);
  channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin), PinMap_PWM));
  pinMode(pin, INPUT_PULLUP);
  // Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished.
  MyTim = new HardwareTimer(Instance);

  // Configure rising edge detection to measure frequency
  MyTim->setMode(channel, TIMER_INPUT_CAPTURE_FALLING, pin);

  // With a PrescalerFactor = 1, the minimum frequency value to measure is : TIM counter clock / CCR MAX
  //  = (SystemCoreClock) / 65535
  // Example on Nucleo_L476RG with systemClock at 80MHz, the minimum frequency is around 1,2 khz
  // To reduce minimum frequency, it is possible to increase prescaler. But this is at a cost of precision.
  // The maximum frequency depends on processing of the interruption and thus depend on board used
  // Example on Nucleo_L476RG with systemClock at 80MHz the interruption processing is around 4,5 microseconds and thus Max frequency is around 220kHz
  uint32_t PrescalerFactor = 1;
  MyTim->setPrescaleFactor(PrescalerFactor);
  MyTim->setOverflow(0x10000);  // Max Period value to have the largest possible time to detect rising edge and avoid timer rollover
  MyTim->attachInterrupt(channel, InputCapture_IT_callback);
  MyTim->attachInterrupt(Rollover_IT_callback);
  MyTim->resume();

  // Compute this scale factor only once
  input_freq = MyTim->getTimerClkFreq() / MyTim->getPrescaleFactor();
}

void loop() {
  /* Print frequency measured on Serial monitor every seconds */
  mySerial.println((String) "Frequency = " + FrequencyMeasured);
  delay(1000);
}

Problem:
I used the official input capture code example and used the PB15 pin of SMT32F030CCT6 as the input pin. In reality, I measured the frequency of this pin at around 265kHz using an oscilloscope, but the serial port printed in the code was 0kHz.
1eb1916fb49e949daa4ad78389880c69

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis doesn't seem right

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions