cancel
Showing results for 
Search instead for 
Did you mean: 

Variable runover before it reaches its limit

HNguy.25
Associate III

Hello everyone,

My variable had a Runover even before it reached its range.

Currently, I am working with timer 2 with a frequency of 90MHz. When I retrieved the current time by `__HAL_TIM_GET_COUNTER()` and printed it by `printf("receive_time: %lu\n", (unsigned long)receive_time)`, the maximum the `receive_time` get is 16 bits although I declared it as 32 bits. I observed the printed value and it never exceeded 2^16 -1. 

I also tried to print with `printf("%" PRIu32 "\n",a);` but it also returned the same. 

I had another 32-bit variable `send_time` which is used later to subtract with `receive_time`. However, it gave me something in the order of 2*10^9 (2147482170 for example) besides some common values.

I want to ask what happen and if I do something wrong. If everything is correct, is there any way to handle the rollover besides having 2 timers starting at different times?

The code is here:

Radio::radio.tx_buf[0] = seq++; /* set payload */
 
  printf("send a ready message\r\n");
 
  Radio::Send(1, 0, 0, 0);  /* begin transmission */
 
  send_time = __HAL_TIM_GET_COUNTER(&htim2);
 
.
 
.
 
.
 
if (Radio::radio.rx_buf[0] == 100)
 
  {
 
    receive_time = __HAL_TIM_GET_COUNTER(&htim2);
 
    printf("receive_time: %lu\n", (unsigned long)receive_time);
 
    printf("send_time: %lu\n", (unsigned long)send_time);
 
    time_difference = (receive_time - send_time)/2;
 
    printf("time_difference: %lu\n", (unsigned long)time_difference);
 
    uint32_t distance = time_difference * 10 / 3;
 
    printf("Distance: %lu\n", (unsigned long)distance);
 
  }

Thank you in advance,

Huy Nguyen.

1 ACCEPTED SOLUTION

Accepted Solutions
Danish1
Lead II

Sorry I was wrong about the 32-bit timer. I didn't spot you specifying which stm32 you were using, and many are only 16-bit even for TIM2.

Looking at e.g. stm32f4xx_hal_tim.h, I see __HAL_TIM_GET_COUNTER expands to

((__HANDLE__)->Instance->CNT)

It might be worth looking at the code your compiler generates, to verify that it is doing a 32-bit access to htim2.Instance->CNT

And with a debugger seeing if the top 16-bits in TIM2->CNT ever get set.

How strongly do you know that htim2 refers to TIM2?

Regards,

Danish

View solution in original post

5 REPLIES 5
Danish1
Lead II

The problem isn’t your variable.

The underlying hardware of stm32 timers is generally 16-bit. Have a look at the TIM section of the Reference Manual for your stm32 for a better understanding of the issues involved.

I strongly dislike ST’s HAL library because the documentation is inadequate. Although it helps users avoid “gotchas�?, users still need to understand the limitations of the underlying hardware, which is ONLY covered by the Reference Manual, Data Sheet and Programming Manual.

Hope this helps,

Danish

Hello @Danish​ 

Thank you for your response. Before using the timer 2, I did check the manual about timer in the datasheet as below:

0693W00000WId0JQAT.pngAnd timer 2 has a counter of 32-bit.

That is why I got confused a bit.​

Danish1
Lead II

Sorry I was wrong about the 32-bit timer. I didn't spot you specifying which stm32 you were using, and many are only 16-bit even for TIM2.

Looking at e.g. stm32f4xx_hal_tim.h, I see __HAL_TIM_GET_COUNTER expands to

((__HANDLE__)->Instance->CNT)

It might be worth looking at the code your compiler generates, to verify that it is doing a 32-bit access to htim2.Instance->CNT

And with a debugger seeing if the top 16-bits in TIM2->CNT ever get set.

How strongly do you know that htim2 refers to TIM2?

Regards,

Danish

For the question "How strongly do you know that htim2 refers to TIM2?": it is in the initialization of timer 2. htim2 is just a name. And in the initialization function, the instance of htim2 is TIM2 (htim2.Instance = TIM2;)

As for your other suggestion, I will bear that in mind and check it. I think it is also about the maximum counter or Auto Reload Register (ARR).

I will update more.

The ARR value is the issue here. Earlier, I used the TIM10 and its maximum value is only 16 bits. Later I changed to TIM2 and its maximum value is 32 bits but I forgot to set the Period (ARR) value so the counter rolled over when it reached 16-bit. As I set the Period (ARR) value to the maximum possible (32 bits), it returned the values that I want.

Thank you for helping me.