STM32之SysTick

1. SysTick介绍

1.1 什么是SysTick

• SysTick,既滴答定时器 ,是内核 中的一个特殊定时器,用于提供系统级的定时服务 。该定时器是一个24 位的递减计数器,具有自动重装载值的功能。当计数器到达自动重装载值的时候,它会自动重新加载并开始新的计数周期。

• SysTick定时器的主要功能包括实现简单的延时 ,生成定时中断以及进行精准定时和周期定时 等。此外,SysTick定时器还可以被用作其他目的,例如,作为操作系统的时基 ( 如FreeRTOS),软件看门狗等系统调度操作,在STM32中SysTick通常以HCLK(APB 时钟 ) 或者 HCLK/8作为运行时钟。

1.2 SysTick工作原理

• 在使用Systick定时器进行延时操作时,可以设定初值并使能滴答定时器后,每经过一个系统时钟周期 ,计数值就减1。当计数到0时,Systick计数器会自动重装初值并继续计数,同时内部的COUNTFLAG标志会置位,触发中断(如果中断使能)。这样,可以在中断处理函数中实现特定的延时逻辑。

2. SysTick寄存器

2.1 SysTick控制及状态寄存器(CTRL)

• 这个寄存器主要用于使能时钟和中断,选择时钟来源,以及提供定时器当前状态查询功能(COUNTFLAG)。

• 控制位有COUNTFLAG,CLKSOURCE,TICKINT,ENABLE等。

2.2 SysTick重装载值寄存器(LOAD)

• 这个寄存器主要用于设置SysTick定时器的重装载值,即定时器计数值的初始化

• 当计数器递减到0的时候,如果使能自动重装载值的功能,则计数器的值会被自动设置成这个寄存器的值,从而进行下一个计数周期。

• 控制位有RELOAD,如图:

2.3 SysTick当前数值寄存器(VAL)

• 这个寄存器的主要作用是读取或者写入 SysTick 定时器的值。

• 当读取的时候,返回当前计数器的剩余值,当写入时,则清零计数器的值,并且还会清除CTRL寄存器里面COUNTFLAG标志。

• 控制位是CURRENT,如图:

3. 手写延时函数

• 在delay.c文件中,只要会了us级别延时,后面的ms和s级延时,按照单位换算就行了,HAL库已经有了HAL_Delay这个延时函数,为什么还要重写一个?因为HAL库这个只能提供ms级别的延时,而重写这个能提供us级别延时。

cpp 复制代码
void delay_us(uint32_t nus)
{
    uint32_t temp;
    SysTick->LOAD = 72 * nus;                           /* 设置定时器重装值 */
    SysTick->VAL = 0x00;                                /* 清空当前计数值 */
    SysTick->CTRL |= 1 << 2;                            /* 设置分频系数为1分频 */
    SysTick->CTRL |= 1 << 0;                            /* 启动定时器 */
    do
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16)));     /* 等待计数到0 */
    SysTick->CTRL &= ~(1 << 0);                         /* 关闭定时器 */
}

4. 手写带操作系统延时函数,上述已经有了一个us级别延时,为什么还要写带操作系统的延时,因为上述的延时是需要频繁打开关闭计数器

4.1 具体流程,如下图:

4.2 代码

cpp 复制代码
/*void delay_us(uint32_t nus){//这个不用关闭计数器,
    uint32_t ticks = nus * 72;//一共要计的多少个数
    uint32_t tcnt = 0;//已经计了多少个数
    uint32_t told = SysTick->VAL;    //上次循环VAL的值
    uint32_t tnow = SysTick->VAL;//当前VAL的值
    while(1){//递减计数器
        tnow = SysTick->VAL;//获得当前VAL值
        if(tnow != told){
           if(tnow < told){
              tcnt += (told - tnow);
           }else {
              tcnt += SysTick->LOAD - (tnow - told);
           }
        }
        told = tnow;
        if(tcnt >= ticks){
            break;
        }
    }

}*/

void delay_us(uint32_t nus){//所有的配置都在HAL_InitTick这里配置好了
    uint32_t ticks = nus * 72;//一共要计的多少个数
    uint32_t tcnt = 0;//已经计了多少个数
    uint32_t told = SysTick->VAL;    //上次循环VAL的值
    uint32_t tnow ;//当前VAL的值
    uint32_t reload = SysTick->LOAD;//重装载值
    while(1){
        tnow = SysTick->VAL;//获得当前VAL值
        if(tnow != told){
           if(tnow < told){
              tcnt += (told - tnow);
           }else {
              tcnt += reload - (tnow - told);
           }
           
           told = tnow;
           if(tcnt >= ticks){
                 break;
           }   
        }
        
    }

}
相关推荐
不悔哥4 天前
开源OV-Watch:怎么做一个智能手表
单片机·开源·嵌入式
XiHongShi20164 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
优信电子4 天前
AIT1001 非接触式红外测温模块 STM32 驱动开发实战:从引脚到代码全解析
stm32·嵌入式·温度传感器·红外测温·非接触式测温·ait1001
深圳老胡4 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
wuyk5554 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
女神下凡4 天前
嵌入式设计的各种存储芯片的硬件/软件设计规范,非常全面。
arm开发·单片机·嵌入式硬件
梅梅9664 天前
一款mipi转lvds的lcd调试(LT8912B)
单片机·计算机外设·电脑·显示器·pd芯片
开发笔记-阿牛4 天前
蓝牙音乐灯拆解,又一次拆到蓝牙音乐灯芯片CK6865L
人工智能·单片机·嵌入式硬件·音视频·音频
从零开始的嵌入式之旅5 天前
day47
arm开发·经验分享·笔记·嵌入式硬件
恒锐丰科技林技术员5 天前
EG1164 高压大电流升压同步整流芯片解析
经验分享·嵌入式硬件·硬件工程