2017-07-17 02:15 PM
I am using the STM32F4 board's TIM8 in order to generate a quadrature PWM signal at varying frequencies. That is working great; however, I need to decode the signal as it is being produced, aka, count the rising edges of channels A and B. I've tried using TIM8 to count it and I got huge numbers. When I tried to use TIM5 as shown below, the TIM_GetCounter(TIMx) function returns zero. Any suggestions? Thank you in advance!
void InitializeTIM()
{ //sets clock for TIM8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); //sets clock for TIM5 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //MAY NEED TO CHANGE CLOCK // PERIOD -> DEPENDS ON VELOCITY float velocity = 0.25; //0.1; //meters/s uint16_t half_period = Calculate_Period(velocity); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure8; //creates structure for TIM8 TIM_OCInitTypeDef TIM_OCInitStructure; //creates structure for PWM //Time base configuration TIM8 TIM_TimeBaseStructure8.TIM_Prescaler = PSC_Value; TIM_TimeBaseStructure8.TIM_Period = half_period; TIM_TimeBaseStructure8.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure8.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure8); //Enable TIM8 Preload register on ARR TIM_ARRPreloadConfig(TIM8, ENABLE); //TIM8 PWM1 Configuration --> 50% duty cycle TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //CHANNEL A -> PC8 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = half_period; // PHASE SHIFT TIM_OC3Init(TIM8, &TIM_OCInitStructure); //CHANNEL B -> PC9 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_Pulse = (half_period/2); // PHASE SHIFT TIM_OC4Init(TIM8, &TIM_OCInitStructure); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure5; //creates structure for TIM5 //Time base configuration TIM5 TIM_TimeBaseStructure5.TIM_Prescaler = PSC_Value*0.3071; TIM_TimeBaseStructure5.TIM_Period = 65535; TIM_TimeBaseStructure5.TIM_ClockDivision = 0; TIM_TimeBaseStructure5.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure5); //Encoder count configuration TIM5 TIM_ETRClockMode1Config(TIM5, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); //timer used, no prescaler, active on rising edge, no filter // Enables counter TIM_Cmd(TIM8, ENABLE); TIM_Cmd(TIM5, ENABLE); }void InitializePINS()
{ //******************** TIM 8 ********************// //GENERATING PWM RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //creates structure for GPIOC GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;//PC8 & PC9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //alternative function GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //operating output GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //push or pull of pin GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // speed of pins -> slower saves power and cancels out some of the noise GPIO_Init(GPIOC, &GPIO_InitStructure); //intializes structure // Sets pin's alternative function to that of TIM8 GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM8); GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM8); //******************** TIM 5 ********************// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //creates structure for GPIOE GPIO_InitTypeDef GPIO_InitStructure2; GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_2; //| GPIO_Pin_3; GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF; //alternative function GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_UP; //push or pull of pin GPIO_Init(GPIOA, &GPIO_InitStructure2); //intializes structure // Sets pin's alternative function to that of TIM5 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5); //GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5); //******************** TIM 5 ********************/ }int main(void)
{ //Initializing functions InitializePINS(); InitializeTIM(); pulse_counter = 0; previous_round = 0; while(1) { TIM_CtrlPWMOutputs(TIM8, ENABLE); pulse_counter = TIM_GetCounter(TIM5); totalPulses = cycle_counter - previous_round; previous_round = cycle_counter; } return 0; }#timers #external-clock #pwm2017-07-17 03:14 PM
From an external pin this is a TIM9_CH1 configuration, modify to suit..
void TIM9_Configuration(void)
{ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 16-bit maximal TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);
TIM_TIxExternalClockConfig(TIM9, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0);
TIM_Cmd(TIM9, ENABLE);
}2017-07-18 08:48 AM
Thank you for replying! I tried the solution you gave me, but 0 was still returned from the GetCounter() function. I didn't change my pin config- I'm still using PA2, just switched it to TIM9. Do you think that I need to config it an external pin for a channel in TIM8 since that's the timer that is generating the PWM? Also, where did you find the information to know it's an external pin with the TIM9_CH1 config? I've looked over the datasheets and couldn't find it. Thank you in advance!
2017-07-18 10:48 AM
I copied this from an external clock demo I built, doesn't use the same TIM and pins as you. I prefer to post code I know that works than dig through and correct code I didn't write on platforms I don't own.
The Data Manual provides specific pin associativity, the Reference Manual would cover possible internal connectivity options, you will need to review those in the context of your design/implementation.
The TIM9 code provides specifics on correct time base initialization, ie no prescaler, or other settings, just a wrapping 16-bit count, visible from TIM9->CNT to input clock stream on TIM9_CH1, in this case I think my source was PA2 (AF3)
2017-07-18 10:53 AM
PA2 is also TIM5_CH3 (AF2), I don't think that's routable using
TIM_TIxExternalClockConfig(), you'd need to dig into those options.
2017-07-19 03:03 PM
So, to anyone that is following this and would appreciate the solution I found..
Basically, after looking at the manual, I noticed a 'Figure 94'. It's related to the input triggers for the advanced timers 1 and 8. I reconfigured my PWM toggle to use TIM5 so that I could use TIM5's TRGO to input into TIM1 (ITR0); TIM1 will count the rising edges of TIM5 now. In other words, TIM5 is the master of TIM1. It seems to be working quite nicely- I get a triangle wave as I count up and store the values into an array. I hope this helps for anyone who needs it!