HAL库与Cubemx系列|Systick-系统滴答定时器详解

Systick是什么?

关于Systick,在Context-M3权威指南中如此描述:

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号: 15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。

SysTick定时器能产生中断, CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的移植变得简单多了,因为在所有CM3产品间对其处理都是相同的。

SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从 RELOAD 寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除, 就永不停息,图 13.1 中小结了 SysTick的相关寄存器。


这是定义在core_cm3.h中的结构体:

SysTick 的最大使命,就是定期地产生异常请求,作为系统的时基。 OS 都需要这种“滴答” 来推动任务和时间的管理。 如欲使能 SysTick 异常, 则把 STCSR.TICKINT 置位。 另外, 如果向量表被重定位到 SRAM 中,还需要为 SysTick 异常建立向量,提供其服务例程的入口地址。

Systick如何使用?

前面说了那么多,Systick到底是什么,小伙伴们是不是已经明白了呢?其实,简单一句话,就是“心跳”,CPU以心跳为依据分配要做的事情,嘀哒...嘀哒...嘀哒...

cubemx配置Systick

来来来,实践是检验真理的唯一标准,没有实践的理论就是耍流氓~~

Systick是系统的“心跳”,为系统提供着时基来源,cubemx中是已经为我们勾选了的,默认的时基是来源于Systick


当然了,条条大路通罗马,Systick可以作为时基,但却不是唯一的,不信你看,实际上有这么多的定时器都可以用来作为时基来源的,移植过操作系统的小伙伴一定不陌生,本次,我们只介绍关于Systick的功能~

  • 时钟配置

关于时钟配置的详细讲解,请参看:CubeMX的正确打开方式 一文

  • 串口配置

关于串口配置的详细解释,请参看:CubeMX的正确打开方式 一文

  • Systick中断

可以看到,Systick的中断是默认已经开启了的,直接使用即可

Systick代码详细解析

结合生成的工程,来看看Systick的时钟配置以及工作流程,systick首先在HAL_Init()函数中被提到,被cue来干嘛呢,接下来跟进去看看


从英文解释中(别说看不懂哈),Systick被配置为系统时基,并且被配置为了1ms,做技术,要有刨根问底的精神,奥利给,继续跟进去看看


这段英文解释很重要,外设中断进程调用HAL_Delay的时候,要特别注意中断的优先级问题,如果systick的中断优先级低于外设中断优先级,会导致一直在外设中断中阻塞,如果外设中调用了HAL_Delay(),一定要保证Systick的中断优先级高于外设中断优先级,但是,小飞哥是极其不建议在中断中调用HAL_Delay()函数的


明明是在说Systick的事情,怎么牵扯到HAL_Delay()函数了呢,那就再来看看,HAL_Delay()是如何实现的呢?打开HAL_Delay(),可以看到,实际上是通过uWTick这个全局变量不断增加,比较来实现的延时,那么uWTick是在哪里增加的呢?


好家伙,转了十万八千里,最终还是在Systick中断中进行增加的,默认配置的是Systick 1ms中断,这下知道了我们调用的HAL_Delay(),为什么是1ms了吧,绕了那么一大圈,是不是有点想打人呢~

默认配置的是1ms中断周期,那我们HAL_Delay()的最小单位是1ms,如果想获得1us的中断周期,该如何调整呢?且往下看,这是我们自定义的systick周期配置函数,一步一步来看

先来看systick的时钟来源,时钟来源为HCLK或者是HCLK的8分频,小飞哥实验选择的是HCLK,72MHZ,确定了systick的时钟源,接下来配置systick的中断周期

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

再来看这个函数,分析之前,我们先来看看systick的中断周期时间是怎么计算的,T=ReloadValue10001/72000000ms

这是默认的配置1ms,主频是72MHZ,uwTickFreq默认是1KHZ,根据上面的分析计算,算下来T = (72MHZ/1000)1/72MHZ=1000/72MHZ(1/72MHZ)=1/1000s=1ms,你看懂了吗?

HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)

根据上面的分析,我们想要1us、10ms、100ms....的中断周期怎么办,那就根据上面的计算公式算吧,那这么修改后,HAL_Delay不就可以实现us延时了嘛,实现当然是能实现,但中断是不是过于频繁了呢,1us一个中断诶,那怎么实现呢,请查看,关于HAL库us延时的3种实现方式

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); //1ms

到此,关于systick的工作流程就算是介绍差不多了,还有最后一步,Systick中断回调函数需要添加到中断回调句柄中


可以看到systick中断回调函数依然是_weak修饰符,意思就是我们自己一个一样名字的函数,不会报错

我们自己重新定义回调函数,处理中断事务,好的编程习惯,中断置标志,所有的逻辑处理放在中断外处理,建议这样做

while中不断查询标志

测试结果

间隔100ms,打印systick test,测试OK,over

关于Embeded-party

欢迎加入群聊Embeded-party,这里有一群可爱的人儿,很多有意思的设计,等着你的加入哦

资料获取

公众号后台回复,systick,即可获得源码哦~

  • 31
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
好的,针对您的问题,可以按照以下步骤开启STM32F401的系统滴答定时器中断: 1. 首先,需要开启系统滴答定时器TIM6,使用HAL库函数进行初始化: ```c // 定义TIM_HandleTypeDef类型的结构体变量 TIM_HandleTypeDef htim6; // 初始化TIM6 void TIM6_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim6.Instance = TIM6; htim6.Init.Prescaler = 8399; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 999; htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } } ``` 其中,TIM6_Init()函数是自定义的初始化函数,使用了宏定义的方式配置了预分频器,计数模式和自动重载,最终调用HAL_TIM_Base_Init()函数进行初始化。 2. 开启TIM6的中断,并编写中断服务函数,使用HAL库函数进行配置: ```c // TIM6中断服务函数 void TIM6_DAC_IRQHandler(void) { HAL_TIM_IRQHandler(&htim6); } // 配置TIM6中断 void TIM6_ConfigInterrupt(void) { HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); HAL_TIM_Base_Start_IT(&htim6); } ``` 其中,TIM6_DAC_IRQHandler()是TIM6的中断服务函数,使用了HAL_TIM_IRQHandler()函数进行中断处理;TIM6_ConfigInterrupt()函数是配置TIM6中断的函数,使用了HAL_NVIC_SetPriority()函数设置中断优先级,使用了HAL_NVIC_EnableIRQ()函数开启中断,最终调用HAL_TIM_Base_Start_IT()函数开启TIM6的中断。 以上就是开启STM32F401的系统滴答定时器中断的步骤,希望能对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小飞哥玩嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值