嵌入式开发十九:SysTick—系统定时器

2024-06-20 14:28

本文主要是介绍嵌入式开发十九:SysTick—系统定时器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

         在前面实验中我们使用到的延时都是通过SysTick进行延时的。 我们知道,延时有两种方式:软件延时,即CPU 循环等待产生的,这个延时是不精确的。第二种就是滴答定时器延时,本篇博客就来介绍 STM32F4 内部 SysTick 系统定时器,通过一个简单的 LED 流水灯程序来讲述如何配置 SysTick 系统定时器实现精确延时。学习可以参考《STM32F3 与 F4 系列 Cortex M4 内核编程手册》 4.5 SysTick timer (STK) 章节或者参考库函数中 core_cm4.h 文件 。

目录

一、SysTick 定时器介绍

二、SysTick 定时器操作

2.1 SysTick 定时器寄存器

2.1.1 控制和状态寄存器:CTRL

2.1.2  重装载寄存器:LOAD

2.1.3 当前数值寄存器:VAL

2.1.4  校准数值寄存器:CALIB 

2.2 系统节拍定时器的工作原理

2.3 SysTick 定时器操作步骤

2.4  使用SysTick 定时器实现精准延时

2.4.1 实现1微秒延时

2.4.2 实现1毫秒延时

2.4.3 实现1秒延时

三、SysTick 定时实验

一、SysTick 定时器介绍

       SysTick 定时器也叫 SysTick 滴答定时器,它是 Cortex-M4 内核的一个外设, 被嵌入在 NVIC 中,用来产生SYSTICK异常(异常号:15)。它是一个 24 位向下递减的定时器,每计数一次所需时间为 1/SYSTICK,SYSTICK 是系统定时器时钟,它可以直接取自系统时钟,还可以通过系统时钟 8 分频后获取,本套程序中我们采用后者,即每计数一次所需时间为 1/(168/8)us,换句话说在 1us 的时间内会计数 21 次。当定时器计数到 0 时,将 从 LOAD 寄存器中自动重装定时器初值,重新向下递减计数,如此循环往复。如果开启 SysTick 中断的话,当定时器计数到 0,将产生一个中断信号。如下图所示,因此只要知道计数的次数就可以准确得到它的延时时间。 因为 SysTick 是属于 CM4 内核的外设,所以所有基于 CM4 内核的单片机都具有这个系统定时器,使得软件在 CM4 单片机中可以很容易的移植。系统定时器一般用于操作系统, 用于产生时基,维持操作系统的心跳。

如何计算延时时间?

       如果时钟源选择8分频后的即21MHZ,那么,1秒钟就会计数21000000次,(计数一次的时间就是:1/21000000),如此:如果想要定时1毫秒,就要计数21000次,定时1微秒,就要计数21次!

二、SysTick 定时器操作

        在 STM32F4 库函数中,并没有提供相应的 SysTick 定时器配置函数,我们要操作 SysTick 定时器就需要了解它的寄存器功能。其实 SysTick 定时器寄存器很 简单,只有 4 个,分别是 CTRL、LOAD、VAL、CALIB,在使用 SysTick 产生定时的时候, 只需要配置前三个寄存器,最后一个校准寄存器不需要使用。对应如下图所示:

2.1 SysTick 定时器寄存器

2.1.1 控制和状态寄存器:CTRL

CTRL 是 SysTick 定时器的控制及状态寄存器。其相应位功能如下:

注:CLKSOUTCE 位是用于选择 SysTick 定时器时钟来源:

  1. 如果该位为 1,表示其时钟是由系统时钟直接提供即 168M。
  2. 如果该位为 0,表示其时钟是由系统时钟八分频后提供即 168/8=21M。

2.1.2  重装载寄存器:LOAD

LOAD 是 SysTick 定时器的重装载数值寄存器。其相应位功能如下:

因为 STM32F4 的 SysTick 定时器是一个 24 位递减计数器,因此重装载寄存器中只使用到了低 24 位,即 bit0-bit23。当系统复位时,其值为 0。

2.1.3 当前数值寄存器:VAL

VAL 是 SysTick 定时器的当前数值寄存器。其相应位功能如下:

同样只有 bit0-bit24 有效,复位时值为 0。

2.1.4  校准数值寄存器:CALIB 

CALIB 是 SysTick 定时器的校准数值寄存器。其相应位功能如下:

此寄存器在定时实验中不需要使用,可以不用了解。

2.2 系统节拍定时器的工作原理

        当系统节拍定时器⼯作时,该定时器⾸先会从寄存器LOAD存储的值开始递减计数。当递减为0 后,寄存器CTRL的COUNTFLAG状态位会置1,同时会重装载寄存器LOAD预置的值。 当计数到0时,通过设置寄存器CTRL的TICKINT的值来产⽣异常(中断),或是⽆动作。

2.3 SysTick 定时器操作步骤

SysTick 定时器的操作可以分为 4 步:

  1. 设置 SysTick 定时器的时钟源。
  2. 设置 SysTick 定时器的重装初始值(如果要使用中断的话,就将中断使能打开)。
  3. 清零 SysTick 定时器当前计数器的值。
  4. 打开 SysTick 定时器。

2.4  使用SysTick 定时器实现精准延时

2.4.1 实现1微秒延时

void Sleep_us(uint32_t us)
{while(us--){SysTick ->CTRL = (1 << 0);   //定时器使能第0位置1SysTick ->CTRL &= ~(1<<2);   //选择时钟源:第2位置0,选择外部时钟源,由系统时钟八分频后提供即 168/8=21MSysTick ->CTRL &= ~(1<<1);   //延时时间到无动作:第1位置0SysTick ->VAL = 0x0;        //当前数值寄存器初值赋0SysTick ->LOAD = 21;       //重装载数值寄存器的值,定时1微秒,所以是21while(!(SysTick ->CTRL & (1<<16)));  //死循环等待计数值减到0SysTick ->CTRL = ~(1<<0);    //关闭定时器,第0位置0}}//复用上述函数实现延时1秒
void Sleep_s(uint32_t s)
{while(s--){Sleep_ms(1000);}
}

2.4.2 实现1毫秒延时

void Sleep_ms(uint32_t ms)
{while(ms--){SysTick ->CTRL = (1 << 0);   //定时器使能第0位置1SysTick ->CTRL &= ~(1<<2);   //选择时钟源:第2位置0,选择外部时钟源,由系统时钟八分频后提供即 168/8=21MSysTick ->CTRL &= ~(1<<1);   //延时时间到无动作:第1位置0SysTick ->VAL = 0x0;        //当前数值寄存器初值赋0SysTick ->LOAD = 21000;       //重装载数值寄存器的值,定时1毫秒,所以是21000while(!(SysTick ->CTRL & (1<<16)));  //死循环等待计数值减到0SysTick ->CTRL = ~(1<<0);    //关闭定时器,第0位置0}}

2.4.3 实现1秒延时

void Sleep_s(uint32_t s)
{while(s--){SysTick ->CTRL = (1 << 0);   //定时器使能第0位置1SysTick ->CTRL &= ~(1<<2);   //选择时钟源:第2位置0,选择外部时钟源,由系统时钟八分频后提供即 168/8=21MSysTick ->CTRL &= ~(1<<1);   //延时时间到无动作:第1位置0SysTick ->VAL = 0x0;        //当前数值寄存器初值赋0SysTick ->LOAD = 21000000;       //重装载数值寄存器的值,定时1秒,所以是21000000while(!(SysTick ->CTRL & (1<<16)));  //死循环等待计数值减到0SysTick ->CTRL = ~(1<<0);    //关闭定时器,第0位置0}}

1秒=1000毫秒=1000微秒。

三、SysTick 定时实验

利用 SysTick 产生 1s 的时基,LED 以 1s 的频率闪烁。

led.h文件

#ifndef __MYLED_H
#define __MYLED_Hvoid LED_Init(void);#endif

led.c 文件

#include "stm32f4xx.h"                  // Device header
#include "myled.h"/*开时钟  打开外设对应的时钟(查看参考手册,该外设挂在哪个数据总线上),对应GPIO在哪条总线开哪条GPIOF外设 挂在AHB1总线上,所以要打开AHB1的时钟,双击函数,右键->go to definition*/void LED_Init(void)
{//第一步:使能GPIOF的时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟//第二步:GPIOF9,F10 初始化设置GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1 对应 IO 口GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO//第三步:设置灯的初始状态GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10 设置高电平,灯灭
}

mydelay.h

#ifndef __MYLED_H
#define __MYLED_Hvoid LED_Init(void);#endif

mydelay.c

#include "stm32f4xx.h"                  // Device header
#include "mydelay.h"void My_Delay_us(uint32_t num)
{while(num--){SysTick ->CTRL = (1 << 0);SysTick ->CTRL &= ~(1<<2);SysTick ->CTRL &= ~(1<<1);SysTick ->VAL = 0x0;SysTick ->LOAD = 21;while(!(SysTick ->CTRL & (1<<16)));SysTick ->CTRL = ~(1<<0);}
}void My_Delay_ms(uint32_t num)
{while(num--){My_Delay_us(1000);}
}void My_Delay_s(uint32_t num)
{while(num--){My_Delay_ms(1000);}
}

main.c文件

#include "stm32f4xx.h"                  // Device header
#include "stdio.h"
#include "mydelay.h"
#include "myled.h"int main(void)
{LED_Init();while(1){My_Delay_ms(1000);           //延时1秒GPIO_ToggleBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);}
}

实验现象:

     两个灯每隔一秒闪烁一次。

至此,我们的本次的学习就结束了。通过以上几个实验,相信对串口通信有了深入的理解,这一节我们就讲解到这里,希望能对大家的开发有帮助。 如有兴趣,感谢点赞、关注、收藏,若有不正地方,还请各位大佬多多指教!

这篇关于嵌入式开发十九:SysTick—系统定时器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1078388

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

PS系统教程25

介绍软件 BR(bridge) PS 配套软件,方便素材整理、管理素材 作用:起到桥梁作用 注意:PS和BR尽量保持版本一致 下载和安装可通过CSDN社区搜索,有免费安装指导。 安装之后,我们打开照片只需双击照片,就自动在Ps软件中打开。 前提:电脑上有PS软件 三种预览格式 全屏预览 评星级 直接按数字键就可以 方向键可以更换图片 esc退出 幻灯片放

风水研究会官网源码系统-可展示自己的领域内容-商品售卖等

一款用于展示风水行业,周易测算行业,玄学行业的系统,并支持售卖自己的商品。 整洁大气,非常漂亮,前端内容均可通过后台修改。 大致功能: 支持前端内容通过后端自定义支持开启关闭会员功能,会员等级设置支持对接官方支付支持添加商品类支持添加虚拟下载类支持自定义其他类型字段支持生成虚拟激活卡支持采集其他站点文章支持对接收益广告支持文章评论支持积分功能支持推广功能更多功能,搭建完成自行体验吧! 原文

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

又看见定时器了,怎么这么想写了~~

1.scheduleUpdate(); 与virtual void update(float dt);   联合使用,就是每隔一段时间就调用一次update,实际上是每一帧都调用一次updata方法,scheduleUpdate();方法相当于开启了定时器。 2.schedule的作用和scheduleUpdate差不多,只是这个其实更好用一些,这个可以只是指定调用的方法,系统默认每一帧都调用一