HAL_GetTick()函数用法
时间: 2023-09-10 08:09:07 浏览: 1183
HAL_GetTick()函数是STM32 HAL库中提供的一个函数,用于获取当前系统的运行时间,单位为毫秒。
该函数的用法如下:
```c
uint32_t HAL_GetTick(void);
```
该函数返回一个32位的无符号整数,表示从系统启动开始到当前时刻经过的毫秒数。因此,可以通过调用该函数来实现延时、定时等功能。
需要注意的是,该函数的实现依赖于一个系统滴答定时器(SysTick),因此在使用该函数之前,需要确保该定时器已经被正确地初始化和启动。
此外,HAL_GetTick()函数返回的时间数值是一个循环计数器,当计数器溢出时会从零重新开始计数。因此,在计算时间间隔时,需要考虑到计数器溢出的情况。
相关问题
代码在运行时,在while((HAL_GetTick() - tickstart) < wait)卡住,但是当我将代码中的 HAL_Delay(1000); // 延迟1秒注释掉的时候,代码就不卡了,请问这是为何呢?
### 回答1:
这可能是由于HAL_Delay(1000)阻塞了STM32的系统时钟,在while循环中等待时间过程中系统时钟停止工作,无法计时,造成卡住的现象。去掉延时函数后,系统时钟可以持续运转,计时器也可以正常工作,因此代码不会卡住。建议使用其他方法进行延时,例如使用定时器或者外部中断等方式。
### 回答2:
代码在运行时,在while((HAL_GetTick() - tickstart) < wait)卡住的原因是由于HAL_Delay函数在延迟1秒时,会使程序暂停运行1秒钟,此时HAL_GetTick()函数记录的时间不会更新。而在while循环中,一直判断(HAL_GetTick() - tickstart) < wait,如果HAL_GetTick()的值不变,那么循环条件始终成立,导致程序一直卡在这个循环中。
当将HAL_Delay(1000); // 延迟1秒注释掉后,代码不再卡住的原因是没有延迟,程序可以正常运行,执行完while循环中的语句后,程序继续执行下一行代码,而不会进入到延迟函数内部,因此程序不再卡住。
解决这个问题的办法是可以在循环中添加一些延迟,以便HAL_GetTick()的值可以及时更新。例如在循环内添加一个短暂的延迟,比如HAL_Delay(1);,使得程序每次循环都会有一小段时间的休眠,从而让HAL_GetTick()有机会更新时间。这样可以保证程序不会一直卡在while循环中。
另外,可以考虑使用HAL_Delay函数的替代方法,比如使用HAL_Delay的底层实现函数,或者使用其他的延迟函数来代替。这样可以避免在延迟函数中导致HAL_GetTick()的时间不更新的问题。
### 回答3:
在这种情况下,代码在while((HAL_GetTick() - tickstart) < wait)陷入无限循环。HAL_GetTick()函数返回系统启动后的毫秒数,tickstart是一个变量,表示代码开始运行时的时间,wait是一个变量,表示期望的延迟时间。
当执行到while((HAL_GetTick() - tickstart) < wait)时,代码会不断地比较系统当前时间与代码开始时间的差值,直到这个差值大于等于wait时,才会跳出循环。
在这个问题中,当将代码中的HAL_Delay(1000); // 延迟1秒注释掉后,while循环中没有延迟操作,导致循环非常快速地执行。在一秒内,很可能无法满足差值大于等于wait的条件,因此代码会一直处于循环状态,没有机会跳出循环。
而当加上延迟操作时,每次循环执行时会延迟1秒钟,这样while循环中的差值会随着时间的流逝逐渐增大,最终达到大于等于wait的条件,才会跳出循环,使代码继续执行。
因此,从逻辑上来说,将代码中的延迟操作注释掉会导致while循环一直无法满足跳出条件,从而使代码卡住。
void ShowMessageLBJ(POCSAG_RESULT* POCSAG_Msg) { char LBJ_Info[3][7] = {{0},{0},{0}};、 for(uint8_t i = 0;i < 3;i++) { strncpy(LBJ_Info[i],POCSAG_Msg->txtMsg+i5,5); OLED_ShowString(68,0,LBJ_Info[0],16); OLED_ShowString(7*8,4,LBJ_Info[2],16); } 这个是STM32F103C8T6和ssd1306的显示函数,现在是收到消息直接显示,不会息屏,能不能帮我把它修改为收到消息后常亮6秒,如果有新消息就替换显示,不用HAL_GetTick
可以使用定时器来实现消息显示和替换的功能。具体做法是,在接收到新消息时,启动一个定时器,定时器到达后关闭屏幕,然后在新消息到达时重新启动定时器,以此循环。
下面是修改后的代码示例:
```
#define DISPLAY_TIME 6000 // 显示时间,单位为毫秒
TIM_HandleTypeDef htim3; // 定时器句柄
void StartDisplayTimer(uint16_t time)
{
HAL_TIM_Base_Start_IT(&htim3);
__HAL_TIM_SET_AUTORELOAD(&htim3, time);
}
void StopDisplayTimer()
{
HAL_TIM_Base_Stop_IT(&htim3);
OLED_Clear();
}
void ShowMessageLBJ(char* msg)
{
OLED_Clear();
OLED_ShowString(68, 0, msg, 16);
StartDisplayTimer(DISPLAY_TIME);
}
void ReceiveMessageLBJ(POCSAG_RESULT* POCSAG_Msg)
{
static char last_msg[16] = {0}; // 上次显示的消息
char LBJ_Info[3][7] = {{0},{0},{0}};
for (uint8_t i = 0; i < 3; i++)
{
strncpy(LBJ_Info[i], POCSAG_Msg->txtMsg + i * 5, 5);
}
char msg[16];
snprintf(msg, 16, "%s %s", LBJ_Info[0], LBJ_Info[2]);
if (strcmp(msg, last_msg) != 0)
{
strncpy(last_msg, msg, 15);
ShowMessageLBJ(msg);
}
else
{
StartDisplayTimer(DISPLAY_TIME);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM3)
{
StopDisplayTimer();
}
}
```
这里使用了定时器来实现屏幕显示和关闭。在接收到新消息时,判断是否和上一次显示的消息相同,如果不同则调用`ShowMessageLBJ`函数显示新消息,否则重新启动定时器。在定时器到达时,调用`StopDisplayTimer`函数关闭屏幕。定时器的实现可以参考STM32 HAL库的定时器使用方法。
阅读全文