2014-06-23 09:03 AM
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****/ #!rocketscience2014-06-29 12:22 PM
2014-06-29 03:08 PM
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 duty2014-07-01 08:13 AM
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.2014-07-01 08:22 AM
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 4547if input signal has a frequency of 100Hz the frequency variable (in debug) read 1564if input signal has a frequency of 50Hz the frequency variable (in debug) read 20072014-07-01 08:43 AM
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.2014-07-01 11:22 AM
How can I change the TIMEBASE's prescaler?
2014-07-01 12:11 PM
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);
2014-07-02 05:58 AM
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 periodto read a signal about 100 Hz?My ultimate objective is calculate precise frequency of a signal about 100Hz2014-07-02 11:39 AM
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 = 14TIM_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.