这几年一直使用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. 使用App.config管理数据库连接

    程序的数据库连接字符串可以保持在程序的配置文件App.config中,便于管理. 将配置文件添加至解决方案: 添加连接信息: <?xml version="1.0"?> ...

  2. Python 【第八章】:JavaScript 、Dom、jQuery

    JavaScript 放置位置 body内部最下面,这样可以避免javascript链接失效时,长时间加载不到页面html内容 变量: var a =123 局部变量 a = 123 全局变量 作用域 ...

  3. Java MD5机密算法的使用

    MD5 是常用的加密算法,是不可逆的.既只能加密,但不能解密. package cn.com.ctsi.csdp.base.util; import java.security.MessageDige ...

  4. CSS-各种cs样式之浏览器兼容处理方式汇总大全(更新中...)

    页面模板 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 ...

  5. ORACLE中的LTRIM、RTRIM和TRIM

    LTRIM.RTRIM和TRIM在ORACLE中的用法:1.LTRIM(C1,C2)其中C1和C2都可以字符串,例如C1是'Miss Liu',C2'MisL'等等.这是第一个和SQL SERVER不 ...

  6. SQL中distinct的用法

    SQL中distinct的用法   1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...

  7. 纯CSS3实现动态导航栏目

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【转】Python实现不同格式打印九九乘法表

    前言:最近在学习Python,学习资源有慕课网上的视频教程.菜鸟教程以及Python官方文档tutorial.虽然了解了Python的基本语法,但是还没有真正意义上输出自己写的代码.代码小白,之前仅学 ...

  9. 【转】Ubuntu 16.04安装配置TensorFlow GPU版本

    之前摸爬滚打总是各种坑,今天参考这篇文章终于解决了,甚是鸡冻\(≧▽≦)/,电脑不知道怎么的,安装不了16.04,就安装15.10再升级到16.04 requirements: Ubuntu 16.0 ...

  10. ThinkphpCMF笔记

    1.模板js,css文件__PUBLIC__ <link href="__TMPL__Public/style.css" rel="stylesheet" ...