从 32 位计时器获取 64 位时间戳 [英] Get 64bit timestamps from a 32bit timer

查看:63
本文介绍了从 32 位计时器获取 64 位时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 stm32wb55 上,我使用的是 32 位定时器tim2";用于从 32 位寄存器CNT"读取时间;系统启动以来.通过预缩放,我在腻子控制台上以微秒为单位显示时间,并且效果很好.但是现在,我需要记住更高的值.所以我想以 64 位整数来存储时间.

On my stm32wb55, I am using the 32bit-timer "tim2" for reading the time from 32bit-register "CNT" since system startup. With prescaling, I display the time in microseconds on my putty-console and it works very well. But now, I need to memory higher values. So I want to memory the time in a 64bit integer.

有人知道这样做的简单方法吗?

Does anyone know a simple way for doing that?

推荐答案

tim2 定时器是一个 32 位分辨率的定时器,你想要 64 位分辨率.有两种方法可以模拟 64 位计数器,以跟踪您的正常运行时间.

The tim2 timer is a 32bit resolution timer, you want a 64bit resolution. There are two ways to emulate a 64bit counter, to keep track of your uptime.

  1. 每次到达要跟踪的时间单位时都会增加一个变量.但鉴于微控制器将进行大量持续的上下文切换,这将是非常低效的.

  1. One would be incrementing a variable each time you reach the unit of time that you want to keep track of. But that would be extremely inefficient giving that the microcontroller would be doing a lot of constant context switching.

第二种方法是使用 32 位变量扩展计时器.然后在溢出时增加这样的变量.

The second way would be to extend the timer with a 32bit variable. Then incrementing such variable on an overflow.

MSB                           LSB
+--------------+ +--------------+
|  32bit uint  | |  32bit timer |
+--------------+ +--------------+

这种工作方式是,在定时器达到 0xffffffff(32 位无符号计数器的最大值)后,定时器将溢出并从 0 开始.如果在 32' 之后还有另一个位第 1 位,它将翻转(与递增相同).您可以做的是通过增加一个变量来模拟这种确切的行为.

The way this works is that after the timer reaches 0xffffffff which is the maximum for a 32bit unsigned counter, the timer will overflow and start back at 0. If there was another bit after that 32'th bit, it will flip on(which is the same as incrementing). What you can do is emulate this exact behavior by incrementing a variable.

首先,设置您的计时器.

First, set up your timer.

static TIM_HandleTypeDef s_TimerInstance = { 
    .Instance = TIM2
};

void setup_timer()
{
    __TIM2_CLK_ENABLE();
    s_TimerInstance.Init.Prescaler = ##; //Chose the correct value that fits your needs
    s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
    s_TimerInstance.Init.Period = 0xffffffff; //Chose the correct value that fits your needs
    s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //Also choose this value
    s_TimerInstance.Init.RepetitionCounter = 0;
    HAL_TIM_Base_Init(&s_TimerInstance);
    HAL_TIM_Base_Start(&s_TimerInstance);
}

你的处理程序,每次你的计时器到达 0xffffffff

Your handler, this has to be called each time your timer reaches 0xffffffff

extern void TIM2_IRQHandler();
void TIM2_IRQHandler()
{
    HAL_TIM_IRQHandler(&s_TimerInstance);
}

uint32_t extension;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    extension++; //Increment
}

组合扩展变量和定时器值.每次要获取扩展器计数器值时都使用此函数.您可以将其设置为内联以避免额外调用,也可以将其设置为宏.

Combine the extension variable and the timer value. Use this function each time you want to get the extender counter value. You can make it inline to avoid extra calls, or as a macro.

uint64_t get_time()
{
    return (extension << 32) & (__HAL_TIM_GET_COUNTER(&s_TimerInstance));
}

现在把所有东西粘在一起

Now glue everything together

int main(void)
{
    HAL_Init(); //Initialize HAL library
    InitializeTimer(); //Initialize timer
    
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);

    while(1);
}

注意,现在 tim2 将被使用,直到它溢出.不应更改,否则以下代码将不起作用.此外,设置分频器,使计时器每微秒递增一次,如您之前所述.

Note, that now tim2 will be used until it overflows. It should not be changed, or the following code will not work. Also, setup the divider, so the timer increment each microsecond as you stated earlier.

此外,您可以使用计时器来计算秒数,然后改为计算微秒.如果您计算秒数,则最多可以计算 2^32 秒,即 4294967296.一年大约有 31536000 秒.使用 32 位计数器 (4294967296/31536000),您最多可以计算 136.19252 年的正常运行时间.然后通过将正常运行时间除以 1000000 (uptime/1000000) 得到微秒.我不知道你打算用微控制器做什么,但对我来说数秒听起来更有意义.

Also, you can use the timer to count seconds and then calculate the microsecond instead. If you count seconds instead you can count up to 2^32 seconds which is 4294967296. A year has about 31536000 seconds. With a 32bit counter (4294967296/31536000) you can count up to 136.19252 years of uptime. Then get the microseconds by dividing the uptime with 1000000 (uptime/1000000). I don't know what are you planning to do with the microcontroller, but counting seconds sounds more sensical for me.

如果你真的想要精度,你仍然可以通过计算秒数来做到这一点,你可以将计时器计数器值添加到微秒计数中,你可以通过将秒数降低到微秒数来获得,这样你就可以抵消没有的微秒数t 已添加到第二个计数中.

If you really want precision, you can still do it by counting seconds, you can add the timer counter value to the microsecond count, which you can get by diving the seconds down into microseconds, that way you offset microseconds that haven't been added to the second count.

这篇关于从 32 位计时器获取 64 位时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆