cancel
Showing results for 
Search instead for 
Did you mean: 

PWM input with a signal that can get stuck high or low

Posted on February 24, 2015 at 00:11

I'm using TIM1 channels 1 and 2 to resolve a PWM input. So far I have been able to get the frequency to a deci-hertz and the duty cycle to a deci-percent.

Since the input signal can, legitimately, go high or low and stay there, I will get no more interrupts to unload the timer and update the calculations.

The timer should count to 0xFFFF (counter period), but can I get it to generate an interrupt at that point so I can see where the PWM input is stuck?

Thanks.

#tim-pwm-stm32
5 REPLIES 5
Posted on February 24, 2015 at 01:45

Isn't that the Update interrupt? (STM32F4 -> TIM1_UP_TIM10_IRQHandler)

For some other timeout number, use Channel 3 or 4 with compare values?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 25, 2015 at 00:26

Nothing yet.

What I did is set up the CC and UP interrupts, the CC system works nicely. I set the Timer1 period to 0xFFFF, expecting that when the timer1 CNT register increments (clocked by APB2/1000 == 84MHz/1000) and reaches 0xFFFF (countup), I would get the update interrupt as the counter reloads - but Noooooo. Code follows. (The following is my best understanding of how the PWM input resolving system works) For those not playing along, timer1 is being incremented by a fraction of the system clock. An external signal on TIM1_CH1 causes the capture 1 register to grab a snapshot of CNT on a high going transition. The timer setup also routes TIM1_CH1 to channel 2 which grabs a snapshot of CNT on a low going transition. In the system that I am working with, the PWM can range from 0 to 100% inclusive. Now, when TIM1_CH1 does not make any transitions (stuck high or low because of the nature of the equipment), channel 1 and channel 2 will not grab the value of the CNT register, nor will it cause CNT to clear, it will just keep counting. Eventually CNT will hit 0xFFFF and SHOULD cause a UP interrupt. As you can see from my interrupt routine entry routine

TIM1_UP_TIM10_IRQHandler

I have put in code to toggle a bit when the routine is entered (yes I have tested the toggle bit stuff). I get no indication of the interrupt triggering. Bother. Clive, thanks for your help. You should get paid by ST.


tim.c


TIM_HandleTypeDef htim1;

TIM_HandleTypeDef htim2;

TIM_HandleTypeDef htim3;

TIM_HandleTypeDef htim4;

TIM_HandleTypeDef htim6;


/* TIM1 init function */

void MX_TIM1_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_SlaveConfigTypeDef sSlaveConfig;

TIM_MasterConfigTypeDef sMasterConfig;

TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

TIM_IC_InitTypeDef sConfigIC;

TIM_OC_InitTypeDef sConfigOC;


htim1.Instance = TIM1;

htim1.Init.Prescaler = 1000;

htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

htim1.Init.Period = 0xffff;

htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim1.Init.RepetitionCounter = 0;

HAL_TIM_Base_Init(&htim1);


sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_RISING;

sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;

sClockSourceConfig.ClockFilter = 1;

HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);


HAL_TIM_IC_Init(&htim1);


HAL_TIM_PWM_Init(&htim1);


sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;

sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;

sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sSlaveConfig.TriggerFilter = 0;

HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);


sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);


sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSI_DISABLE;

sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

sBreakDeadTimeConfig.DeadTime = 0;

sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);


sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

sConfigIC.ICFilter = 0;

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);


sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;

sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2);


sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.Pulse = 0;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4);


}


void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)

{


GPIO_InitTypeDef GPIO_InitStruct;

if(htim_base->Instance==TIM1)

{

/* USER CODE BEGIN TIM1_MspInit 0 */


/* USER CODE END TIM1_MspInit 0 */

/* Peripheral clock enable */

__TIM1_CLK_ENABLE();


/**TIM1 GPIO Configuration 

PE9 ------> TIM1_CH1

PE14 ------> TIM1_CH4 

*/

GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_14;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);


/* Peripheral interrupt init*/

HAL_NVIC_SetPriority(TIM1_CC_IRQn, 8, 0);

HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);

HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 7, 0);

HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);

/* USER CODE BEGIN TIM1_MspInit 1 */


/* USER CODE END TIM1_MspInit 1 */

}

{yadda}


stm32f4xx_it.c


void TIM1_CC_IRQHandler(void)

{

/* USER CODE BEGIN TIM1_CC_IRQn 0 */


/* USER CODE END TIM1_CC_IRQn 0 */

HAL_TIM_IRQHandler(&htim1);

/* USER CODE BEGIN TIM1_CC_IRQn 1 */


/* USER CODE END TIM1_CC_IRQn 1 */

}


void TIM1_UP_TIM10_IRQHandler(void)

{

/* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */

HAL_GPIO_WritePin( GPIOD, GPIO_PIN_11, GPIO_PIN_SET);


/* USER CODE END TIM1_UP_TIM10_IRQn 0 */

HAL_TIM_IRQHandler(&htim1);

/* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */

HAL_GPIO_WritePin( GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);


/* USER CODE END TIM1_UP_TIM10_IRQn 1 */

}

Nickname1997_O
Associate II
Posted on February 25, 2015 at 16:06

Hello Andrei

just a comment, Did you enable the UPDATE IT by using either : __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE); or HAL_TIM_Base_Start_IT(&htim1); on top of the input capture start function ( to get the pwm input capture started with CC interrupt enabled) HAL_TIM_IC_Start_IT (&htim1,TIM_CHANNEL_1); regards

From: chichak.andrei

Posted: Wednesday, February 25, 2015 12:27 AM Subject: PWM input with a signal that can get stuck high or low

Nothing yet.

What I did is set up the CC and UP interrupts, the CC system works nicely. I set the Timer1 period to 0xFFFF, expecting that when the timer1 CNT register increments (clocked by APB2/1000 == 84MHz/1000) and reaches 0xFFFF (countup), I would get the update interrupt as the counter reloads - but Noooooo. Code follows. (The following is my best understanding of how the PWM input resolving system works) For those not playing along, timer1 is being incremented by a fraction of the system clock. An external signal on TIM1_CH1 causes the capture 1 register to grab a snapshot of CNT on a high going transition. The timer setup also routes TIM1_CH1 to channel 2 which grabs a snapshot of CNT on a low going transition. In the system that I am working with, the PWM can range from 0 to 100% inclusive. Now, when TIM1_CH1 does not make any transitions (stuck high or low because of the nature of the equipment), channel 1 and channel 2 will not grab the value of the CNT register, nor will it cause CNT to clear, it will just keep counting. Eventually CNT will hit 0xFFFF and SHOULD cause a UP interrupt. As you can see from my interrupt routine entry routine

TIM1_UP_TIM10_IRQHandler

I have put in code to toggle a bit when the routine is entered (yes I have tested the toggle bit stuff). I get no indication of the interrupt triggering. Bother. Clive, thanks for your help. You should get paid by ST.


tim.c


TIM_HandleTypeDef htim1;

TIM_HandleTypeDef htim2;

TIM_HandleTypeDef htim3;

TIM_HandleTypeDef htim4;

TIM_HandleTypeDef htim6;


/* TIM1 init function */

void MX_TIM1_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_SlaveConfigTypeDef sSlaveConfig;

TIM_MasterConfigTypeDef sMasterConfig;

TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

TIM_IC_InitTypeDef sConfigIC;

TIM_OC_InitTypeDef sConfigOC;


htim1.Instance = TIM1;

htim1.Init.Prescaler = 1000;

htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

htim1.Init.Period = 0xffff;

htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim1.Init.RepetitionCounter = 0;

HAL_TIM_Base_Init(&htim1);


sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_RISING;

sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;

sClockSourceConfig.ClockFilter = 1;

HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);


HAL_TIM_IC_Init(&htim1);


HAL_TIM_PWM_Init(&htim1);


sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;

sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;

sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sSlaveConfig.TriggerFilter = 0;

HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);


sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);


sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSI_DISABLE;

sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

sBreakDeadTimeConfig.DeadTime = 0;

sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);


sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

sConfigIC.ICFilter = 0;

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);


sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;

sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2);


sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.Pulse = 0;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4);


}


void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)

{


GPIO_InitTypeDef GPIO_InitStruct;

if(htim_base->Instance==TIM1)

{

/* USER CODE BEGIN TIM1_MspInit 0 */


/* USER CODE END TIM1_MspInit 0 */

/* Peripheral clock enable */

__TIM1_CLK_ENABLE();


/**TIM1 GPIO Configuration 

PE9 ------> TIM1_CH1

PE14 ------> TIM1_CH4 

*/

GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_14;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);


/* Peripheral interrupt init*/

HAL_NVIC_SetPriority(TIM1_CC_IRQn, 8, 0);

HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);

HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 7, 0);

HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);

/* USER CODE BEGIN TIM1_MspInit 1 */


/* USER CODE END TIM1_MspInit 1 */

}

{yadda}


stm32f4xx_it.c


void TIM1_CC_IRQHandler(void)

{

/* USER CODE BEGIN TIM1_CC_IRQn 0 */


/* USER CODE END TIM1_CC_IRQn 0 */

HAL_TIM_IRQHandler(&htim1);

/* USER CODE BEGIN TIM1_CC_IRQn 1 */


/* USER CODE END TIM1_CC_IRQn 1 */

}


void TIM1_UP_TIM10_IRQHandler(void)

{

/* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */

HAL_GPIO_WritePin( GPIOD, GPIO_PIN_11, GPIO_PIN_SET);


/* USER CODE END TIM1_UP_TIM10_IRQn 0 */

HAL_TIM_IRQHandler(&htim1);

/* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */

HAL_GPIO_WritePin( GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);


/* USER CODE END TIM1_UP_TIM10_IRQn 1 */

}

Posted on February 25, 2015 at 17:50

Yes, well spotted, I forgot to list this bit:


if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2) != HAL_OK) {

/* Starting Error */

error();

}


/*##-5- Start the Input Capture in interrupt mode ##########################*/

if (HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK) {

/* Starting Error */

error();

}

Posted on February 25, 2015 at 18:44

Thanks Stark,

This was the solution:

__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);

The HAL start routine for IT enables the CC interrupt, but not the UP.

Thanks again.