历史上的今天
今天是:2025年07月17日(星期四)
2018年07月17日 | STM32学习笔记3——Systick
2018-07-17 来源:eefocus
对于STM32中,有一个经常用到,却在数据手册上很少资料的工具,那就是Systick,这个工具是所有cortex-M0内核的单片机所共有的,他是一个系统定时器,其存在的主要目的是为嵌入式操作系统提供100Hz(即10ms)的定时节拍。当然,也可以做为其它的普通定时等其他用途。下面,我们就开始理解这个定时器。
寄存器
系统定时器包括四个寄存器,SYST_CSR、SYST_RVR、SYST_CVR、SYST_CALIB。定义如下所示:
对于这几个寄存器我们可以翻译一下:
SYST_CSR寄存器,系统定时器控制和状态寄存器
SYST_RVR寄存器,系统定时器重载值寄存器
SYST_CVR寄存器,系统定时器当前值寄存器
SYST_CALIB寄存器,系统定时器校准寄存器
这样就很明了了,对于这几个寄存器我们一个个的看。
首先是SYST_CSR寄存器:
CSR寄存器用到的位有4个,bit0用于是否开启定时器,bit1用于是否产生中断,bit2用于选择定时器的时钟源是等于主时钟还是等于主时钟的一半,bit16是定时器的状态。
SYST_RVR寄存器
RELOAD 值可以是 0x00000001-0x00FFFFFF 范围内的任何值。您可以将 RELOAD 的值设为 0,这不会产生任何影响,因为计数值从 1变为 0时 SysTick 异常请求和 COUNTFLAG都被激活了。如果要产生一个周期为 N个处理器时钟周期的多次触发定时器,就可以将 RELOAD 值设为 N-1。例如,如果要求每隔 100个时钟脉冲就触发一次 SysTick 中断,RELOAD 就被设为 99。
SYST_CVR寄存器
CVR寄存器用到bit0~23,即24位数,这是一个状态寄存器,当定时器开始运作,这个值在不断地变化,从RVR寄存器获取初值以后,倒计时到0.
SYST_CALIB寄存器
校准寄存器SYST_CALIB不用我们考虑,出厂前就配置好了。
函数
系统自带的Systick函数,由CMSIS(关于什么是CMSIS,去百度搜吧)提供,位于core_cm0.h文件,在其中第656行有如下函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
由函数内部的语句“SysTick->LOAD = ticks – 1;”知道,ticks就是LOAD值,即重载值,表示两次中断的计数。
例如,要产生10ms的中断,可以在程序中如下调用函数:Systick_Config(SystemCoreClock/100);函数参数中的SystemCoreClock是当前主频的值,假如现在的主频是48MHz,SystemCoreClock就是48 000 000 ,48 000 000 /100=480 000。我们把参数带进去以后,LOAD=479 999,也就是说,定时器开始运行后,定时器的值会从479 999递减到0,进入中断函数,然后再次从479 999 递减到0,如此循环。至于为什么从479 999递减到0就是10ms?知道每递减一个值需要多长时间,那么递减480 000下,需要多长时间,就知道了。要知道每递减一个值需要多长时间,就需要知道当前定时器运行的时钟是多少。由寄存器CSR知道,定时器的时钟有两种,一种是等于主频,一种是等于主频的二分之一,由CSR寄存器中的bit2决定。
函数中,对控制寄存器的bit0 bit1 bit2都置1,对照前面的寄存器定义可知,时钟设置为等于主频,打开系统定时器中断,允许定时器运行。
我们知道了时钟,就知道定时器每递减一个值需要的时间了,即:1/SystemCoreClock 秒,换算成毫秒即:(1/SystemCoreClock)*1000=1000/SystemCoreClock毫秒,即每递减一个值,耗时1000/SystemCoreClock毫秒。所以如果要使得10ms定时,即10/(1000/SystemCoreClock)=SystemCoreClock/100,所以,我们的设置是正确的。以此类推,需要定时多长时间,你可以自己算一个参数带进去了,需要注意的是,LOAD值是个24位数,带进去的数不要超过24位数的最大值。还有一个需要注意的地方,就是LOAD值最小255,当你给LOAD值带进去小于255值,LOAD会自动变成255。由于定时器SYST_RVR寄存器为24位的,所以最大值为十六进制FFFFFF,化为十进制为16777215,所以最多能储存数据为16777215+1=16777216;
定时器延时
利用CMSIS中的函数我们可以写如下的函数:
__IO uint32_t msTick;
void SysTick_Handler(void) // 中断函数
{
msTick++;
}
void delay_ms(IO uint32_t ms)
{
uint32_t endTime=msTicks+ms;
SysTick_Config((SystemCoreClock/1000)*ms);
while(msTicks } 进行1ms的精确延时。此外还可以修改SystemCoreClock/1000进行不同时间的延时。
史海拾趣
|
WinCE6.0中Catalog Item没有CISCO Aironet 340/350 PCMCIA WLAN Card网卡驱动选项 我要加一个CISCO Aironet 350 PCMCIA 无线网卡,查看Windows Embedded CE6.0帮助文件,有CISCO Aironet 340/350 PCMCIA WLAN Card驱动可以用,位于Device Drivers\\Networking\\下。可是我的Wince6.0却找不到这个驱动,不知道怎么回事?… 查看全部问答> |
|
wince5.0 我的板子不用ADSL线,用公司网络上网正常,说明网卡及驱动没有问题! 我用ADSL线直接接我的PC,通过输入用户名及密码,正常登录,并正常浏览网页,说明ADSL线及账户没有问题! 我的问题是: ADSL线接上我的板子,创建PPPOE后,只要一 ...… 查看全部问答> |
|
【LaunchPad手记】MSP430 LaunchPad演示应用:内部温度测量 不会编辑帖子,直奔主题,利用刚刚到手的MSP430 LaunchPad演示应用,内部温度测量,注意到手后的430先不要下载新程序哦,里面是带程序的准备工作1:下载IAR for MSP430,因为我用的IAR就暂时不提CCS了哦准备工作2:检查电脑是否安装java程序,如果 ...… 查看全部问答> |
|
要使用1062液晶显示 所以通过void cmg88()//关数码管,点阵函数,但是点阵关不不了,还是不停的闪,液晶显示也有点闪,不知道为什么这样。 程序如下: #include//包含头文件,一般情况不需要改动,头文件包含特殊功能 #include ...… 查看全部问答> |
|
【晒心得】+购买的EZ430-CHRONOS-433收到了,第一次海外购物总结 经过漫长的等待,终于在周五收到了手表。不容易啊。 总结下这次的海外购物经验: 这是我第一次从海外购买东西,共经历了7天时间。上周五下的订单,周一就过海关了,很神速。可惜联邦快递在国内不给力,货物到了济南,连续三天,一天是例外情况,F ...… 查看全部问答> |




