时基
2025/8/22大约 2 分钟
时基
时基就是延时函数实现的计数器
正点原子的中断函数里面让uwtick和rtos的计数值都增加
//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler(); //RTOS计数值++
}
HAL_IncTick();//uwTick++;
}//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为AHB时钟
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
u32 reload;
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK
fac_us=SYSCLK; //不论是否使用OS,fac_us都需要使用
reload=SYSCLK; //每秒钟的计数次数 单位为K
reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
//reload为24位寄存器,最大值:16777216,在180M下,约合0.745s左右
fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
SysTick->LOAD=reload; //每1/configTICK_RATE_HZ断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}HAL和RTOS的延时本质上是定时器产生固定周期的中断,在中断里面对两个Tick计数,根据Tick延时
正点原子的延时函数是根据systick的硬件计数值实现的
在启用了RTOS的情况下,在正点原子的延时函数初始化里会根据定义的configTICK_RATE_HZ(滴答中断的频率)来设置SYSTICk定时器。
默认情况下是1ms SYSTICK发生一次中断,在中断里面uwtick和RTOS计数值加1,rtos里面的延时是基于RTOS计数值的,不是uwTick。
HAL库的延时是基于uwTick的。所以,如果初始化SYSTICK的中断不为1ms,那么uwTick的增加就不是1ms一次,HAL_Delay(1)也不是1ms;
RTOS计数值加就不是1ms一次,rtos里面的延时函数也不会是1ms
总结:
在移植时会把SYSTICK的频率改为RTOS要的,不改变HAL时基的话(改变时基在TIM定时器中断里增加uwtick),HAL的延时时间会和RTOS一样
如果RTOS里面规定10ms一次中断,HAL_Delay(1)一次10ms,所以要改变HAL的时基,防止HAL错乱,比如 HAL_Delay(1) 实际就是 10ms,会影响 HAL 驱动(USB、UART DMA 超时之类的,驱动函数里面调用HAL_Delay())。这种情况 必须把 HAL 的时基迁到 TIM。

