STM32 SysTick 滴答定时器原理及应用

发布者:清新家园最新更新时间:2018-07-17 来源: eefocus关键字:STM32  SysTick  滴答定时器 手机看文章 扫描二维码
随时随地手机看文章

SysTick滴答定时器

一、功能

SysTick定时器是一个简单的定时器,CM3\CM4内核芯片都具备此定时器。SysTick定时器常用来做延时,采用实时系统时则用来做系统时钟。

无论用作延时还是用作系统心跳时钟,不需要太复杂的功能,SysTick即可胜任。

二、实现原理

SysTick定时器是一个24位的倒计数,当倒计数为0时,将从RELOAD寄存器中取值作为定时器的初始值,同时可以选择在这个时候产生中断(异常号:15)。

例如从RELOAD的值为999,那么当倒计数为0时,就会从复位为999继续倒计数。

        只要不把它在SysTick控制及状态寄存器中的使能位清楚,就永不停息,即使在睡眠模式下也能继续工作。

三、SysTick寄存器(在 core_cm3.h 有定义,凡是 M3 内核的单片机都是一样的)

#define SysTick             ((SysTick_Type *)       SysTick_BASE) 

#define SysTick_BASE        (SCS_BASE +  0x0010)

#define SCS_BASE            (0xE000E000) 

typedef struct

{

  __IO uint32_t CTRL;  // 控制及状态寄存器

  __IO uint32_t LOAD;   // 重装载数值寄存器

  __IO uint32_t VAL; // 当前计数数值寄存器

  __I  uint32_t CALIB;  // 校准寄存器

} SysTick_Type;

SysTick->CTRL: (可通过 SysTick_CLKSourceConfig() 函数设置)

COUNTFLAG(16)R: 计数标志位

当SysTick数到0,则该位被硬件置 1,当读取该位时,将被硬件清零

CLKSOURCE(2)R/W: 时钟源设置

1 = 外部时钟源(STCLK) (AHB总线时钟的1/8(HCLK/8))

0 = 内核时钟(FCLK)  (AHB总线时钟的频率(HCLK))

TICKINT(1)R/W: 中断使能位

1 = SysTick 倒数到0时产生 SysTick 异常请求

0 = 数到 0 时无动作

ENABLE(0)R/W: SysTick 定时器使能位

(当中断被使能后,需要关注 void SysTick_Handler(void) 函数)

SysTick_Type->LOAD: (SysTick_Config() 函数会设置该寄存器)

RELOAD(23:0)R/W: 重装载数值寄存器

当SysTick数到0,将被重装载的值

SysTick_Type->VAL: (SysTick_Config() 函数会设置该寄存器)

CURRENT(23:0)R/Wc: 当前计数数值寄存器

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

四、库函数分析

misc.c

----------------------------------------------------------------------------------

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)

#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)

#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \

((SOURCE) == SysTick_CLKSource_HCLK_Div8))

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)

{

  /* Check the parameters */

  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));

  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)

  {

SysTick->CTRL |= SysTick_CLKSource_HCLK; // 设置 CLKSOURCE 为 1

  }

  else

  {

SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;      // 设置 CLKSOURCE 为 0

  }

}


core_cm3.c

----------------------------------------------------------------------------------

#define SysTick_LOAD_RELOAD_Pos             0                                           

#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)

typedef enum IRQn

{

//...

SysTick_IRQn                = -1, 

//...

}IRQn_Type;

#define __NVIC_PRIO_BITS          4

#define SysTick_CTRL_CLKSOURCE_Pos          2                                           

#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)          


#define SysTick_CTRL_TICKINT_Pos            1                                           

#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)            


#define SysTick_CTRL_ENABLE_Pos             0                                           

#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos) 

static __INLINE uint32_t SysTick_Config(uint32_t ticks)

  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */

  // 设置计数值为 ticks - 1 

  // 原因1:视频说是执行这些代码需要时间,所以减少一个节拍

  // 原因2:我认为是因为 SysTick 的倒计数到 0,例如设置 1000 ,那么范围就应该是 999 ~ 0。

  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;     

  // 设置中断优先级

  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 

  SysTick->VAL   = 0;                                

  // 设置时钟源为外部时钟源,同时开启中断、并使能 SysTick 定时器

  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 

   SysTick_CTRL_TICKINT_Msk   | 

   SysTick_CTRL_ENABLE_Msk;                   

  return (0);                                                 

}

五、延时应用

1、中断方式

static __IO uint32_t TimingDelay;

void Delay(__IO uint32_t nTime)

   TimingDelay = nTime;

   while(TimingDelay != 0);

}

/* 中断服务函数 */

void SysTick_Handler(void)

{

if (TimingDelay != 0x00) 

TimingDelay--;

}

}

int main(void)

{  

// ...

if (SysTick_Config(SystemCoreClock / 1000)) // 注意,这里systick时钟为HCLK,中断时间间隔1ms 

{

while (1);

}

while(1)

{

Delay(200);//2ms

// ...

}

}

SysTick_Config(SystemCoreClock / 1000): (原代码这里假设是采用时钟源为 HCLK)

这里设置的是 72000000Hz / 1000 = 72000 ticks,也就是说 SysTick 从 (72000-1) 开始倒数。

每倒数完 72000 个节拍就触发一次中断。

一个节拍的时间为:72000000 / 72000 = 1000us == 1ms

SysTick_Config((SystemCoreClock / 8000000) * 1000 * 1): 

SysTick_Config() 会设置时钟源为 HCLK/8 所以实际应用中不能按照上述代码的参数。

SystemCoreClock / 8000000: 1us 的节拍数

1us的节拍数 * 1000: 则为 1ms 的节拍数

1ms 的节拍数 * 1: 设置 1ms 一个SysTick中断,即从 ((SystemCoreClock / 8000000) * 1000 * 1) - 1 开始倒数。

2、轮询方式

static u8  fac_us=0; //us延时倍乘数    

static u16 fac_ms=0; //ms延时倍乘数

void delay_init()

{

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟  HCLK/8

fac_us = SystemCoreClock/8000000;         // 为系统时钟的1/8  1us = 72000000 / 8000000 =  9 个节拍

fac_ms = (u16)fac_us*1000; // 1ms 需要 9 * 1000 = 9000 个节拍

}

//延时 nus 微秒         

void delay_us(u32 nus)

{

u32 temp;

SysTick->LOAD=nus*fac_us;  //时间加载     

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

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;                //开始倒数

do

{

temp=SysTick->CTRL;

}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达  

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;//关闭计数器

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

}

//延时nms

//注意nms的范围

//SysTick->LOAD为24位寄存器,所以,最大延时为:

//nms<=0xffffff*8*1000/SYSCLK

//SYSCLK单位为Hz,nms单位为ms

//对72M条件下,nms<=1864 

void delay_ms(u16 nms)

{        

u32 temp;    

SysTick->LOAD=(u32)nms*fac_ms;   //时间加载(SysTick->LOAD为24bit)

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

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;  //开始倒数 

do

{

temp=SysTick->CTRL;

                //等待时间到达,这里使用了一个小技巧,通过(temp&0x01)检查 SysTick 的使能位,避免 Systick 定时器被关闭而导致无限循环 

}while((temp&0x01)&&!(temp&(1<<16)));  

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器

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


关键字:STM32  SysTick  滴答定时器 引用地址:STM32 SysTick 滴答定时器原理及应用

上一篇:STM32中sysTick的设置
下一篇:STM32 Systick定时器在实现1us延时的问题与解决

推荐阅读最新更新时间:2024-03-16 16:09

意法半导体的新STM32探索套件简化移动网至云端连接
中国,2018年3月2日 —— 意法半导体专门配置的两个STM32探索套件让物联网设备能够通过2G/3G或LTE Cat M1/NB1网络快速连接云服务,让大众市场开发人员更自由、更灵活地开发应用。 每款套件都包括一个STM32L496探索板和集成一个Quectel蜂窝移动网络调制解调器的STMod+ 蜂窝扩展板。配套软件包括X-CUBE-CLD-GEN,这是一个移植到STM32L496超低功耗微控制器和扩展板的Espruino嵌入式JavaScript引擎,兼容STM32Cube生态系统。  硬件可直接使用,开发人员可以在JavaScript引擎上快速启动并定制脚本示例,无需额外投资。X-CUBE-CLD-GEN扩展
[半导体设计/制造]
STM32开发入门之串口详解
  一、通信接口   处理器与外部设备通信的两种方式:   并行通信:   -传输原理:数据各个位同时传输。   -优点:速度快   -缺点:占用引脚资源多   串行通信:   -传输原理:数据按位顺序传输。   -优点:占用引脚资源少   -缺点:速度相对较慢   串行通信,按照数据传送方向,分为:   单工:   数据传输只支持数据在一个方向上传输   半双工:   允许数据在两个方向上传输,但是,在某一时刻,只允许数   据在一个方向上传输,它实际上是一种切换方向的单工通信;   全双工:   允许数据同时在两个方向上传输,因此,全双工通信是两个   单工通信方式的结合,它要求发送设备和接收设备都有独立
[单片机]
<font color='red'>STM32</font>开发入门之串口详解
STM32 Flash
1:Flash简介 FLASH存储器是闪速存储器,它的主要特点是在不加电的情况下能长期保持存储的信息。就其本质而言,Flash Memory属于EEPROM(电擦除可编程只读存储器)类型。它既有ROM的特点,又有很高的存取速度,而且易于擦除和重写, 功耗很小。 2:嵌入式Flash特性 对于 STM32F40x 和 STM32F41x,容量高达 1 MB;对于 STM32F42x 和 STM32F43x,容量高达 2 MB 128 位宽数据读取 字节、半字、字和双字数据写入 扇区擦除与全部擦除 低功耗模式 STM32F40x和STM32F41x Flash 模块构成 可以看到 主存储器 该部分用来存放代码和数据常数(如
[单片机]
<font color='red'>STM32</font> Flash
STM32按键输入程序
简介:这是一个STM32按键输入程序,配有原理图及相关程序解析。KEY_Scan函数频繁调用了JTAG_Set函数,每次按键扫描的时候都禁用了JTAG和SWD。 原理图: 程序: delay_init();延时函数,以后再讲 LED_Init();KEY_Init();初始化LED灯何按键为上拉输入 KEY_Scan();
[单片机]
<font color='red'>STM32</font>按键输入程序
STM32的GPIO的寄存器配置学习1
本篇文章主要是学习以M3内核的STM32的GPIO的寄存器的配置,为什么要学习寄存器,而不利用库函数呢?我只能说为了让学的知识更加牢固吧!当然,你可以直接去利用库函数,但是如果你能认真读完本篇博客,你会对知识豁然开朗!加油吧! STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:配置模式的 2 个 32 位的端口配置寄存器 CRL 和 CRH;2 个 32 位的数据寄存器 IDR 和 ODR;1 个 32 位的置位/复位寄存器BSRR;一个 16 位的复位寄存器 BRR;1 个 32 位的锁存寄存器 LCKR;这里我们仅介绍常用的几个寄存器,我们常用的 IO 端口寄存器只有 4 个:CRL、CRH、IDR、OD
[单片机]
<font color='red'>STM32</font>的GPIO的寄存器配置学习1
STM32基础知识:中断系统
中断系统 1 数据传输方式 无条件传输 :处理器不必了解外部设备状态,直接进行数据传输,用于指示灯和按键等简单设备.。 查询方式 :传输前,一方先查询另一方的状态,若已经准备好就传输,否则就继续查询。 中断方式 :一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作。 直接存储器访问 :处理器内部建立片内外设和内存之间的数据传输通道,传输过程不需要处理器参与。 2 中断系统的基本概念 2.1 中断全过程 中断发生: 当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。 中断处理: CPU暂停当前的工作,转去处理事件B。 中断返回: 当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继
[单片机]
<font color='red'>STM32</font>基础知识:中断系统
基于STM32的CAN总线通信程序
#include #include sys.h #include delay.h #include CAN.h CAN_msg CAN_TxMsg; //发送邮箱 CAN_msg CAN_RxMsg; //接收邮箱 u8 CAN_TxRdy=0; //发送就绪标志 u8 CAN_RxRdy=0; //接收就绪标志 u8 CAN_TDTxR_DLC; //数据长度,最高为1111 /////////////////CAN设置///////////////////////////////////// void CAN_setup(void) { u8 brp=20;
[单片机]
零基础入门stm32知识学习的先后顺序
  这里大概的罗列了一些学习STM32的内容,以及学习顺序。如果是新手的话,建议边看中文手册和学习视频(一般都看原子的,视频的话百度就可以了,如果实在是找不到的话,我给大家推荐一个网站:21ic公开课,里面很多免费的基础学习视频,非常适合广大的学生);如果是已经入门的,个人建议自己做一个项目,不论项目大小,当然里面会涉及到自己已经学习过的,或者是自己正在学习的,亦或是自己想来想要学习的,一边学习,一边做项目。这样好处颇多,大家慢慢去体会。下面就是本人所罗列的一些STM32的内容,不需要看懂,只需要记住即可,在你以后慢慢深入的过程中,就会了解到的:   1、STM32基本配置(运行环境、编译器、下载器、板子等)。   2、G
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved