从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick

2023-05-16

系列文章目录

Github开源地址
从头开始写STM32F103C8T6驱动库(一)——STM32CubeMX创建并调整工程结构
从头开始写STM32F103C8T6驱动库(二)——编写系统初始化程序,配置时钟树
从头开始写STM32F103C8T6驱动库(三)——编写GPIO驱动
从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick


文章目录

  • 系列文章目录
  • 前言
    • 1.Systick定时器介绍
    • 2.Systick定时器使用方法
    • 3.编写微秒延时程序(delay_us)
    • 4.编写毫秒延时程序(delay_ms)
    • 5.编写测试程序


前言

上一章我们编写了GPIO驱动函数,但是如果我们想使用GPIO来实现一个流水灯的话还需要一个延时函数,今天我们就来写一下使用Systick实现的系统延时函数


1.Systick定时器介绍

Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的Cortex‐M3芯片都带有这个定时
器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,
CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。 Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

2.Systick定时器使用方法

在这里插入图片描述
Systick定时器的使用方法也十分简单,稍微介绍一下就能理解,首先Systick定时器共有四个寄存器:

  1. SysTick控制及状态寄存器(SysTick->CTRL):该寄存器负责控制Systick定时器的相关功能
  2. SysTick重装载数值寄存器(SysTick->LOAD):定时器所要计数的值
  3. SysTick当前数值寄存器(SysTick->VAL):定时器当前的数值
  4. SysTick校准数值寄存器(SysTick->CALIB):定时器校准相关的寄存器

(1)所以想要使用SysTick定时器实现延时函数就是先选择一个时钟源,这里我们使用默认的外部时钟源(此外部时钟非彼外部时钟,是Systick定时器外的时钟并非单片机芯片的外部时钟)
在这里插入图片描述

该定时器的时钟源可以是内部时钟(FCLK,
CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过, STCLK的
具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视
芯片的器件手册来决定选择什么作为时钟源。
——————————————————————————————节选自Cortex‐M3 权威指南

而STM32上所指的STCLK是

RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick
控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。
——————————————————————————————节选自STM32F10xxx参考手册
在这里插入图片描述

(2)第二步载入定时器所要计数的值
(3)第三步清空定时器当前的数值
(4)第四步使能定时器
(5)第五步循环等待SysTick控制及状态寄存器(SysTick->CTRL)字段16置1

3.编写微秒延时程序(delay_us)

和第三章同样的方法我们新建delay.c和delay.h文件并添加到工程当中,这里就不再赘述了,详细教程可见第三章:
从头开始写STM32F103C8T6驱动库(三)——编写GPIO驱动

  1. 编写函数名

首先我们需要了解一下计时器所能计的最大值是多少,这涉及到我们函数声明时传入参数的数据类型
在这里插入图片描述
从上图可以看出SysTick重装载数值寄存器所能写入的最大值为2^24因为没有"uint24"这个数据类型所以我们需要用uint32类型来声明传入参数,但是输入范围必须限制在 0 ~ 2^24

void delay_us(uint32 us)
  1. 对输入参数做单边限幅
us = (1<<25) <= us ? (1<<25) - 1 : us;
  1. 载入定时器所要计数的值
    现在有一个问题就是我们需要向重装载数值寄存器写入多少才是我们想要的时间呢?
    回顾刚才我们所说的,我们使用Systick默认的外部时钟作为时钟源,而在STM32中RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。
    这里还需要回顾一下第二章我们所配置的时钟树,详情可见:
    从头开始写STM32F103C8T6驱动库(二)——编写系统初始化程序,配置时钟树
    在这里插入图片描述
    在第二章中我们配置的AHB时钟频率为72MHz所以经过8分频后也就是Systick的时钟频率为9MHz。
    也就是说当前Systick计一个数需要1/9,000,000秒。
    所以:
    LOAD(载入数值)=t(计时时间,单位:秒) x T(频率,单位:Hz)

我们现在common.h文件中将各个外设桥频率宏定义,方便我们后期更改

//系统各外设桥主频
#define 		AHB_freq			72000000UL
#define 		APB1_freq			36000000UL
#define 		APB2_freq			72000000UL

数字后面字母的含义
U:unsigned
L:long / double
F:float

也就是表示无符号长整型的意思。

然后再在delay_us函数中编写

SysTick->LOAD = us * (AHB_freq / 8000000);
  1. 清空当前数值寄存器的值
SysTick->VAL = 0;
  1. 使能定时器
SysTick->CTRL |= 0x01<<SysTick_CTRL_ENABLE_Pos;
  1. 循环等待计数值为0
while(!(SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk));
  1. 关闭定时器
SysTick->CTRL &= ~(0x01<<SysTick_CTRL_ENABLE_Pos);
  1. 完整代码如下:
/**
	* @name		delay_us
  * @brief  微秒延时函数
	* @param  us	延时微秒数   0 ~ 2^24
	* @return void
	* @Sample delay_us(2)
  */
void delay_us(uint32 us)
{
	us = (1<<25) <= us ? (1<<25) - 1 : us;
	//LOAD(载入数值)= t(计时时间,单位:秒) x T(频率,单位:Hz)
	SysTick->LOAD = us * (AHB_freq / 8000000);
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;
	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
	SysTick->CTRL &= ~(0x01<<SysTick_CTRL_ENABLE_Pos);
}

4.编写毫秒延时程序(delay_ms)

ms延时要注意计数器数值范围问题,我们可以算一下最大计时时间
2^24 = 16,777,216 / 9,000,000Hz = 1.864135s
也就是说毫秒延时最大为1864ms
具体方法和微妙延时大同小异,代码如下:

/**
	* @name		delay_ms
  * @brief  毫秒延时函数
	* @param  ms	毫秒微秒数   0 ~ 1864
	* @return void
	* @Sample delay_ms(100)
  */
void delay_ms(uint16 ms)
{
	ms = 1864 <= ms ? 1864 : ms;
	SysTick->LOAD = ms * (AHB_freq / 8000);
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;
	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
	SysTick->CTRL &= ~(0x01<<SysTick_CTRL_ENABLE_Pos);
}

5.编写测试程序

我们来简单写一个闪灯程序,发现小灯是可以已10Hz频率在闪烁,说明我们的延时数运行正确。

int main(void)
{
	gpio_init(PC13, GPO, 0, GPO_PUSH_PULL, GPIO_SPEED_50MHZ);
 	while (1)
  	{
		delay_ms(100);
		gpio_reverse(PC13);
  	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick 的相关文章

  • 手机摄像头的等效焦距

    笔者随意拿出一张最近评测文章中的样张 xff0c EXIF信息就位于照片的下方 我们看到 xff0c 光圈 ISO感光度 曝光时间 曝光补偿这样的参数都比较好理解 xff0c 唯独这个焦距确实让不少人生疑 焦距 4mm 光圈 f 2 4 I
  • 关于3D打印文件格式:STL、OBJ、AMF、3MF的详解

    很多人对3D打印的数据格式颇有微词 xff0c 辛辛苦苦用三维软件设计好的作品 xff0c 一转换成3D打印格式 xff0c 基本就从白天鹅变成丑小鸭了 xff0c 既没有颜色 xff0c 数据也不完整 xff0c 形状重叠表面破损那是常有
  • 在线绘制函数图像和在线图标绘制网址

    经过寻找 xff0c 找到了几个在线绘制函数图像的网址 xff0c 可以不用matlab和geogebra软件绘制了 数学函数图像 xff1a 第一个 xff1a Desmos 首推 第二个 xff1a fooplot 可以绘制分段函数比如
  • geogebra中函数的定义域的输入

    ggb中函数的输入有如下几种方式 xff1a 一 如果if做法 1 区间函数 xff1a 做出函数在某区间上的图象 xff1a f x 61 if x gt 61 0 amp amp x lt 61 2 x 2 43 2x 1 2 分段函数
  • 升级Ubuntu内核

    自己下载deb或使用某些其他工具 xff0c 无脑dpkg deb会导致Depends libc6 gt 61 2 33 but 2 31 ubuntu9 2 is to be installed的错误 xff08 猜测该错误产生的原因是没
  • 在ROS的noetic版本中通过rosrun运行python文件

    xff08 1 xff09 不要将python文件放入scr目录中 xff0c 否则后续编译工作空间会报如图所示的错误 首先要在功能包文件夹 xff08 catkin ws src learnning topic xff09 中创建一个sc
  • linux音量调节

    转自 xff1a https www jianshu com p fc8c8cad67d6 一 alsa设置默认声卡 alsa设置默认声卡 理解和使用Alsa的配置文件 alsa的配置文件是alsa conf位于 usr share als
  • FutureTask实际应用案例

    GetResultTask java package com cwp data service service task import com cwp data intelligence common exception RRExcepti
  • 异常检测算法综述

    一 异常检测 随着人工智能的火热 xff0c 运维人员也开始考虑将算法引入运维领域 xff0c 对传统DevOps的核心功能进行优化改进 异常检测是运维不可或缺的重要要功能模块之一 xff0c 可以提升企业运维能力和效率 xff0c 释放运
  • 每日一书丨嵌入式C语言自我修养:从芯片、编译器到操作系统

    最近 xff0c 阅读了王工 xff08 王利涛 xff09 赠送的一本由他编著的书籍 嵌入式C语言自我修养 xff0c 感觉写的挺不错 今天分享一下这本书籍 嵌入式C语言自我修养 xff1a 从芯片 编译器到操作系统 从芯片 编译器到操作
  • JSP提交仍然停留在当前页面

    在C S结构中 xff0c 用户提交内容以后 xff0c 系统任停留在当前页面上 xff0c 直到服务返回处理成功或者失败的提示 而用户录入的信息 xff0c 除非程序清除 xff0c 否则不会自动消失 xff0c 方便用户修改 为了解决这
  • FreeRTOS Queue

    变量定义 span class token keyword typedef span span class token keyword void span span class token operator span QueueHandle
  • 专门讲解无人机航拍图像处理的书【包括图像拼接!!!】

    最近正式开始做课设啦 xff0c 博主在网上搜集到有专门的书讲解无人机航拍图像的处理 xff0c 包括图像拼接 xff01 xff01 xff01 更非常激动的是博主在图书馆把两本书都找到了 xff0c 俺滴学校i了i了 两本书如下所示 x
  • 1.2 向量与线性代数

    向量与线性代数 图形学基础向量向量点乘向量叉乘矩阵 图形学基础 基础数学 xff1a 线性代数 统计学 微积分基础物理 xff1a 其他课程 xff1a 信号处理 数学分析一点点 xff1a 美学课程 向量 方向长度单位向量向量加法 向量点
  • 2.1 变换

    矩阵变换 二维变换齐次坐标齐次坐标下的二维变换矩阵逆变换 xff08 逆矩阵 xff09 复合变换三维空间仿射变换 modeling and viewing 模型变换和视角变换 二维变换 尺度变换 Scale 镜像变换 切变变换 旋转变换
  • 2.2 变换(模型、视图、投影)

    变换 xff08 模型 视图 投影 xff09 三维变换观测变换 xff08 Viewing transformation xff09 视图 xff08 View xff09 定义相机如何将相机移动到约定俗成位置 投影 xff08 Proj
  • 四轴飞行器入门——基础知识

    引言 从2016年起 xff0c 细细数来入门无人机已经有两年时间 两年期间 xff0c 自己边学边摸索 xff0c 组装过机架四轴无人机 xff0c 也修改过开源飞控的代码 xff0c 但是因为种种原因 xff0c 始终没有写过相关博客记
  • Linux系统下搭建PX4/Pixhawk原生固件编译环境

    简介 PX4固件是Pixhawk飞行控制器的官方固件 xff0c Pixhawk官网也给出了Linux windows下搭建开发环境的方法 由于种种原因 xff0c 搭建开发环境时总会遇到各种各样的bug xff0c 致使PX4固件编译失败
  • main(int argc, char *argv[])

    这是UNIX和Linux中的标准主函数 argc 用来统计运行时发送给main函数的命令行参数的个数 argv 其中每个元素都是上述参数 以字符串形式存储 的首地址 argv 0 指向程序运行的全路径名 argv 1 指向程序名后的第一个参
  • 为PX4添加串口通讯模块(模块结构)

    主要讲模块的结构 不贴代码 从最外层开始 执行read uart main start dev ttyS1 read uart main int argc char argv 入口函数 判断任务进程read uart task是否存在 根据

随机推荐

  • C++抽象基类与虚基类(C++ primer)

    c 43 43 primer plus P508 xff0c 抽象基类 c 43 43 primer plus P556 xff0c 虚基类 抽象基类 xff08 abstract base class xff0c ABC xff09 抽象
  • MFC学习笔记(二)处理命令行选项

    目标 让应用程序处理这里所见的命令行标志 gt XXX exe c d 策略 一个MFC应用程序可以用CCommandLineInfo类的成员函数ParseParam 处理一些标准标 志 要添加我们自己的标志 xff0c 而仍然能够支持另外
  • C++ expection异常类、捕获所有异常(C++ primer,P639)

    expection类 头文件 lt expection gt stdexcept类 C 43 43 primer plus xff0c P632 包含以下异常 xff1a domain errorinvalid argumentlength
  • 5.1 运输层协议

    运输层协议 运输层的复用与常见端口常用端口 UDP协议特点UDP帧格式 TCP协议特点socket套接字可靠传输工作原理TCP帧首部重要字段 TCP可靠传输以字节为单位的滑动窗口选择超时重传时间选择确认SACK xff08 未经常使用P22
  • Linux上VScode + cmake + gcc开发环境搭建

    VScode 43 cmake 43 gcc 下载 安装vscode安装插件cmake文件结构vscode修改json文件编译 调试的过程 下载 安装 span class token comment cmake gcc 安装都很简单 sp
  • 软件测试面试04:实战项目介绍

    4 1 简单介绍下最近做过的项目 根据自己的项目整理完成 xff0c 要点 xff1a 1 xff09 项目背景 业务 需求 核心业务的流程 2 xff09 项目架构 xff0c B S还是C 5 xff0c 数据库用的什么 中间件用的什么
  • 一张图搞定SDF的概念

    本文仅代表个人理解 xff0c 谬误之处请指正 SDF Signed Distance Field 译为有向距离场 xff0c 有向 距离 场 这三个词非常精确的描述了 sdf 究竟是个什么东西 GPU Gems 3 中是这么描述 sdf
  • Ubuntu Windows双系统切换最简方法!!!

    安装完Ubuntu windows双系统后的第一个问题 xff1a 该怎么在两个系统间快速自由切换呢 xff1f 本文给出两种无需命令行的实用易上手方式 一 什么 xff0c 你要快快快快速切换 xff1f 这里直接给出答案 xff0c F
  • C++primer(第五版)习题答案

    前两章习题较简单 xff0c 这里就不作整理了 xff0c 直接从第三章开始 持续更新 xff1a Chapter 3 Strings Vectors and Arrays Exercise 3 1 part 1 include lt io
  • PX4源码地址和wiki

    源码 https github com 987419640 Firmware wiki https dev px4 io v1 9 0 zh concept architecture html
  • 视觉十四讲:第七讲_2D-2D:对极几何估计姿态

    1 对极几何 从2张图片中 得到若干个配对好的2d特征点 就可以运用对极几何来恢复出两帧之间的运动 设P的空间坐标为 P 61 X Y Z T 两个像素点 p 1 p 2 的像素坐标为 s 1 p 1 61 KP s 2 p 2 61 K
  • VINS_FUSION入门系列---GPS与VIO融合

    参考的博客 https blog csdn net subiluo article details 105429471 http www luyixian cn news show 313718 aspx state 状态量 位姿 速度 b
  • 几种常用加壳软件图文详解

    为了保护自己的软件不轻易被他人 借鉴 xff0c 有必要对软件进行一些加密保护 xff0c 而这方面目前己有成熟的专业加密软件可选择 但不要太依赖壳的保护 xff0c 大多数壳是可以被攻破的 xff0c 还是在自身保护上下些功夫 加密软件比
  • debian添加source源后update出现GPG错误

    错误如下 xff1a W GPG error http mirrors 163 com debian buster updates InRelease The following signatures couldn 39 t be veri
  • windows clang 编译Qt

    准备 xff1a qt everywhere src 5 15 0 zip jom 1 1 3 zip LLVM 10 0 0 win64 exe VS2019 xff1a 需要安装win10 SDK xff0c 也有自带的clang xf
  • docker 最新Dockerfile命令手册

    Dockerfile Reference Docker can build images automatically by reading the instructions from a Dockerfile A Dockerfile is
  • 单片机移植 - RTOS总结 -uC/OS-II ; FreeRTOS的区别

    RTOS总结 uC OS II FreeRTOS的区别 实时操作 xff08 RTOS xff09 系统有很多种 xff0c 分别为 Clinux C OS II eCos FreeRTOS mbed OS RTX Vxworks QNX
  • CentOs Stream脚本安装单机版Kubernetes并配置Calico和NFS

    随着Kubernetes和CentOs的不断升级 xff0c 在安装Kubernetes时 xff0c 网上其他的一些参考资料可能会遇到一些问题 本文以脚本方式列出了所有步骤 xff0c 这些步骤对于一台纯净的CentOs Stream服务
  • java基础必备丨阿里云kubernetes集群部署

    1 创建的前提 开通资源编排服务ROS 因为阿里云的k8s集群依赖于ROS的资源编排 xff0c 所以 xff0c 要先开通ROS才可以创建k8s集群开通弹性伸缩服务ESS开通访问控制服务RAM 2 创建说明 每个账号创建的云资源是由于配额
  • 从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick

    系列文章目录 Github开源地址 从头开始写STM32F103C8T6驱动库 xff08 一 xff09 STM32CubeMX创建并调整工程结构 从头开始写STM32F103C8T6驱动库 xff08 二 xff09 编写系统初始化程序