我是使用HAL功能的新手。函数HAL_GetTick()
的{{3}}表示它在毫秒"中提供 tick 值。
我不明白这个函数是返回tick还是毫秒。当然要从刻度转换为毫秒,我需要知道一毫秒内有多少刻度,以及它的CPU特定。
那么HAL_GetTick()
究竟返回了什么?
修改
我真正的问题是知道如何以微秒为单位测量时间。所以我想从HAL_GetTick()
得到滴答并将它们转换为微秒。这在评论和至少其中一个答案中得到了解决,所以我也在这里提到这一点并编辑了标题。
答案 0 :(得分:12)
HAL_GetTick()
应该返回自启动以来经过的毫秒数,因为很多HAL函数都依赖于它。你如何实现它取决于你。默认情况下,HAL_Init()
查询系统时钟速度,并将SysTick频率设置为1/1000:
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/*Configure the SysTick to have interrupt in 1ms time basis*/
HAL_SYSTICK_Config(SystemCoreClock /1000);
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);
/* Return function status */
return HAL_OK;
}
然后默认的SysTick中断处理程序调用{{1}}每ms增加一次内部计数器,HAL_IncTick()
返回该计数器的值。
所有这些函数都定义为HAL_GetTick()
,因此您可以覆盖它们,只要您的weak
版本以毫秒为单位返回已用时间,就可以了。你可以,例如替换HAL_GetTick()
让SysTick以10 kHz运行,但是你应确保仅在每第10次中断时调用HAL_InitTick()
。在216 MHz STM32F7控制器(或刚刚发布的400MHz STM32H743)上,您实际上可以降至1 MHz Systick,但是您应该非常小心地从处理程序中尽快返回。除非你在处理程序中做一些硬件计数器无法做到的事情,否则它仍会浪费宝贵的处理器周期。
或者您可以在不配置SysTick的情况下执行此操作(使用空函数覆盖HAL_IncTick()
),但设置一个32位硬件计时器,并使用足够的预分频器来计算每微秒,并让{{1返回计时器计数器。
回到你真正的问题,测量微秒级的时间,有更好的方法。
如果你有一个32位定时器,那么你可以将相应APB时钟的MHz值放入预分频器,启动它,并且有你的微秒钟,而不是从你的应用程序中取走处理时间。此代码应在 STM32L151 / 152/162 STM32F4上启用(未测试):
HAL_InitTick()
然后通过阅读HAL_GetTick()
随时获取其价值。
检查您的参考手册哪些硬件定时器具有32位计数器,以及它从何处获取时钟。它在整个STM32系列中变化很大,但应该在F4上。
如果你不能使用32位定时器,那么就有核心周期计数器。只需使用
启用一次__HAL_RCC_TIM5_CLK_ENABLE();
TIM5->PSC = HAL_RCC_GetPCLK1Freq()/1000000 - 1;
TIM5->CR1 = TIM_CR1_EN;
然后从TIM5->CNT
读取值。请注意,当它返回经过的处理器周期时,它将在几秒钟内溢出。
<击>编辑:击>
<击> 我刚才注意到你正在使用STM32L0。因此,忘记32位定时器和200+ MHz内核。使用。CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
,或仔细考虑您想测量的间隔时间,以及准确度,然后选择16位计时器。您可以将其作为单独的问题发布,更详细地描述您的硬件的外观以及它应该做什么。可能有一种方法可以直接通过您想要计时的事件触发计数器启动/停止。
答案 1 :(得分:2)
两者兼而有之。大多数情况下,使HAL滴答计数器递增的函数挂钩到SysTick中断,该中断被配置为每1ms滴答一次。因此,HAL_GetTick()
将返回自配置SysTick中断以来的毫秒数(基本上自程序启动以来)。这也可以是&#34; SysTick中断的次数&#39;勾选&#39;&#34;。
答案 2 :(得分:1)
尽管已经回答了该问题,但我认为了解HAL如何使用HAL_GetTick()
来计数毫秒会有所帮助。可以在HAL的函数HAL_Delay(uint32_t Delay)
中看到。
HAL_Delay(uint32_t Delay)
中stm32l0xx_hal.c
的实现:
/**
* @brief This function provides minimum delay (in milliseconds) based
* on variable incremented.
* @note In the default implementation , SysTick timer is the source of time base.
* It is used to generate interrupts at regular time intervals where uwTick
* is incremented.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @param Delay specifies the delay time length, in milliseconds.
* @retval None
*/
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a period to guaranty minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait++;
}
while((HAL_GetTick() - tickstart) < wait)
{
}
}
答案 3 :(得分:1)
查看调试器时,我可以看到private static readonly int FIFO_SIZE = 244;
...
if (txSize >= FIFO_SIZE)
{
/* Copy chunk of data to send */
Array.ConstrainedCopy(data, i * FIFO_SIZE, bytesToSend, 0, FIFO_SIZE);
i++;
/* Convert to IBuffer type */
dataToSend = CryptographicBuffer.CreateFromByteArray(bytesToSend);
/* Write FIFO characteristic (244 bytes) >> observed physically 10 writes 0f 24 bytes + 1 write of 4 bytes */
status = await fifo.WriteValueAsync(dataToSend, GattWriteOption.WriteWithoutResponse);
if (status != GattCommunicationStatus.Success)
{
System.Diagnostics.Debug.WriteLine("FIFO write error !");
}
txSize -= FIFO_SIZE;
}
...
全局变量可用,这似乎与针对我自己定义的全局变量调用uwTick
的结果相同。
根据文档:
无效HAL_IncTick(无效)
调用此函数可增加使用的全局变量“ uwTick” 作为申请的时基。
注意:
在默认实现中,此变量每1ms递增一次 在Systick ISR中。
该函数声明为__weak 如果用户文件中有其他实现,则将其覆盖。
答案 4 :(得分:1)
我遇到了同样的问题,但是随后在PlatformIO中找到了一个库函数,该函数返回了微秒。
s = temp.assign(listofitemids=temp['listofitemids'].str.split(', ')).explode('listofitemids')
s = pd.crosstab(s['userid'], s['listofitemids']).mask(lambda x : x.eq(0))
s
Out[266]:
listofitemids 10 20 30 40
userid
100 1.0 1 1 NaN
200 NaN 1 1 1.0
它位于〜/ .platformio / packages / framework-arduinoststm32 / libraries / SrcWrapper / src / stm32 / clock.c
但是看起来STM32CubeIde没有它,所以我只是从PlatformIO复制了它。另外我还必须复制LL_SYSTICK_IsActiveCounterFlag()函数:
uint32_t getCurrentMicros(void)
{
/* Ensure COUNTFLAG is reset by reading SysTick control and status register */
LL_SYSTICK_IsActiveCounterFlag();
uint32_t m = HAL_GetTick();
const uint32_t tms = SysTick->LOAD + 1;
__IO uint32_t u = tms - SysTick->VAL;
if (LL_SYSTICK_IsActiveCounterFlag()) {
m = HAL_GetTick();
u = tms - SysTick->VAL;
}
return (m * 1000 + (u * 1000) / tms);
}
答案 5 :(得分:-2)
/* Initialization */
__HAL_RCC_TIM5_CLK_ENABLE();
TIM5->PSC = HAL_RCC_GetPCLK1Freq() / 500000;
TIM5->CR1 = TIM_CR1_CEN;
TIM5->CNT = -10;
/* Reading the time */
uint32_t microseconds = TIM5->CNT << 1;
我没有完全探讨为什么我必须做我做的事情。但是我很快意识到了两件事。 (1)尽管看起来不错,但标量缩放无法工作。这是我尝试使其工作的几件事之一(基本上是半个时钟,然后将结果除以2)。 (2)时钟已经在运行,起初给出了奇怪的结果。我尝试了一些不成功的事情来停止,重新编程并重新启动它,并将计数设置为-10是一种粗略但有效的方法,只需使其完成当前循环,然后即可根据需要迅速开始工作。当然,有更好的方法可以实现这一目标。但总的来说,这是一种获得开销非常低的准确事件时间戳的简单方法。