3
\$\begingroup\$

Update

I checked the block diagram of the timer 3 again

block diagram

It looks like there's no connection between channel 4 and the trigger input TRGI. Is this correct?

Can I use channel 4 for gated mode?

original question

I have the following signal with varying pulse width. (high)

pulses

I want to measure the pulse width with an STM32F030F4 (link removed due to reputation limit).

The signal is connected to Pin 14, PB1. I verified that the signal can be scoped directly at the pin of the µC, so it should be there. I want to use timer 3 because its channel 4 is connected to that pin.

Chapter 13.3.19 TIMx and external trigger synchronization of the reference manual describes a mode that's exactly what I'm looking for.

Slave mode: Gated mode

The counter can be enabled depending on the level of a selected input.

There's also an example for that:

A.8.13 Gated mode code example

/* (1) Configure channel 1 to detect low level on the TI1 input       
by writing CC1S = ‘01’,       
and configure the input filter duration by writing the IC1F[3:0]       
bits in the TIMx_CCMR1 register (if no filter is needed,       
keep IC1F=0000). */ 

/* (2) Select polarity by writing CC1P=1 in the TIMx_CCER register */ 

/* (3) Configure the timer in gated mode by writing SMS=101       
Select TI1 as the trigger input source by writing TS=101       
in the TIMx_SMCR register. */ 

/* (4) Set prescaler to 12000-1 in order to get an increment each 250us */ 

/* (5) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */ 

TIMx->CCMR1 |= TIM_CCMR1_CC1S_0; /* (1)*/ 
TIMx->CCER |= TIM_CCER_CC1P; /* (2) */ 
TIMx->SMCR |= TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0 | TIM_SMCR_TS_2 | TIM_SMCR_TS_0; /* (3) */ 
TIMx->PSC = 11999; /* (4) */ 
TIMx->CR1 |= TIM_CR1_CEN; /* (5) */

I tried to modify the example to my needs and it looks like that:

// based on example A.8.13

/* (1) Configure channel 4 to detect low level on the TI4 input
 * by writing CC4S = ‘01’,
 * and configure the input filter duration by writing the IC1F[3:0]
 * bits in the TIMx_CCMR1 register (if no filter is needed,
 * keep IC1F=0000). */

/* (2) Select polarity by writing CC4P=1 in the TIMx_CCER register */

/* (3) Configure the timer in gated mode by writing SMS=101
 * Select TI1 as the trigger input source by writing TS=101
 * in the TIMx_SMCR register. */

/* (4) Set prescaler to 12000-1 in order to get an increment each 250us */

/* (5) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */

TIM3->CCMR2 |= TIM_CCMR2_CC4S_0; /* (1) */
TIM3->CCER |= TIM_CCER_CC4P; /* (2) */
TIM3->SMCR |= TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0 | TIM_SMCR_TS_2 | TIM_SMCR_TS_0; /* (3) */
TIM3->PSC = 11999; /* (4) */
TIM3->CR1 |= TIM_CR1_CEN; /* (5) */

I would expect that the counter register of timer 3 TIM3->CNT changes over time as the pulses tickle in.

However, TIM3->CNT does not change at all.

Here's the configuration that I suspect to be erroneous

GPIO

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(tim_baseHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspInit 0 */

  /* USER CODE END TIM3_MspInit 0 */
    /* Peripheral clock enable */
      __TIM3_CLK_ENABLE();

    /**TIM3 GPIO Configuration
    PB1     ------> TIM3_CH4
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM3_MspInit 1 */

  /* USER CODE END TIM3_MspInit 1 */
  }
}

timer

/* TIM3 init function */
void MX_TIM3_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_IC_InitTypeDef sConfigIC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 0;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }

}

When debugging, I can see the configuration registers change and read/write their values, but the counter register is not increasing.

\$\endgroup\$
  • \$\begingroup\$ Where do you call __TIM3_CLK_ENABLE();? \$\endgroup\$ – Bence Kaulics Nov 10 '16 at 18:16
  • \$\begingroup\$ @BenceKaulics sorry for not posting the full code, question edited. I also verified that both initialisations get called by putting breakpoints into each. Does the order matter? The GPIO goes first. \$\endgroup\$ – cross Nov 11 '16 at 8:16
  • \$\begingroup\$ The order is fine as it is. \$\endgroup\$ – Bence Kaulics Nov 11 '16 at 9:16
  • \$\begingroup\$ @BenceKaulics I checked the block diagram again and maybe what I'm trying isn't even possible with this timer and channel? \$\endgroup\$ – cross Nov 11 '16 at 15:45
  • \$\begingroup\$ I do not this specific feature but the trigger controller seems to be connected to all channels. Channel 4 cannot give trigger I think, but that is not the problem. Your trigger source is ITR0 but I do not know what should drive this line. Your timer probably does not receive trigger and won't be enabled. You should find out where does that ITR0 should come from. \$\endgroup\$ – Bence Kaulics Nov 11 '16 at 16:19
1
\$\begingroup\$

Looks like using the input capture mode is not possible, because channel 4 cannot be used as trigger.

I give up. Too many different examples on the web using too many different configuration tools, tool chains, etc.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.