铁血丹心LLLL 发表于 2022-2-28 16:24

STM32 HAL使用TIM6代替Systick作为时基

本帖最后由 铁血丹心LLLL 于 2022-2-28 16:28 编辑

在使用STM32CubeMX生成对应的STM32工程时,很多时候在配置SYS的时候,会直接忽略掉时基源的选择,而STM32CubeMX默认选择的是Systick,作为HAL库的时基,用于一些超时操作,像I2C\USART等,都会用到。



而在实际的应用中,如果不跑裸机,就会用到Systick,作为RTOS的时基。许多人使用HAL库的时候,都会很习惯使用HAL_Delay作为毫秒级的延时(当然也可以作为us级别的,需要去改)。但上了RTOS,由于systick被HAL占用了,如果在Systick的中断中,继续添加RTOS的计数,不是不行,在使用STM32CubeMX 加上FreeRTOS的时候,就会有这样的提示:


其实你可以忽略掉这个,直接生成,得到的FreeRTOS的工程也是能用的,但是如果使用DWT作为时间戳进行时间测量(时间足够长),你会发现对比出来有时间差。并且官方也是极力不推荐的。

当然,面对这种尴尬的情况,也是有解决方案的

1 、在杰杰的博客中有提到,使用Cortex-M内核中的一个调试追踪器----DWT,DWT有计数器寄存器,可以代替SYSTICK进行足够时间的计数。具体可看他的博客:https://blog.csdn.net/jiejiemcu/article/details/83932913

2、使用一个TIM来代替systick进行延时。具体在使用STM32CubeMX生成的时候,将Systick换

成一个自己不常用的基本定时器:
配置出来的工程中,会出现一个文件,


这里就已经将你的TIM6(或者别的,自己选择的)初始化并配置好了,基本上不需要自己配置,当然也可以自己配置初始化,将原本放在Systick中断中的
HAL_IncTick()
这个函数,放在TIM6的中断服务函数中,也是可以的。
而也可以学官方的来改,
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef    clkconfig;
uint32_t            uwTimclock = 0;
uint32_t            uwPrescalerValue = 0;
uint32_t            pFLatency;

/*Configure the TIM6 IRQ priority */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0);

/* Enable the TIM6 global Interrupt */
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);

/* Enable TIM6 clock */
__HAL_RCC_TIM6_CLK_ENABLE();

/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

/* Compute TIM6 clock */
uwTimclock = 2*HAL_RCC_GetPCLK1Freq();

/* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);

/* Initialize TIM6 */
htim6.Instance = TIM6;

/* Initialize TIMx peripheral as follow:
+ Period = [(TIM6CLK/1000) - 1]. to have a (1/1000) s time base.
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
htim6.Init.Period = (1000000 / 1000) - 1;
htim6.Init.Prescaler = uwPrescalerValue;
htim6.Init.ClockDivision = 0;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim6) == HAL_OK)
{
    /* Start the TIM time Base generation in interrupt mode */
    return HAL_TIM_Base_Start_IT(&htim6);
}

/* Return function status */
return HAL_ERROR;
}

改好之后,在上RTOS的时候,记得在TIM6中断中,加入临界段保护(或进入中断保护),否则会出现意想不到的结果,反正我第一次这样做的时候,运行了5分钟左右就死机了,当时也不明白为啥。。。现在也不明白,后来发现中断那里写少了东西,加上之后就好了。



pixhw 发表于 2022-3-4 20:33

这个可以替代的。

ghuca 发表于 2022-3-4 20:41

Systick有什么用呢

beacherblack 发表于 2022-3-4 20:58

还是习惯Systick作为时基

10299823 发表于 2022-3-5 22:55

很多芯片没有TIM6的

pixhw 发表于 2022-3-5 23:38

为什么要替换其他定时器呢

ghuca 发表于 2022-4-1 14:05

SysTick是默认的HAL基础时钟源

sdCAD 发表于 2022-4-1 14:13

将Systick的时钟源设置为HCLK,一般的,也就是系统时钟

wtywtykk 发表于 2022-4-1 14:49

用freertos的时候应该可以直接用rtos的tick代替hal的tick吧

i1mcu 发表于 2022-4-1 15:45

STM32中最多的是一共有10个定时器

mmbs 发表于 2022-4-11 16:20

可以选择基础定时器TIM6作为HAL的基础时钟源

benjaminka 发表于 2022-4-11 18:27

Cube默认设置Systick中断优先级为最高优先级

lzmm 发表于 2022-4-11 19:32

HAL库实现微秒级别延时

wengh2016 发表于 2022-4-11 20:58

使用定时器实现 SysTick 时:要实现HAL_TIM_PeriodElapsedCallback 。

soodesyt 发表于 2022-4-11 22:02

STM32CubeMX默认选择的是Systick

pentruman 发表于 2022-4-25 16:39

Systick会被操作系统设置为最低优先级中断
页: [1]
查看完整版本: STM32 HAL使用TIM6代替Systick作为时基