cancel
Showing results for 
Search instead for 
Did you mean: 

TIM PWM input Example

cchechio
Associate II
Posted on June 23, 2014 at 18:03

How can I modify this example to read pwm signals with a frequency of 40Hz?

/* Includes ------------------------------------------------------------------*/

&sharpinclude ''stm32f4_discovery.h''

&sharpinclude ''stm32f4xx_it.h''

/** @addtogroup STM32F4_Discovery_Peripheral_Examples

  * @{

  */

/** @addtogroup TIM_PWM_Input

  * @{

  */ 

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

TIM_ICInitTypeDef  TIM_ICInitStructure;

/* Private function prototypes -----------------------------------------------*/

void TIM_Config(void);

/* Private functions ---------------------------------------------------------*/

/**

  * @brief  Main program

  * @param  None

  * @retval None

  */

int main(void)

{

  /*!< At this stage the microcontroller clock setting is already configured, 

       this is done through SystemInit() function which is called from startup

       file (startup_stm32f4xx.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f4xx.c file

     */

       

  /* TIM Configuration */

  TIM_Config();

  /* TIM4 configuration: PWM Input mode ------------------------

     The external signal is connected to TIM4 CH2 pin (PB.07), 

     The Rising edge is used as active edge,

     The TIM4 CCR2 is used to compute the frequency value 

     The TIM4 CCR1 is used to compute the duty cycle value

  ------------------------------------------------------------ */

  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);

  uint16_t duty = getFrequency();

  uint32_t freq = getDuyCycle();

  

  while (1);

}

/**

  * @brief  Configure the TIM4 Pins.

  * @param  None

  * @retval None

  */

void TIM_Config(void)

{

  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);

}

&sharpifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  while (1)

  {}

}

&sharpendif

/**

  * @}

  */ 

/**

  * @}

  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

#!rocketscience
9 REPLIES 9
cchechio
Associate II
Posted on June 29, 2014 at 21:22

up

Posted on June 30, 2014 at 00:08

What's NOT working with your incomplete example now?

You might consider increasing you time base's prescaler, or using a 32-bit timer, like TIM2?

I'm pretty sure I've published examples for the VL Discovery that's capable of doing 50 Hz, and similar ones for sampling servo drive inputs. ie 20 ms, 50 Hz, variable duty
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cchechio
Associate II
Posted on July 01, 2014 at 17:13

With TIM4,

I can measure only signal with a frequency more of 1400 Hz. If I descrease (for example 1000 Hz or 50Hz) the frequency of input signal to PB7,the value of Frequency variable (in debug) is not correct. 

cchechio
Associate II
Posted on July 01, 2014 at 17:22

If I increase the prescaler in the main from TIM_ICPSC_DIV1 to TIM_ICPSC_DIV8:

  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_ICPrescaler =  TIM_ICPSC_DIV8;

  TIM_ICInitStructure.TIM_ICFilter = 0x0;

if input signal has a frequency of 1000Hz the frequency variable (in debug) read 4547

if input signal has a frequency of 100Hz the frequency variable (in debug) read 1564

if input signal has a frequency of 50Hz the frequency variable (in debug) read 2007

Posted on July 01, 2014 at 17:43

That's the INPUT's prescaler, it decimates the input signal, ie measures the time for 8 cycles vs 1 cycle. It will make the situation WORSE, if the problem is a 16-bit overflow.

You need to change the TIMEBASE's prescaler, so the granularity of the measurement is COURSER, and doesn't overflow the 16-bit number space, or use a 32-bit timer which would permit finer granularity, and longer span.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cchechio
Associate II
Posted on July 01, 2014 at 20:22

How can I change the TIMEBASE's prescaler?

Posted on July 01, 2014 at 21:11

How can I change theTIMEBASE'sprescaler?

It's really going to help if you read the chapter in the manual about the timers.

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0; // N-1, ie 0=DIV1, 1=DIV2, 2=DIV3 of the TIMCLK (Nominally APB*2, or APB*1)
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Maximal 16-bit, for 32-bit ones use 0xFFFFFFFF
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Filter Clock
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cchechio
Associate II
Posted on July 02, 2014 at 14:58

I use TIM4,

main.c

...

  TIM4_Config();

  /* Time base configuration */

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  

  TIM_TimeBaseStructure.TIM_Prescaler = ?; 

  TIM_TimeBaseStructure.TIM_Period = ?;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0; 

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

...

can you help me with mathematical formulas how calculate prescaler and period

to read a signal about 100 Hz?

My ultimate objective is calculate precise frequency of a signal about 100Hz 

Posted on July 02, 2014 at 20:39

You want the Period to be maximal, ie to FILL a 16-bit unsigned integer

If you have the Time Base ticking at 5 MHz or 6 MHz, a 100 Hz signal would represent 50000 or 60000 ticks respectively and thus fit within 16-bit, ie 0..65535 range. For an STM32F4 running at 168 MHz TIM4 is 16-bit ticking at 84 MHz 5 MHz does not cleanly divide, 6 MHz does, but there are other options, this just makes the math easier. So 84,000,000 / 6,000,000 = 14

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 14 - 1; // ((SystemCoreClock / 2) / 6000000) - 1
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Maximal 16-bit, for 32-bit ones use 0xFFFFFFFF
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Filter Clock
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

If you take TWO measurements of CCR1, ie 100 then 60100 TimeBase clock divided by delta ticks Hz = 6000000 / (60100 - 100) Hz = 100 If you variability from 100 Hz is too large, consider a 3 or 4 MHz TimeBase clock.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..