打印
[应用相关]

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

[复制链接]
1076|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ST, TI, ck, ic
本帖最后由 铁血丹心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分钟左右就死机了,当时也不明白为啥。。。现在也不明白,后来发现中断那里写少了东西,加上之后就好了。



85388621c871a18d2a.png (8.68 KB )

85388621c871a18d2a.png

使用特权

评论回复
沙发
pixhw| | 2022-3-4 20:33 | 只看该作者
这个可以替代的。  

使用特权

评论回复
板凳
ghuca| | 2022-3-4 20:41 | 只看该作者
Systick有什么用呢

使用特权

评论回复
地板
beacherblack| | 2022-3-4 20:58 | 只看该作者
还是习惯Systick作为时基  

使用特权

评论回复
5
10299823| | 2022-3-5 22:55 | 只看该作者
很多芯片没有TIM6的

使用特权

评论回复
6
pixhw| | 2022-3-5 23:38 | 只看该作者
为什么要替换其他定时器呢

使用特权

评论回复
7
ghuca| | 2022-4-1 14:05 | 只看该作者
SysTick是默认的HAL基础时钟源

使用特权

评论回复
8
sdCAD| | 2022-4-1 14:13 | 只看该作者
将Systick的时钟源设置为HCLK,一般的,也就是系统时钟

使用特权

评论回复
9
wtywtykk| | 2022-4-1 14:49 | 只看该作者
用freertos的时候应该可以直接用rtos的tick代替hal的tick吧

使用特权

评论回复
10
i1mcu| | 2022-4-1 15:45 | 只看该作者
STM32中最多的是一共有10个定时器

使用特权

评论回复
11
mmbs| | 2022-4-11 16:20 | 只看该作者
可以选择基础定时器TIM6作为HAL的基础时钟源

使用特权

评论回复
12
benjaminka| | 2022-4-11 18:27 | 只看该作者
Cube默认设置Systick中断优先级为最高优先级

使用特权

评论回复
13
lzmm| | 2022-4-11 19:32 | 只看该作者
  HAL库实现微秒级别延时

使用特权

评论回复
14
wengh2016| | 2022-4-11 20:58 | 只看该作者
使用定时器实现 SysTick 时:要实现HAL_TIM_PeriodElapsedCallback 。

使用特权

评论回复
15
soodesyt| | 2022-4-11 22:02 | 只看该作者
STM32CubeMX默认选择的是Systick

使用特权

评论回复
16
pentruman| | 2022-4-25 16:39 | 只看该作者
Systick会被操作系统设置为最低优先级中断

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

473

帖子

1

粉丝