2023-09-01 03:11 AM
Hi, I'm learning how to use timers by following digikey's tutorial : Getting Started with STM32 and Nucleo Part 6: Timers and Timer Interrupts | Digi-Key Electronics - YouTube
However at 9:41 in the video I don't understand the code :
// If enough time has passed (1 second), toggle LED and get new timestamp
if (__HAL_TIM_GET_COUNTER(&htim16) - timer_val >= 10000)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
timer_val = __HAL_TIM_GET_COUNTER(&htim16);
}
What does __HAL_TIM_GET_COUNTER(&htim16) really do? Then what the condition if is testing?
Thanks
Solved! Go to Solution.
2023-09-03 03:20 PM - edited 2023-09-03 03:22 PM
Hello @Gnahore
This part of the code is testing if the difference between TIMER_CNT(now) and TIMER_CNT went the TIMER start counting (timer_val)is equal to 10000. Which means that the TIMER has counted 1 Second.
If so, the code toggle the led and update the timer_val with the new TIMER_CNT value to restart a 1 Second count .
Rq: 10000 is calculated depends on the timer frequency and other conditions that are well explained in the tutorial.
Best regards.
II
2023-09-01 09:24 AM
Hello @Gnahore,
The HAL_TIM_GET_COUNTER is used to get the current TIM Counter Register value on runtime (from the CNT register), and return 16-bit or 32-bit value of the timer counter register (TIMx_CNT).
Imen
2023-09-03 03:20 PM - edited 2023-09-03 03:22 PM
Hello @Gnahore
This part of the code is testing if the difference between TIMER_CNT(now) and TIMER_CNT went the TIMER start counting (timer_val)is equal to 10000. Which means that the TIMER has counted 1 Second.
If so, the code toggle the led and update the timer_val with the new TIMER_CNT value to restart a 1 Second count .
Rq: 10000 is calculated depends on the timer frequency and other conditions that are well explained in the tutorial.
Best regards.
II
2023-09-03 11:27 PM
> What does __HAL_TIM_GET_COUNTER(&htim16) really do?
You can find out yourself, Cube is open source, so you can read its sources and/or step through the code in debugger.
JW
2023-09-04 12:08 AM
Btw. there is also a problem with this code:
If you'd observe timer_val in a debugger, you'd see that it changes in this way: 0-10000-20000-30000-40000-50000-60000-0-10000-20000-... etc. It means, that every 7th interval (between 60000 and 0) is half the expected lenght, as it lasts only 0.5536 seconds. And yes, it's clearly visible on the LED blinking.
This is due to the facts that a) TIM16 is 16-bit timer; b) STM32 is a 32-bit mcu thus int type is 32-bit wide; c) integer promotion rules in C are at times really tricky (although they are logical and straightforward, but sometimes understanding logical and straightforward things requires significant effort).
Correctly, the 16-bit rollover should be handled like this:
if ((uint16_t)(__HAL_TIM_GET_COUNTER(&htim16) - timer_val) >= 10000)
now timer_val will go like
... 50000-60000-4464-14464...
JW
2023-09-04 01:54 AM - edited 2023-09-04 02:10 AM
@Issamos Thank you for your answers ! But I'm still very confused. HAL_TIM_GET_COUNTER() get the tim counter register value on runtime since the start of the timer with the function HAL_TIM_Base_Start(), right? And timer_val was also set with HAL_TIM_GET_COUNTER(). So timer_val is a fixed value and HAL_TIM_Base_Start() is the one that inscrease.
Does HAL_TIM_GET_COUNTER() start at 0 when it is called in the test? Also does timer_val as for first value 0? I wonder if by the time, the timer started thanks to HAL_TIM_Base_Start() and the time the value is put in timer_val, the value of timer_val is really 0.
I'm slowly understanding but what happens when timer_val get 60000 as value? HAL_TIM_Base_Start() can't go above 65 536
Here is the full code :
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim16;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM16_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t timer_val;
/* 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_USART2_UART_Init();
MX_TIM16_Init();
/* USER CODE BEGIN 2 */
// Start timer
HAL_TIM_Base_Start(&htim16);
// Get current time (microseconds)
timer_val = __HAL_TIM_GET_COUNTER(&htim16);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// If enough time has passed (1 second), toggle LED and get new timestamp
if (__HAL_TIM_GET_COUNTER(&htim16) - timer_val >= 10000)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
timer_val = __HAL_TIM_GET_COUNTER(&htim16);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2023-09-04 02:18 AM
Thanks for answering @waclawek.jan
How does timer_val go back to 0 ? From what I understood HAL_TIM_GET_COUNTER don't go above 65 536 so at what moment
HAL_TIM_GET_COUNTER(&htim16) - timer_val) >= 10000
can happen when timer_val reached 60 000 ?
2023-09-05 06:23 AM
Any answer ?
2023-09-05 06:36 AM
Hello @Gnahore
I don't have a clear answer to your question but I suggest you to close these post by choosing a best answer and copie your new request to a new post to give him more visibility.
Best regards.
II
2023-09-05 03:26 PM - edited 2023-09-05 03:27 PM
How does timer_val go back to 0 ? From what I understood HAL_TIM_GET_COUNTER don't go above 65 536 so at what moment
HAL_TIM_GET_COUNTER(&htim16) - timer_val) >= 10000
can happen when timer_val reached 60 000 ?
In this case, the subtraction is between unsigned variables, and that, according to C99 conversion rules, results in an unsigned value. So, when TIM_CNT rolls over from 65535 to 0, the subtraction result is 0x0000'0000-0x0000'EA60 = 0xFFFF'15A0 and that is higher than 10000.
> does timer_val as for first value 0?
Well spotted - as an uninitialized local variable, timer_val has a "random" initial value, so that's another bug in that program. However, due to the just described unsigned subtraction and the range of TIMx_CNT, the first period won't last longer than 1s, and most probably (for most timer_val values) the program won't wait at all in the first period.
JW