cancel
Showing results for 
Search instead for 
Did you mean: 

stm32 f3 discovery tim2 to capture 4 pwm input

jipeng
Associate II
Posted on January 23, 2014 at 06:24

the office pwm input example is work ok, but i want to capture 4pwm with one timer,so i find this:https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Discovery%2FPWM%20Input%20capture%20doesnt%20work%20on%20Ch34%20pair&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=642

and this: https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fMultiple%20PWM%20input%20capture%20on%20one%20timer&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A7... but above two way i can't run it, so i modifie the standard example like this;


static
void
TIM_Config(
void
)

{

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;


/* TIM2 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


/* GPIOB clock enable */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);


/* TIM2 chennel2 configuration : PA.01 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

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(GPIOA, &GPIO_InitStructure);


/* Connect TIM pin to AF1 */

GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);


/* Enable the TIM2 global Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//TIM_DeInit(TIM2); 


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 enable counter */

TIM_Cmd(TIM2, ENABLE);


/* Enable the CC2 Interrupt Request */

TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

}


void
TIM2_IRQHandler(
void
)

{

RCC_GetClocksFreq(&RCC_Clocks);

TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

IC2Value = TIM_GetCapture2(TIM2);

Frequency = RCC_Clocks.HCLK_Frequency;

}

this code can work,but when change to TIM_IT_CC1,TIM_IT_CC3,TIM_IT_CC4. it not work,why?like below


static
void
TIM_Config(
void
)

{

......

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

......

/* Enable the CC2 Interrupt Request */

TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);

}


void
TIM2_IRQHandler(
void
)

{

RCC_GetClocksFreq(&RCC_Clocks);

TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

IC2Value = TIM_GetCapture1(TIM2);

Frequency = RCC_Clocks.HCLK_Frequency;

}

#stm32 #discovery #f3 #pwm-input
6 REPLIES 6
chen
Associate II
Posted on January 23, 2014 at 10:58

Hi

''this code can work,but when change to TIM_IT_CC1,TIM_IT_CC3,TIM_IT_CC4.

it not work,why?''

Look at the reference manual for the F3 device.

Look VERY CAREFULLY at the block diagram for the timers.

Note how the compare registers are linked to CCR registers.

It is only possible to use a compare register with the associated CCR register.

jipeng
Associate II
Posted on January 23, 2014 at 14:36

thanks

Posted on January 23, 2014 at 15:50

So you're trying to measure a PWM signal, ie the period and duty, or just the frequency (period) of the signal?

PWM Input mode isn't going to support multiple channels, it resets the counter, the only element in the timer that ticks. For four channel you have to use input capture you need to measure the delta between two consecutive samples. You can't just pull the value out of the register with no point of reference. A point them seems to have been lost on you in examining the examples I've previously posted.

For 4-channels measuring different frequencies the first cite should get you most of the way there. If the duty is critical then you'll need to time stamp both edges of the signal. The interrupt method also won't be viable at high clock rates (>50-100KHz?)

You probably want to avoid reading the clock settings repeatedly in the interrupt, do that once into a global variable.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jipeng
Associate II
Posted on January 24, 2014 at 03:10

thanks, i will do it.

jipeng
Associate II
Posted on January 26, 2014 at 17:07

hi, clive1,i modified the code like below:

static void TIM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOB clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* TIM2 chennel2 configuration : PA.01 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
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_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM pin to AF1 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_DeInit(TIM2); 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
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(TIM2, &TIM_ICInitStructure);
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
}
struct PWM_State {
uint8_t state;
uint16_t rise;
uint16_t fall;
uint16_t capture;
}Inputs[4] = { { 0, } };
/**
* @brief This function handles TIM2 global interrupt request.
* @param None
* @retval None
*/
void TIM2_IRQHandler(void)
{
static uint32_t Current;
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
Current = TIM_GetCapture1(TIM2);
if (Inputs[0].state == 0) {
Inputs[0].rise = Current;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[0].state = 1;
} else {
Inputs[0].fall = Current;
Inputs[0].capture = Inputs[0].fall - Inputs[0].rise;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[0].state = 0;
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
Current = TIM_GetCapture2(TIM2);
if (Inputs[1].state == 0) {
Inputs[1].rise = Current;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[1].state = 1;
} else {
Inputs[1].fall = Current;
Inputs[1].capture = Inputs[1].fall - Inputs[1].rise;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[1].state = 0;
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
Current = TIM_GetCapture3(TIM2);
if (Inputs[2].state == 0) {
Inputs[2].rise = Current;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[2].state = 1;
} else {
Inputs[2].fall = Current;
Inputs[2].capture = Inputs[2].fall - Inputs[2].rise;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[2].state = 0;
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
Current = TIM_GetCapture4(TIM2);
if (Inputs[3].state == 0) {
Inputs[3].rise = Current;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[3].state = 1;
} else {
Inputs[3].fall = Current;
Inputs[3].capture = Inputs[3].fall - Inputs[3].rise;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
Inputs[3].state = 0;
}
}
}

i think the capture is ths pulse width,Inputs[i].caputer = Inputs[i].fall-Inputs[i].rise.but the measurement of each loop value is not the same.am i misunderstand sth? whether the duty = pulse/period; frequence = 10000/period; period = rise - prevrise; pulse = fall - rise. thanks;
Posted on January 26, 2014 at 17:28

Be aware you also have :

TIM_ICPolarity_BothEdge

You haven't stated the frequencies you are attempting to measure, this would be helpful to know.

duty = pulse/period;

period = rise - prevrise;

pulse = fall - rise;

Yes

frequence = 10000/period;

No, unless you happened to set the timer to 10KHz, which I don't see any evidence. The timer is presumably clocking at 72 or 36 MHz depending on what speed you're running the processor, and the peripheral buses.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..