这几年一直使用STM32的MCU,对ARM内核的SysTick计时器也经常使用,但几乎没有仔细了解过。最近正好要在移植一个新的操作系统时接触到了这块,据比较深入的了解了一下。

1SysTick究竟是什么?

关于SysTick在STM32的资料中并没有详细的介绍,这可能由于SysTick是ARM内核的东西。在《STM32F10xxx参考手册》、《STM32F4xx参考手册》以及《STM32F7xx参考手册》中,介绍时钟的时候仅仅是在使用树上简单的画出了HCLK时钟经过8分频后送到了Cortex系统时钟。对这个时钟的描述也非常的简单。在《STM32F10xxx参考手册》中仅仅说:“RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。”同样在《STM32F4xx参考手册》和《STM32F7xx参考手册》中,也只是说:“RCC 向 Cortex 系统定时器 (SysTick) 馈送 8 分频的 AHB 时钟 (HCLK)。”

另外,STM32在中断部分对SysTick也有一句话的描述。如在《STM32F10xxx参考手册》中的“9.1.1 系统嘀嗒(SysTick)校准值寄存器”中提到:“系统嘀嗒校准值固定为9000,当系统嘀嗒时钟设定为9MHz(HCLK/8的最大值),产生1ms时间基准。”而在《STM32F4xx参考手册》的“10.1.2 SysTick 校准值寄存器”一节和《STM32F7xx参考手册》“10.1.1 SysTick 校准值寄存器”一节中也都有:“SysTick 校准值设置为 18750。当 SysTick 时钟设置为 18.75 MHz(HCLK/8,HCLK 设为150 MHz),会产生 1 ms 时间基准。”

仅看这些让我们觉得SysTick似乎都是定好的,但事实上并非如此,因为在库函数中有相关寄存器的操作函数。为了搞清楚这一点,我们必须查看Cortex-M3和M4的手册。在《Cortex-M3权威指南》的“第8章 NVIC与中断控制”中有比较详细的描述。首先很明确SysTick 就是一个定时器;其次SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常,主要适用于操作系统的“心跳”节律。关于SysTick的时钟来源最终还是由芯片厂商决定。

SysTick定时器能产生中断,并且是一个单独的异常类型,并且在向量表中有它的一席之地。并有四个寄存器来控制SysTick,在《Cortex-M3权威指南》中对他们的描述如下:

1)、STK_CSR控制寄存器:寄存器内有4个位具有意义

2)、STK_LOAD 重载寄存器

Systick 是一个递减的定时器,当定时器递减至0 时,重载寄存器中的值就 会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24 位的寄存器最大计数0xFFFFFF。

3)、STK_VAL当前值寄存器

也是个24 位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。

4)、STK_CALRB 校准值寄存器 

2STM32中的SysTick

作为一用于系统级的24位递减计时器,在STM32中又是处理的呢?ST在手册里介绍的比较简单,但在库函数中却有比较清楚的定义。不论是标准库还是HAL库都有较为清楚的定义,如在标准库中就定义SysTick寄存器结构体机器操作函数,在misc.C文件中的SysTick_CLKSourceConfig函数,它是一个时钟源配置函数,其定义如下:

/*@功能:配置SysTick时钟源

*@输入参数:  SysTick_CLKSource:  指定 SysTick 时钟源.

*  该参数可以是以下其中一个值:

* @ SysTick_CLKSource_HCLK_Div8: AHB 时钟 8 分频作为SysTick时钟源

* @ SysTick_CLKSource_HCLK: AHB 时钟作为 SysTick 时钟源. */

void SysTick_CLKSourceConfig(uint32_t Sy sTick_CLKSource)

{

assert_param(IS_SYSTICK_CLK_SOURCE(Sy sTi ck_CLKSource));

if(SysTick_CLKSource ==  SysTick_CLKSource_HCLK)

{

SysTick->CTRL |= SysTi ck_CLKSource_HCLK;

}

else

{

SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;

}

}

由此可见,在STM32中时钟可以设置为HCLK或者HCLK的8分频,根据使用的需求而定。默认不配置的话时钟就是HCLK的8分频。同样在HAL苦衷的定义也是如此。

在core_cm3.h文件中有寄存器定义:

typedef struct

{

__IO uint32_t CTRL;

__IO uint32_t LOAD;

__IO uint32_t VAL;

__I uint32_t CALIB;

} SysTick_Type;

还定义了一个 SysTick_Config 函数

#if (!defined(__Vendor_Sy sTickConfig )) ||(__Vendor_SysTickConfig  == 0)

/**

* @功能  初始化并开启 Sy sTick 计数器及其中断

*@输入参数    ticks    两次中断间的 ticks 数值

*@返回值  1 =  失败, 0=成功

*  初始化系统滴答定时器及其中断并开启系统滴答定时器在自由运行模式下以产生周期中断*/

static __INLINE uint32_t SysTick_Config(uint32_t ticks)

{

if(ticks > SysTick_LOAD_RELOAD_Msk)  return(1);/* 重装值超过了 24 位,是不可能的。返回失败值 0 */

SysTick->LOAD  =(ticks & SysTick_LOAD_RELOAD_Msk) - 1; /*  设置重装载寄存器  */

NVIC_SetPriority(SysTick_IRQn, ( 1<<__NVIC_PRIO_BITS) - 1);  /*设置优先级for Cortex-M0系统中断*/

SysTick->VAL  = 0; /*装载计数器值(当前计数值清 0)  */

SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |

Sy sTick_CTRL_TICKINT_Msk| SysTick_CTRL_ENABLE_Msk;/* 使能 Sy sTick 中断请求和 Sy stick 定时*/

return(0);          /*成功,返回 0 */

}

#endif

经过以上分析,我们我们需要,可以很方便的在自己的软件中操作SysTick来实现一些功能。

3STM32SysTick应用举例

既然SysTick我们已经清楚了他的原理及操作,也明白了STM32库中如何来操作它,那么我们能用他来做什么呢?首先我们可以在STM32中使用嵌入式操作系统的时候使用它来,并更具实际应用来设置。其实在不考虑操作系统是我们还可以使用SysTick来实现延时计时器。

一个实现的例子如下:

//定义延时计数的变量

__IO uint32_t TimingDelay;

const uint16_t delayAdjustments=12;

//函数名:ms延时函数

//描 述:参数1即为1ms,1000即为1s;只有几us的误差;

void Delayms(__IO uint32_t nTime)

{

while(SysTick_Config(SystemCoreClock/1000));

SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;// 关闭滴答定时器

TimingDelay = nTime;

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;// 使能滴答定时器

while(TimingDelay != 0);

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

//函数名:us延时函数

//描 述:参数1即为1us,1000即为1ms;只有几us的误差;

void Delayus(__IO uint32_t nTime)

{

while(SysTick_Config(SystemCoreClock/1000000));

SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;// 关闭滴答定时器

TimingDelay = nTime;

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;// 使能滴答定时器

while(TimingDelay != 0);

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

//函数名:延时递减计数函数

//描 述:由systick的中断函数调用,实现延时数值的递减计数

void TimingDelay_Decrement(void)

{

if (TimingDelay != 0x00)

{

TimingDelay--;

}

}

//函数名:延时调整形式的delaynus函数

//描 述:参数1即为1us,1000即为1ms,根据时钟频率的不同时间不同

void delay_nus(uint16_t n)

{

uint16_t j;

while(n--)

{

j=delayAdjustments;//根据不同时钟频率的指令周期调整数值

while(j--);

}

}

//函数名:延时调整形式的delaynms函数

//描 述:参数1即为1ms,1000即为1s,根据时钟频率的不同时间不同

void delay_nms(uint16_t n)

{

while(n--)

{

delay_nus(1000);

}

}

4、参考文献

我们参考了一些经典的手册以及网络论坛上的一些讨论,无法一一列出,暂列出部分参考文献:

(1)、《Cortex-M3权威指南》

(2)、《STM32F10x参考手册》

(3)、《STM32F4参考手册》

(4)、《STM32F7参考手册》

(5)、《STM32F10x库函数说明》

(6)、《STM32F1 HAL库说明》

(7)、《STM32F4 HAL库说明》

(8)、《STM32F7 Hal库说明》

STM32学习及应用笔记一:SysTick定时器学习及应用的更多相关文章

  1. python从写定时器学习Thread

    目录 python从写定时器学习Thread Timer 对象 粗陋的循环定时器 更 pythonic 循环定时器 FAQ python从写定时器学习Thread python 如何写一个定时器,循环 ...

  2. tensorflow编程学习路线及笔记

    话不多说,直接上图! 关于人工智能算法学习思路,欢迎浏览我的另一篇随笔:如果你想开始学习算法,不妨先了解人工智能有哪些方向? 关于python编程学习路线及笔记,欢迎浏览我的另一篇随笔:python编 ...

  3. STM32学习笔记:系统时钟和SysTick定时器

    原文:http://blog.sina.com.cn/s/blog_49cb42490100s60d.html 1.     STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI.HS ...

  4. stm32学习笔记之SysTick的思考

    原文来自--SevenZ的笔记.http://blog.21ic.com/user1/8247/archives/2011/85920.html ? 首先我们要明白什么是SysTick定时器? Sys ...

  5. STM32学习笔记(六) SysTick系统时钟滴答实验(stm32中断入门)

    系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难 ...

  6. STM32时钟系统之利用 systick 定时器来实现准确的延时。

    本篇文章带着大家来认识一下 STM32 的时钟系统,以及利用 systick 定时器来实现一个比较准确的延时. 我们首先从时钟说起,时钟在MCU中的作用,就好比于人类的心脏一样不可或缺.STM32 的 ...

  7. muduo网络库学习笔记(三)TimerQueue定时器队列

    目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...

  8. SYSTick 定时器

        CM3 内核的处理器,内部包含了一个 SysTick 定时器,(SysTick 的时钟源自 HCLK 的 8 分频,8个系统时钟周期systick跳一个,即8*1/72M=1/9 us)Sys ...

  9. SysTick 定时器的使用

    SysTick是STM32中的一个24位的定时器. Cortex‐M3处理器内部包含了一个简单的定时器.因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简.该定时器的时钟 ...

随机推荐

  1. 玩转Redis之Window安装使用(干货)

    距离上次定Gc.Db框架,好久没有更新博客了,今日没什么事,就打算就Redis写点东西. Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.它支持字符 ...

  2. Scala中apply的用法

    Scala中的 apply 方法有着不同的含义, 对于函数来说该方法意味着调用function本身, 以下说明摘自Programming in Scala, 3rd Edition Every fun ...

  3. OC与JavaScript的交互

    stringByEvaluatingJavaScriptFromString的用法,它的功能非常的强大,用起来非常简单,通过它我们可以很方便的操作uiwebview中的页面元素. UIWebView是 ...

  4. Puzzle 面向服务/切面(AOP/IOC)开发框架 For .Net

    Puzzle 面向服务/切面AOP开发框架 For .Net AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效 ...

  5. destoon : 后台无法登录问题解决

    经常有朋友在destoon搬家的时候 , 数据还原之后 , 会出现后台无法登录的情况 . 具体表现为后台帐号密码输入后点击确定 , 页面刷新 .并没有跳转到相应后台页面 . 但是如果帐号密码输入错误 ...

  6. bzoj 4016: [FJOI2014]最短路径树问题

    bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...

  7. jquery tree

      <div class="fl left"  id="nav" style="width:18%" >             ...

  8. redis技巧--IP地址查询对应城市

    场景: 根据IP地址判断用户所在地,虽然网上有好多篇了,但我记录一个一看就懂的,不用看超长文字再自己理解了. 我们有城市和IP地址段的对应关系,如: 上海: 202.127.0.0 ~ 202.127 ...

  9. 项目中运行报错: Loading XML bean definitions from class path resource [applicationContext.xml]

    记录一下: org.springframework.context.support.AbstractApplicationContext prepareRefresh Refreshing org.s ...

  10. 截取UTF-8编码的汉字,最后一个字出现乱码的问题

    问题描述 原来字串内容name为下面内容: ######name=杨乃文做DJ,微信公众号FunRadio.什么样的姿态是小丑姿态?2016046###### 需要截取成大小为64的name_rm[6 ...