你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

献给新新新手——SysTick定时器的一个简单应用

[复制链接]
挺子啊 发布时间:2017-6-5 21:10
本帖最后由 挺子啊 于 2017-6-5 21:56 编辑

========================
文章转载自知乎专栏 - stm32
========================


SysTick即为系统定时器,又称嘀嗒定时器,是Cortex-M3内核的一个外设,集成在NVIC中。SysTick是一个24bit的向下递减的计数器,每计数一次的时间为1/SYSCLK(SYSCLK一般为72MHz)。
操作系统需要执行多任务管理,用SysTick产生中断,确保单个任务不会锁定整个系统。同时SysTick还可用于闹钟定时、时间测量等。
由于Cortex-M3芯片都有SysTick,所以软件可以很容易地在Cortex-M3的产品间移植。
我们待会儿将利用SysTick产生1s的时基,让LED一秒钟闪烁一次,以完成SysTick的定时实验。
注:本文所用芯片为stm32f103。

SysTick寄存器
SysTick定时器由四个寄存器控制,如图7-1所示。
QQ截图20170605215247.png
图7-1
上图是对四个寄存器各个位的描述。其中最后一个校准值寄存器(STK_CALIB)在定时实验中并没有用到,这里暂且不介绍,有兴趣的读者可以自行查找其他资料阅读。

编程要点
  • 向SysTick重装载值寄存器(STK_LOAD)写入新的重装载值;
  • 配置中断优先级;
  • 写SysTick当前值寄存器(STK_VAL),将当前值清0;
  • 写SysTick控制及状态寄存器(STK_CTRL),启动SysTick。

SysTick属于内核外设,其相关的寄存器定义和库函数都在core_cm3.h中。如图7-2为core_cm3.h头文件里配置SysTick的源码截图。
QQ截图20170605212635.png
图7-2

SysTick_Config()库函数即是按照上述的编程要点完成SysTick配置的。我们在实际项目中时可以直接调用这个库函数来完成配置。而形参ticks用来设置STK_LOAD的值,最大不超过2^24。然后配置中断优先级,清空STK_VAL,最后配置STK_CTRL。其中,在配置中断优先级时调用了NVIC_SetPriority()库函数,传入的优先级实参为(1<<__NVIC_PRIO_BITS) - 1,其中宏__NVIC_PRIO_BITS为4,则可得其优先级为15,则可以看出其默认设置的优先级在内核外设中是最低的。

那么如果我们同时设置了内核外设和片上外设的优先级,该如何判断孰高孰低呢?
专栏(stm32):stm32中断初识与实践(上)里说过,在配置外设中断优先级时,需要先分组,再设置抢占优先级及子优先级,那么我们把内核外设的优先级也用同一配置方式分解为这三个部分。

假设配置一个外设的中断优先级分组为3,抢占优先级为2,子优先级为1,而SysTick优先级为4。则将SysTick优先级4转换为二进制,为0100(0b),在分组为3时,SysTick抢占优先级为010(0b),即为2,子优先级为0。我们先比较抢占优先级,发现相同,那么比较子优先级,此时SysTick子优先级为0,而我们假设的外部中断子优先级为1,所以SysTick优先级大于假设的外设优先级(数值越小,优先级越高)。

中断时间计算
SysTick的计数器执行的是倒计时,我们要计算中断计数时间,需要知道计数总量(STK_LOAD的值)、时钟源频率等两个参数。打个比方,这相当于我们要计算运动时间,需要知道距离和速度,那么STK_LOAD的值即为距离,时钟源频率即为速度。则中断计数时间为(假设STK_LOAD的值为VALUE,时钟源频率为CLK,中断计数时间为T):
T = VALUE / CLK(其中,CLK为72MHz)

当STK_LOAD的值VALUE减到0时,即可产生中断。如果设置VALUE=72000,那么中断一次的时间T = 72000 / 72MHz = 1ms。

定时时间计算
得出中断一次的时间后,我们可以设置一个变量n,用来记录中断次数,那么最终的定时时间即为T*n。
回到开头的实验说明中,我们需要产生1s时基,来实现LED灯1s闪烁一次,则n为1000时满足要求。

QQ截图20170605212538.png
图7-3

由于SysTick不会自动停止,所以我们需要在异常/中断处理中将其停止,即失能SysTick。
到这里为止,一个简单的SysTick定时实验完成了,之后只要在main函数中调用SysTick_Delay_ms(1000)函数,即可实现1s的精确SysTick定时,而不是使用普通的不精确延时函数。

专栏(stm32):stm32的“Hello World”——LED流水灯使用的则是普通延时函数实现流水灯效果。

--------------------------------------------------------------------
文章首发于知乎专栏 - stm32,转载请私信,并注明原文出处。










收藏 2 评论2 发布时间:2017-6-5 21:10

举报

2个回答
Inc_brza 回答时间:2017-6-26 14:44:30
其实这是一个比较浪费资源的方法。不太建议使用!
systick能引起中断,可以通过在中断中使用变量自增的方法来达到延时,而延时函数只需要判断当前的
systickcount和刚进入延时获得的count做对比就能达到延时作用
valetang-126879 回答时间:2017-6-26 16:57:04
帮顶一下

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版