2014-01-22 09:24 PM
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¤tviews=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
2014-01-23 01:58 AM
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.2014-01-23 05:36 AM
thanks
2014-01-23 06:50 AM
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.2014-01-23 06:10 PM
thanks, i will do it.
2014-01-26 08:07 AM
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;
2014-01-26 08:28 AM
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.