STM32中SysTick系统滴答定时器用于延时功能的实现及说明

目录

STM32中SysTick系统滴答定时器用于延时功能的实现及说明

delay.h文件

delay.c文件


STM32中SysTick系统滴答定时器用于延时功能的实现及说明

复制代码
    在进行stm32开发的过程中,我们可能会使用到系统滴答定时器SysTick进行延时。系统滴答定时器是一个24位的向下倒计时的定时器。它主要有四个寄存器:重装载值寄存器LOAD、当前值寄存器VAL、控制寄存器CTRL和校准寄存器CALIB(校准寄存器一般不使用)。
    以下是系统滴答定时器用于延时操作的相关代码实现及说明。(这里只是在没有操作系统OS的驱动代码中使用,在有操作系统OS的代码中,SysTick系统滴答定时器可能作为操作系统的时基时钟使用。并且操作系统OS往往已经提供了相关的延时函数,直接调用操作系统提供的函数即可)

delay.h文件

复制代码
#ifndef __DELAY_H
#define __DELAY_H
​
void delay_init(void);
void delay_ms(u16 ms);
void delay_us(u32 us);
​
#endif

=================================分割线================================

delay.c文件

复制代码
#include "delay.h" 
​
static u8 fac_us = 0;       //微秒级延时系数              
static u16 fac_ms = 0;      //毫秒级延时系数
           
//初始化延迟函数
void delay_init()
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);   //使用外部时钟 
    fac_us = SystemCoreClock / 8000000;                     //微秒对应的tick数  
    fac_ms = (u16)fac_us * 1000;                            //毫秒对应的tick数   
}
说明:
    对于F103系列芯片来说系统时钟为72MHz,而滴答定时器的时钟为HCLK的8分频,即是9MHz。
    那么可以知道滴答定时器的计数器每减9次,时间为1微秒。每减9000次时间为1毫秒。
    (1MHz的时钟频率计数器每加1或者减1的时间为1us)
    因此微秒系数fac_us = 9,fac_ms = 9000。
​
//微秒级延时函数              
void delay_us(u32 us)
{       
    u32 temp;            
    SysTick->LOAD = us * 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;                                //清除COUNTFLAG计时完成标志位     
}
说明:
    对于系统滴答定时器的使用一般为以下步骤:
    1、将重装载值赋给LOAD寄存器,对于微秒延时重装载值就是延时系数乘以延时时间
    2、将当前值寄存器VAL清零
    3、启动定时器进行计时
    4、等待计时时间到关闭定时器
    5、清除计时完成的标志位COUNTFLAG
    关于清除COUNTFLAG标志位,可以等计时完成后直接读取控制寄存器CTRL的第16位进行清除;
    也可以通过写当前值寄存器VAL来进行清除。
    do
    {
        temp = SysTick->CTRL;
    }while((temp & 0x01) && !(temp & (1<<16))); 
    这个语句中(temp & 0x01)首先确保定时器是处于打开状态。
    (temp & (1<<16)用来判断标志位COUNTFLAG是否为1,当计时时间到后标志位COUNTFLAG会自动置1。
    由于这里是do--while循环,因此当计时时间未到时,标志位COUNTFLAG一直为0,也即是(temp & (1<<16)
    为0,取反后为1表示真,以上条件都成立,则继续执行do语句里的内容(继续查询COUNTFLAG标志位的状态)。
                                                     
//毫秒级延时函数   
void delay_ms(u16 ms)
{                 
    u32 temp;          
    SysTick->LOAD = (u32)ms * fac_ms;               //时间加载
    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;                            //清除COUNTFLAG计时完成标志位        
} 
注意:
    由于滴答定时器的重装载值寄存器LOAD和当前值寄存器都是24位的,因此延时的时间是有上限的。
    最大延时时间为2^24 - 1 = 16777215,对于微秒级延时每减9次为1us,因此最大延时时长为:
    16777215 / 9 ---1864135us = 1864.135ms = 1.864s。
    在使用滴答定时器进行延时时不能超过以上的最大延时时间。
相关推荐
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
追梦少年时6 小时前
STM32-Flash闪存
stm32·单片机·嵌入式硬件·51单片机
ChoSeitaku6 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
DdddJMs__1356 小时前
C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
c语言·leetcode·题解
weixin_452600697 小时前
《青牛科技 GC6125:驱动芯片中的璀璨之星,点亮 IPcamera 和云台控制(替代 BU24025/ROHM)》
人工智能·科技·单片机·嵌入式硬件·新能源充电桩·智能充电枪
娃娃丢没有坏心思7 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
ahadee8 小时前
蓝桥杯每日真题 - 第11天
c语言·vscode·算法·蓝桥杯
weixin_452600698 小时前
【青牛科技】14W 高保真音频放大电路——D2030
科技·单片机·嵌入式硬件·音视频·电动工具·智能电表
No0d1es9 小时前
2024年9月青少年软件编程(C语言/C++)等级考试试卷(九级)
c语言·数据结构·c++·算法·青少年编程·电子学会