【杂谈】针对Cortex M4内核使用Systick进行延时

目录

一、简介

1.寄存器组成(4个关键寄存器)

2.时钟源配置

3.小结

二、示例程序


在ST的数据手册中无法找到与内核相关的详细内容,因为M4内核使用的是ARMv7-M指令集,通过ARM官网可以找到并下载内核架构的数据手册

一、简介

SysTick是ARM Cortex-M4内核内置的系统定时器,不属于外设定时器 ,而是内核的一部分。它是一个24位递减计数器,主要用于:

  • 提供操作系统的时钟节拍(如FreeRTOS的时间片调度)
  • 实现精确的延时函数
  • 作为简单的时间基准

1.寄存器组成(4个关键寄存器)

  1. CTRL - 控制和状态寄存器
  2. LOAD - 重装载值寄存器
  3. VAL - 当前值寄存器
  4. CALIB - 校准值寄存器

2.时钟源配置

在STM32F4中,SysTick的时钟源有两种选择:

复制代码
// 查看 SystemCoreClock 的值(通常为168MHz)
SystemCoreClock = 168000000;  // HCLK频率

// 选择时钟源
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;    // 使用HCLK
// 或
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;   // 使用HCLK/8

3.小结

特性 说明
位数 24位递减计数器
时钟源 AHB时钟 或 AHB/8(可配置)
中断能力 计数器到0时产生SysTick中断
自动重载 支持自动重载功能
精度 高精度,基于系统时钟(最大只能计时1ms)

二、示例程序

复制代码
#include "stm32f4xx.h"

// 定义微秒和毫秒延时的基础计数值
// 注意:这些值需要根据你的实际SysTick时钟频率进行计算和调整
static uint32_t fac_us = 168 - 1;    // 假设SysTick时钟为168MHz时,1us的计数值
static uint32_t fac_ms = 168000 - 1; // 1ms的计数值,注意防止溢出


void Delay_Init(void) 
{
  // SysTick时钟源通常默认是HCLK,这里不更改配置,如果需要配置为HCLK/8,可以取消下一行的注释
  // SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}


void Delay_us(uint32_t nus) 
{
    uint32_t temp;
    SysTick->LOAD = nus * fac_us;              // 设置重载值
    SysTick->VAL = 0x00;                       // 计数前先清空当前计数器
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;  // 使能SysTick,使用内核时钟,不开启中断 
                                               // SysTick_CTRL_ENABLE_Msk == 0x01

    do 
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16))); // 等待时间到达,并检查计数器是否仍使能

    SysTick->CTRL = 0x00; // 关闭计数器
    SysTick->VAL = 0x00;  // 清空计数器
}


void Delay_ms(uint32_t nms) 
{
    uint32_t temp;
    // 注意:nms * fac_ms 的值可能超过24位,实际使用中需确保重载值不超过0xFFFFFF
    SysTick->LOAD = nms * fac_ms;              // 设置重载值
    SysTick->VAL = 0x00;                       // 清空当前计数器
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;  // 使能SysTick,使用内核时钟,不开启中断
                                               // SysTick_CTRL_ENABLE_Msk == 0x01

    do 
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16))); // 等待时间到达

    SysTick->CTRL = 0x00; // 关闭计数器
    SysTick->VAL = 0x00;  // 清空计数器
}

其中

temp = Systick->CTRL,用temp检测Systick->CTRL寄存器

(temp & 0x01) 表示定时器仍在运行

!(temp & (1 << 16)) 表示COUNTFLAG位为0(时间未到)

相关推荐
zlinear数据采集卡13 分钟前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
ACP广源盛1392462567318 分钟前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
Rocktech_ruixun2 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
Lzh编程小栈3 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展
Rocktech_ruixun3 小时前
机器人数据采集能力取决于什么?瑞迅科技RK3588/3576核心板方案深度解析
人工智能·嵌入式硬件·机器人
水果里面有苹果3 小时前
28-DRV8825PWPR步进电机驱动器
单片机
恒锐丰科技韩生4 小时前
率能 SS6625E|3.0~20V 单通道 H 桥直流电机驱动 SOP8 电子锁玩具机器人分享
嵌入式硬件·硬件工程
zlinear数据采集卡4 小时前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Dr.kangder5 小时前
嵌入式面试总结(十八)——JTAG调试
嵌入式硬件·面试·职场和发展·架构·嵌入式
恒锐丰科技韩生6 小时前
率能 SS6226|2.4~7.2V 低压双通道双 H 桥电机驱动 SOP16 玩具小家电专用芯片
嵌入式硬件·硬件工程