当前位置: 首页 > article >正文

STM32——系统滴答定时器(SysTick寄存器详解)

文章目录

    • 1.SysTick简介
    • 2.工作原理
    • 3.SysTick寄存器
    • 4.代码延时逻辑
    • 5.附上整体代码
    • 6.一些重要解释

1.SysTick简介

Cortex-M处理器内集成了一个小型的名为SysTick(系统节拍)的定时器,它属于NVIC的一部分,且可以产生 SysTick异常(异常类型#15)。SysTick为简单的向下计数的24位计数器,可以使用处理器时钟或外部参考时钟(通常是片上时钟源)。

2.工作原理

SysTick定时器的工作原理非常简单。它有一个内置的计数器,计数器从一个初始值开始递减,当计数器的值达到零时,它会触发一个中断并重新加载初始值。SysTick定时器一般会与系统时钟频率(通常是CPU时钟)同步工作,可以用来创建精确的时间延迟。
在这里插入图片描述

主要特性
定时器计数:SysTick定时器的计数器在每个时钟周期递减,直到它的值为零时会触发一个中断。
中断功能:当计数器到达零时,SysTick会触发一个中断,通常用于处理系统的定时任务(如操作系统的时钟中断)。
自动重载:SysTick有一个自动重载功能,计数器会从预定的值重新加载并继续计数。
可配置的时钟源:SysTick可以选择不同的时钟源,通常选择处理器的系统时钟,或者是外部的低速时钟源

3.SysTick寄存器

在这里插入图片描述

4.代码延时逻辑

  1. 选择时钟源
    在这里插入图片描述
    根据CTRL寄存器的第2位和第0位,来选择时钟源和是否使能定时器
    其中位0的意思是:位0=0 失能 关闭定时器
    位0=1 使能 开启定时器
SysTuck->CTRL&=(1<<2);//第二位为1.选择高速内部时钟
  1. 关闭计数器
SysTuck->CTRL&=~(1<<0);//第0 位为0,关闭定时器
  1. delay_us(num)
    在这里插入图片描述
    定时器计数为0时候,重装载值为倍乘数系统时钟,我这里用的F4,系统分频的是21Mhz,那么应该是211/21Mhz,
    周期=1/频率=1/168000000约等于0.00592us;这是系统时钟的周期,
    最大延时取决于分频的频率
    分频的频率为21Mhz,1个周期的时间为1/21000000s,大概为1/21us,所以倍乘数应该是21.
    在这里插入图片描述
    写入任何值将清零当前数值
SysTick->LOAD=num*value_us;//设置重装在制,其中num是系统时钟的频率,value_us是倍乘数,若num=42Mhz,则value_us=421,21Mhz,value_us=21,8M则value_us=8,原因看标签5的解释
SysTick->VAL=0;//计数器当前值清零
SysTuck->CTRL|=(1<<0);//第0 位为0,关闭定时器
  1. 等待计数完毕
    判断CTRL寄存器的第16位是否为1–》计数到0
    CTRL=1 &(1<<16)=1 while (!1)
    CTRL=0 &(1<<16)=0 while(!0)
while(!(SysTick->CTRL(&1<<16)))
  1. 清空当前值
SysTick->VAL=0;
  1. 关闭计数器
SysTuck->CTRL&=~(1<<0);//第0 位为0,关闭定时器

5.附上整体代码

//仿原子延时,不进入systic中断
void delay_us(u32 nus)
{
 u32 temp;
 SysTick->LOAD = 21*nus;
 SysTick->VAL=0;//计数器当前值清零
 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达while(!(SysTick->CTRL(&1<<16)))
     SysTuck->CTRL&=~(1<<0);//第0 位为0,关闭定时器
     SysTick->VAL=0;//计数器当前值清零
}
void delay_ms(u16 nms)
{
 u32 temp;
 SysTick->LOAD = 21000*nms;
 SysTick->VAL=0;//计数器当前值清零
 SysTuck->CTRL&=~(1<<0);//第0 位为0,关闭定时器
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
   SysTuck->CTRL&=~(1<<0);//第0 位为0,关闭定时器
   SysTick->VAL=0;//计数器当前值清零
}

借鉴链接https://blog.csdn.net/weibo1230123/article/details/81136564?spm=1001.2014.3001.5506
以及还有一个之前的找不到了。。。

6.一些重要解释

  1. 为什么频率是21M时候,value_us=21,才是1us
    因为当时钟源选择21M的时候,1s时间计数为21M次
    T=1/f(时间是频率的倒数)
    当21M时,计数1次所产生的时间为1/21000000s,是1/21000ms,1/21us,所以*21是1us

  2. 最大延时
    当最大延时为21M时,24位计数器最大值为16777215
    16777215/21=798915us=798.915ms。

由上两点可以计算出若外部时钟源选择是8M时,则value_us=8,valua_ms=8000,最大延时为167.77215/8=2097152us=2097.152ms

  1. HAL_Init()会提前配置好HAL_delay的参数
    ①FLASH读取指令缓存、数据缓存
    ②设置中断组优先级
    ③设置SysTick作为基准时间源、配置1ms tick,复位后默认时钟源为HSI(内部高速时钟源)
    ④初始化底层硬件
    附上原始HAL_Init()函数源码,可看可不看
HAL_StatusTypeDef HAL_Init(void)
{
  /* Configure Flash prefetch, Instruction cache, Data cache */ 
#if (INSTRUCTION_CACHE_ENABLE != 0)
   __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */

#if (DATA_CACHE_ENABLE != 0)
   __HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */

#if (PREFETCH_ENABLE != 0)
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//中断优先级分组4

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);
  
  /* Init the low level hardware */
  HAL_MspInit();
  
  /* Return function status */
  return HAL_OK;
}

以上资料部分来自于《清华开发者书库 ARM Cortex-M3与Cortex-M4权威指南 (Joseph Yiu、吴常玉、曹孟娟、王丽红。) (Z-Library)》
书籍已上传到博客


http://www.kler.cn/a/472088.html

相关文章:

  • Go语言性能优化-字符串格式化优化
  • Java-数据结构-顺序表(ArrayList)
  • 2025 年热门AI 应用——AI 编程会如何发展?
  • SSH(Secure Shell) 网络协议
  • 望获实时Linux系统与大语言模型深度融合,开创实时智能无限可能!
  • Unreal Engine 5 C++ Advanced Action RPG 五章笔记
  • Python爬虫与1688图片搜索API接口:深度解析与显著收益
  • NodeLocal DNS 全攻略:从原理到应用实践
  • 【HTML】Day02
  • 从零手写实现redis(四)添加监听器
  • 30天开发操作系统 第 12 天 -- 定时器
  • 深入 Solana 共识 - 从分叉到最终确定性
  • WebSocket 实战案例:从设计到部署
  • 非一般的小数:小数的概念新解、小数分类、浮点数的存储
  • 【年前假期学SHU分享】:计算机生物学、智能计算、通信、大数据、电子信息工程
  • GRU-PFG:利用图神经网络从股票因子中提取股票间相关性
  • linux环境搭建redis cluster集群
  • 探索Whisper:从原理到实际应用的解析
  • 【Linux系列】并发与顺序执行:在 Linux 脚本中的应用与选择
  • C语言 扫雷程序设计