cancel
Showing results for 
Search instead for 
Did you mean: 

How to read low-frequency PWM signals?

aatif shaikh
Associate III

Hi all,

I'm new with the PWM business, so, I'm referring the sample code (TIM_PWM_Input) provided in STM32F2XX stranded peripheral library . In the readme.txt file it is mentioned that we can measure minimum 915Hz frequency. But in my application, I wanted to read the PWM which is running approximately at 50Hz to 100Hz. Therefore, can anyone help me with configuration in the initialization part, as I'm not really aware of the PWM's configuration and it's mode.

I'm using:

Board: NUCLEOF207ZG.

Controller: STM32F207ZGT6.

Library: Standard peripheral library.

Clock: System:- 120Mhz, Pb-1:- 30Mhz, Pb-2:- 60Mhz,

Timer and channel: Timer-4, Channel-2.

Pin: Port-B, Pin-7.

//Configure the TIM4 Pins
 GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
 
  /* TIM4 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
 
  /* GPIOB clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  
  /* TIM4 chennel2 configuration : PB.07 */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Connect TIM pin to AF2 */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);
 
  /* Enable the TIM4 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  //Timer configuration
 TIM_ICInitStructure.TIM_Channel     = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter    = 0x0;
 
  TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);
 
  /* Select the TIM4 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
 
  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
  TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);
 
  /* TIM enable counter */
  TIM_Cmd(TIM4, ENABLE);
 
  /* Enable the CC2 Interrupt Request */
   TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
//Interrupt sub-rutine
__IO uint16_t IC2Value   = 0;
__IO uint16_t DutyCycle = 0;
__IO uint32_t Frequency = 0;
 
void TIM4_IRQHandler(void)
{
  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);
 
  /* Clear TIM4 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
 
  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM4);
 
  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM4) * 100) / IC2Value;
 
    /* Frequency computation 
       TIM4 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */
 
    Frequency = (RCC_Clocks.HCLK_Frequency)/2 / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

1 REPLY 1

You can increase the prescaler to extend the span of time you can measure, but this makes the granularity of the measurement a lot rougher.

You can use 32-bit TIM (72 MHz would span close to a minute), so TIM2 or TIM5, as I recall for the STM32F2.

For long things you could also use the 1ms SysTick, to measure an EXTI (GPIO Interrupt) to +/-1ms accuracy.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..