AnsweredAssumed Answered

measure pulse width(pwm) with input capture

Question asked by armoun.mohamad on Aug 31, 2014
Latest reply on Sep 1, 2014 by Clive One
hi every body . my micro is stm32f407
my plane was to measure 8 channel pwm to get pulse width, after clive1 guided me([DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/choosing%20pwm%20channel%20stm32f407%20discovery%20board&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F]here) i understood that there is 2 way to get pwm input 1- using pwm input capture which uses each timer for each pwm channel , i implemented that but it's too expensive (gets many resources) so i decided to use 2nd way which is 2- using input capture to gets pwm input.

now i have a problem to understand how can i be able to measure pulse width just with input capture . here is a code that  generates pwm with tim4 and PD12 and i connected it to PC6 which is set for input capture (thanks to clive1 again for [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/PWM%20Input%20capture%20doesnt%20work%20on%20Ch34%20pair&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/AllItems.aspx&currentviews=32]this

i send the measured value with usart to pc but the value is not constant and changes .

here is my code and i have 2 question 1- what exactly i should add to my code to measure the pwm input .

2- i want to generate pwm in 50hz . is there any formula to set the value of Prescaler and period to get 50hz pwm . i don't know how should i setup this value ??

#include <stm32f4xx.h>
 
void TIM3_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;
   
  /* GPIOC clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Input/Output controlled by peripheral
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // Button to ground expectation
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
    /* Connect TIM3 pins to AF */
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3);
   
  TIM_DeInit(TIM3);
   
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  
 
  TIM_ICInitStructure.TIM_ICFilter = 0x0;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; 
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
   
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  TIM_Cmd(TIM3, ENABLE);
  TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
}
 
void InitializeTimer4(int period = 2000-1)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
     
    TIM_TimeBaseInitTypeDef timerInitStructure;
    timerInitStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000)/2) - 1);
    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    timerInitStructure.TIM_Period = period;
    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    timerInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM4, &timerInitStructure);
    TIM_Cmd(TIM4, ENABLE);
    TIM_CtrlPWMOutputs(TIM4, ENABLE);
}
 
void initializeGPIOD()
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    GPIO_InitTypeDef gpioStructure;
    gpioStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15 ;
    gpioStructure.GPIO_Mode = GPIO_Mode_AF;
    gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &gpioStructure);
}
 
void InitializeOutPWMChannel5(int DutySycle)
{
    TIM_OCInitTypeDef outputChannelInit = {0,};
    outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
    outputChannelInit.TIM_Pulse =DutySycle;
    outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
    outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
 
    TIM_OC1Init(TIM4, &outputChannelInit);
    TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
}
 
void NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Enable and set TIM3 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_Init(&NVIC_InitStructure);
}
volatile uint32_t Freq[4];
void TIM3_IRQHandler(void)
{
  union{uint16_t  value; uint8_t byte[2];} inttobyte;
    uint32_t Current, Delta;
    static uint32_t Last[4];
     
    if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
    {
        /* Clear TIM3_CH1 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
  
        Current = TIM_GetCapture1(TIM3);
        Delta = Current - Last[0];
        Last[0] = Current;
        if (Delta)
            Freq[0] = 1000000 / Delta; // 1MHz clock
        inttobyte.value = Freq[0];
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
        USART_SendData(USART2,0xFF);
        for(int i = 0 ; i < 2 ; i++){
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
        USART_SendData(USART2,inttobyte.byte[i]);
      }
        
    }
    if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
    {
        /* Clear TIM2_CH2 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
  
        Current = TIM_GetCapture2(TIM3);
        Delta = Current - Last[1];
        Last[1] = Current;
        if (Delta)
            Freq[1] = 1000000 / Delta; // 1MHz clock
          
         
    }
    if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
    {
        /* Clear TIM2_CH3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
  
        Current = TIM_GetCapture3(TIM3);
        Delta = Current - Last[2];
        Last[2] = Current;
        if (Delta)
            Freq[2] = 1000000 / Delta; // 1MHz clock
            
    }
    if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)
    {
        /* Clear TIM2_CH4 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
  
        Current = TIM_GetCapture4(TIM3);
        Delta = Current - Last[3];
        Last[3] = Current;
        if (Delta)
            Freq[3] = 1000000 / Delta; // 1MHz clock
          
         
    }
}
void init_usart(void){
   
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
       
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
 
     
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);
 
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART2, &USART_InitStructure);
 
    USART_Cmd(USART2, ENABLE);
}
void Delay(__IO uint32_t nCount);
 
int main()
{
  init_usart();
  TIM3_Configuration();
  InitializeTimer4();
  initializeGPIOD();
  InitializeOutPWMChannel5(700);
  NVIC_Config();
  void TIM3_IRQHandler();
  while(true)
  {
  }
  return 0;
}
void Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}



Outcomes