cancel
Showing results for 
Search instead for 
Did you mean: 

TIM2_ETR on Nucleo-f439zi

james_collins_curvalux
Associate II

I have a 1Hz square wave signal with a 50 % duty cycle going into a pin on the MCU.

The pin on the MCU (PA0) is configured to be TIM2_ETR via the STM MX Cube tool.

I am expecting to go into TIM2_IRQHandler() every second, i.e. every positive edge of the external clock.

However, I don't, I just go in TIM2_IRQHandler once just after startup.

Any ideas as to why this is happening ?

1 ACCEPTED SOLUTION

Accepted Solutions
Bob S
Principal

I think you have things backwards.  The "input capture" function copies the current TIMx.CNT value into the CCR register.  If you want to count the number of signal_b edges per signal_a edge, put signal_b into the ETR as clock, then signal_a into CH4.  Then instead of HAL_TIM_Start_IT() you need to call the "start input capture" (I don't recall the exact name).

View solution in original post

7 REPLIES 7
Bob S
Principal

Can't help much without seeing your code.  Are you using the stock HAL TIM2_IRQHandler()?

static void MX_TIM2_Init(void)
{

/* USER CODE BEGIN TIM2_Init 0 */

/* USER CODE END TIM2_Init 0 */

TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};

/* USER CODE BEGIN TIM2_Init 1 */

/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 4294967295;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
sClockSourceConfig.ClockFilter = 0;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */

/* USER CODE END TIM2_Init 2 */

}

 

main() looks like so:

int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */

/* Start timer */
HAL_TIM_Base_Start_IT(&htim2);

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

 

Bob S
Principal

You don't show any timer callback functions, and I presume you are using the stock HAL timer interrupt handler.

You have PA0/ETR2 configured as the CLOCK input to the timer.  So every rising edge will increment the timer count.  Calling HAL_TIM_Base_Start_IT() only enabled the UPDATE interrupt (i.e. timer overflow/reload).  You SHOULD only get an interrupt after 2^32 rising edges, when the timer rolls over.  Not sure why you get 1 interrupt.

What do you REALLY want this signal to do?  Do you only need an interrupt on each rising edge?  Then maybe use GPIO EXTI instead.  Or configure PA0 as TIM2 CH1 and configure it as "input capture).

If you need an interrupt AND some kind of counter value to measure the time between interrupts, the use PA0 as an input capture like above.

james_collins_curvalux
Associate II

Yes i am using the stock HAL interrupt timer.

Ultimately what I want is shown below (I am using a GPS 1pps signal to do some sync, want to get simple example working first on dev board).

signal_a is a 1Hz square wave

signal_b is a 1kHz sinewave, amplitude of 3.3V.

I was aiming to connect signal_a to PA0, and use the TIM2_ETR functionality.

Then I was aiming to connect signal_b to PA3, and use the TIM2_CH4 input capture functionality.

In every period of signal_a (every second) I want to count signal_b, so in this case I would get the answer (should) of 1000. I would then like to reset the count of signal_b such that i cant obtain another total count (of signal_b) in the next period of signal_a.

I want to jump in interrupt associated with TIM2_ETR (every second), then pull the count from the input capture / TIM2_CH4. So every second ideally I should get 1000, on my actual circuit board though I might get 999, then 990 etc, this is when I can apply some correction factor.

Thanks for your help, really appreciate it.

 

 

Bob S
Principal

I think you have things backwards.  The "input capture" function copies the current TIMx.CNT value into the CCR register.  If you want to count the number of signal_b edges per signal_a edge, put signal_b into the ETR as clock, then signal_a into CH4.  Then instead of HAL_TIM_Start_IT() you need to call the "start input capture" (I don't recall the exact name).

Am i wrong or i do not see any :

    HAL_NVIC_SetPriority(xxxx, 9, 0);
    HAL_NVIC_EnableIRQ(xxx);

Related to Timer 2? (xxxx have to be substituted with the relative IRQN of TIM2). Please note that also the priority need to be adjusted based on your project.

 

D.

I didn't pay attention to that since the OP said they got the interrupt once.  But, yes, need to make sure the TIM2 interrupt is enabled in CubeMX.