当前位置: 首页 > news >正文

STM32之六:SysTick系统滴答定时器

目录

1. SysTick简介

2. 时钟来源

3. SysTick寄存器

3.1 CTRL—SysTick控制及状态寄存器

3.2 RELOAD—SysTick重装载数值寄存器

3.3 CURRENT—SysTick当前数值寄存器

4. systick系统定时器配置

5. 延时函数实现

5.1 延时函数编写步骤

5.2 微秒级延时函数delay_us

5.3 毫秒级延时函数delay_ms

5.4 秒级延时函数delay_s


1. SysTick简介

SysTick——系统定时器,是属于CM3内核的一个外设,内嵌在NVIC中。SysTick是一个24位的向下递减的计数器,从重装载寄存器的值递减到0,之后自动从RELOAD寄存器中重装载定时器初值。只要不使能systick定时器,它就永不停息的一直循环计数,在睡眠模式下也能使用。

systick系统滴答定时器在没有操作系统时,用于延时;在有操作系统时候(RTOS、UCOS2)通常为操作系统提供精准的定时中断(1ms~50ms)。

2. 时钟来源

1. AHB时钟8分频

2. FCLK内核时钟 ,默认选择FCLK内核时钟

3. SysTick寄存器

SysTick有4个寄存器,如下图所示。

SysTick寄存器汇总(来源:野火《STM32库开发实战指南》)

3.1 CTRL—SysTick控制及状态寄存器

控制及状态寄存器共计24位,但只使用了其0、1、2、16位。其中第2位为是时钟选择位,置1表示使用处理器时钟,即系统时钟;

3.2 RELOAD—SysTick重装载数值寄存器

3.3 CURRENT—SysTick当前数值寄存器

3.4 校准数值寄存器,这个本节不需要,暂不介绍。

此图汇总systick的寄存器。

systick寄存器图

4. systick系统定时器配置

查看core_cm3.h可以找到systick_Config()函数,该函数配置了系统定时器的时钟源、重装载值和当前值。

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */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_Type,可以看到该结构体中包含了上文介绍的各个寄存器值。

typedef struct
{__IO uint32_t CTRL;                         /*!< Offset: 0x00  SysTick Control and Status Register */__IO uint32_t LOAD;                         /*!< Offset: 0x04  SysTick Reload Value Register       */__IO uint32_t VAL;                          /*!< Offset: 0x08  SysTick Current Value Register      */__I  uint32_t CALIB;                        /*!< Offset: 0x0C  SysTick Calibration Register        */
} SysTick_Type;

下面是函数中使用的宏定义:

/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos         16                                             /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk         (1ul << SysTick_CTRL_COUNTFLAG_Pos)            /*!< SysTick CTRL: COUNTFLAG Mask */#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask *//* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask *//* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos             0                                             /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick VAL: CURRENT Mask *//* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos            31                                             /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk            (1ul << SysTick_CALIB_NOREF_Pos)               /*!< SysTick CALIB: NOREF Mask */#define SysTick_CALIB_SKEW_Pos             30                                             /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk             (1ul << SysTick_CALIB_SKEW_Pos)                /*!< SysTick CALIB: SKEW Mask */#define SysTick_CALIB_TENMS_Pos             0                                             /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */
/*@}*/ /* end of group CMSIS_CM3_SysTick */

其中,Msk表示掩码操作,掩码操作指的是对一串二进制数据,通过与msk的位操作,达到屏蔽制定位而实现需求。

例如对一串数字的0~3位清零,则可以定制一个msk=00001111。对于cmd=01010101,则cmd & ~msk = 01010101 & 11110000 = 01010000.

1ul,其中ul是一个后缀表示无符号长整型(unsigned long)。<<表示左移位操作,例如a<<b,表示a左移b位,通常代表a*2^{b},即a<<b=a*2^{b}.

例如CTRL寄存器,其中SysTick_CTRL_CLKSOURCE_Msk 表示将1ul左移SysTick_CTRL_CLKSOURCE_Pos位,即2位,可得第2位的值为:1*2^{2}=4-->100,即第2位值为1,联系上文,可知CTRL的第2位为systick定时器的时钟源选择位,将本位赋值1,表示使用系统内核时钟。

如此,便能理解systick_Config()函数了。

5. 延时函数实现

5.1 延时函数编写步骤

  1. 失能systick系统定时器,即SysTick->CTRL 定时器第0位置0。
  2. 将新的重加载值写入到SysTick->LOAD寄存器中。
  3. 将SysTick->VAL的值置为0。
  4. 使能systick系统定时器。

官方推荐代码如下:(参考《Cortex M3与M4权威指南.pdf》第316页)

SysTick->CTRL = 0; // Disable SysTick
SysTick->LOAD = 0xFF; // Count from 255 to 0 (256 cycles)
SysTick->VAL = 0; // Clear current value as well as count flag
SysTick->CTRL = 5; // Enable SysTick timer with processor clock
while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
SysTick->CTRL = 0; // Disable SysTick

下面分别为微秒级、毫秒级、秒级延时函数示例(摘自B站金善愚systick定时器讲解视频)。

5.2 微秒级延时函数delay_us

#define AHB_INPUT  72  //请按RCC中设置的AHB时钟频率填写到这里(单位MHz)void delay_us(u32 uS){ //uS微秒级延时程序(参考值即是延时数,72MHz时最大值233015)	SysTick->CTRL = 0;SysTick->LOAD=AHB_INPUT*uS - 1;//重装计数初值(当主频是72MHz,72次为1微秒)SysTick->VAL=0x00;        //清空定时器的计数器SysTick->CTRL=0x00000005;//时钟源HCLK,打开定时器while(!(SysTick->CTRL&0x00010000)); //等待计数到0SysTick->CTRL=0;//关闭定时器
}

5.3 毫秒级延时函数delay_ms

void delay_ms(u16 ms){ //mS毫秒级延时程序(参考值即是延时数,最大值65535)	 		  	  while( ms-- != 0){delay_us(1000);	//调用1000微秒的延时}
}
//或者
void delay_ms(uint32_t ms)
{while(ms --){SysTick->CTRL = 0; 			// 关闭系统定时器后才能配置寄存器SysTick->LOAD = 72000 - 1; 			// 设置计数值,用于设置定时的时间SysTick->VAL = 0; 			// 清空当前值还有计数标志位SysTick->CTRL = 5; 			// 使能系统定时器工作,且时钟源为系统时钟的8分频(168MHz/8=21MHz)while(!(SysTick->CTRL&0x00010000)); //等待计数到0SysTick->CTRL = 0; 			// 关闭系统定时器	}
}

5.4 秒级延时函数delay_s

void delay_s(u16 s){ //S秒级延时程序(参考值即是延时数,最大值65535)	 		  	  while( s-- != 0){delay_ms(1000);	//调用1000毫秒的延时}
} 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Jenkins中Node节点与构建任务
  • 32路串口服务器 应用领域
  • ISO 45001:提升职业健康与安全管理水平的关键
  • MAC通过SSH连接VirtualBox中的虚拟机
  • 整洁架构SOLID-里氏替换原则(LSP)
  • MySQL表的内连和外连(重点)
  • Java 如何不用再每次新建线程,直接使用公共线程池
  • IoTDB 集群高效管理:一键启停功能介绍
  • 数据结构——排序算法(冒泡、快速、选择、插入)
  • Qt中使用RapidJSON
  • Gitea 仓库事件触发Jenkins远程构建
  • 从零编写一个神经网络完成手写数字的识别分类(pytorch实现)
  • 通过Bugly上报的日志查找崩溃闪退原因
  • Rust: 关于Pin以及move前后分析
  • Python基础-循环语句
  • 「面试题」如何实现一个圣杯布局?
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • Android Volley源码解析
  • HashMap剖析之内部结构
  • java多线程
  • JSDuck 与 AngularJS 融合技巧
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • SpringCloud集成分布式事务LCN (一)
  • webpack4 一点通
  • 前端技术周刊 2019-02-11 Serverless
  • 如何用vue打造一个移动端音乐播放器
  • 微信支付JSAPI,实测!终极方案
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 小程序button引导用户授权
  • 学习笔记TF060:图像语音结合,看图说话
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #include
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (4.10~4.16)
  • (52)只出现一次的数字III
  • (arch)linux 转换文件编码格式
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (day6) 319. 灯泡开关
  • (八)Flink Join 连接
  • (二)windows配置JDK环境
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)jdk与jre的区别
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • ::什么意思
  • @FeignClient注解,fallback和fallbackFactory
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [4.9福建四校联考]
  • [acwing周赛复盘] 第 94 场周赛20230311
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [Angular] 笔记 21:@ViewChild
  • [bzoj1324]Exca王者之剑_最小割