STM32的定时器详解(嵌入式学习)

news2024/11/23 21:33:14

STM32的定时器详解

  • 0. 前言
  • 1. Systick定时器
    • 概念
    • 工作原理
    • 时钟基准
    • Systick练习
  • 2. HAL_Delay函数分析
  • 3. 定时器
    • 基本概念
    • 定时器分类
    • 定时器组成
      • 计数器
      • 自动重装寄存器
      • 预分频器
    • 定时器计数原理
    • 定时器练习
  • 4. 软件定时器
    • 概念
    • 设计思想
    • 代码

0. 前言

想要了解STM32的时钟系统
点击这里跳转——》STM32的时钟系统(嵌入式学习)

建议先看看时钟树如何配置
点击这里跳转——》STM32的时钟树配置(嵌入式学习)

跳转——》STM32的时钟基础详解(嵌入式学习)
跳跳转——》STM32的时钟源详解(嵌入式学习)

1. Systick定时器

概念

SysTick又称滴答定时器。是一个定时设备,位于Cortex-M0内核中,和NVIC捆绑,产生SysTick异常(IRQ异常号15)可以对输入的时钟进行计数,系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。

在这里插入图片描述

Systick定时器是一种内置的定时器,通常用于实时操作系统(RTOS)或其他需要精确定时的应用中。它在大多数STM32微控制器中都有提供。

Systick定时器的主要特点如下:

  1. 基于计数器:Systick定时器基于一个32位的自动递减计数器。计数器从一个初始值开始递减,当计数器的值减至零时,会产生一个中断或触发一个事件。

  2. 系统时钟驱动:Systick定时器的时钟源通常是系统时钟(SYSCLK)。这使得它能够提供与系统时钟相关的精确定时功能。

  3. 配置灵活:Systick定时器可以通过寄存器进行灵活的配置。你可以设置计数器的初始值、使能或禁用定时器、选择中断触发或事件触发等。

  4. 中断或事件触发:当计数器减至零时,可以选择触发一个中断或一个事件。中断触发可以用于在特定时间间隔内执行一些任务,而事件触发可以用于与其他外设或模块进行同步。

  5. 时间精度:Systick定时器的时间精度取决于它的时钟源和计数器的位数。通常情况下,它可以提供微秒级别的定时精度。

Systick定时器常用于实现延时函数、系统时钟节拍、定时任务调度等功能。在实时操作系统中,它通常用作系统的节拍定时器,用于调度任务的执行。

要使用Systick定时器,你需要在代码中进行相应的配置和中断处理程序编写。具体的配置和使用方法可以参考相应的微控制器参考手册和编程手册,以及相关的开发工具(如STM32Cube库和HAL库)的文档和示例代码。

工作原理

滴答定时器是一个24位递减定时器,也就是最多能计数2^24(0xFFFFFF)。
SysTick设定初值并使能后,每来一个时钟信号,计数值就减1。
计数到0时,触发中断,SysTick计数器自动重装初值并继续减一,循环不断。
系统默认开启滴答定时器。

Systick定时器是一种基于计数器的定时器,在STM32微控制器中,它的工作原理如下:

  1. 时钟源选择:Systick定时器的时钟源通常是系统时钟(SYSCLK)。系统时钟通常由外部晶体振荡器或内部RC振荡器提供,并通过时钟树的配置确定其频率。

  2. 计数器配置:Systick定时器使用一个32位的自动递减计数器进行计时。在初始化时,需要设置计数器的初始值,这决定了定时器开始计数的起点。

  3. 计数器递减:Systick定时器的计数器从初始值开始递减,每个时钟周期减少一个计数值,直到计数器减至零。

  4. 中断或事件触发:当计数器减至零时,可以选择触发一个中断或一个事件。中断触发会生成一个中断请求,CPU会相应地跳转到Systick中断处理程序执行特定的操作。事件触发则可以与其他外设或模块进行同步操作。

  5. 中断处理程序:Systick定时器的中断处理程序是由开发者编写的一段代码,用于处理定时器中断触发时需要执行的任务。在中断处理程序中,可以执行特定的操作,例如更新系统节拍计数、调度任务、处理延时函数等。

  6. 重载计数器:当计数器减至零后,可以选择自动重载计数器的值。这允许定时器自动重新开始计数,以实现周期性的定时功能。

通过适当配置和使用Systick定时器,可以实现延时函数、系统时钟节拍、定时任务调度等应用。在实时操作系统中,Systick定时器通常用作系统的节拍定时器,用于精确调度任务的执行。

在编程时,你需要配置Systick定时器的相关寄存器,包括计数器的初始值、使能/禁用定时器、中断使能等。同时,需要编写中断处理程序,以响应Systick定时器中断触发时的操作。

请注意,Systick定时器的具体配置和使用方法可能因不同的STM32微控制器型号而有所差异。因此,在进行Systick定时器的配置和使用之前,建议参考所选微控制器的参考手册和编程手册,以获得准确的配置细节和操作说明。

时钟基准

首先看Systick每次触发异常在异常处理程序中做了哪些工作
在这里插入图片描述
在这里插入图片描述

每次systick触发中断后会让uwTick自加1
在这里插入图片描述

这个uwTick的值就作为系统的时钟基准。
然后再来研究一下,uwTick多久会被加1.
在main.c中main函数首个执行的函数HAL_Init(),会对systick进行初始化。
在这里插入图片描述
在HAL_Init中通过调用HAL_InitTick函数,对Tick进行初始化
在这里插入图片描述
传递参数为:
TICK_INT_PRIORITY = 0 作为systick的中断优先级
在这里插入图片描述
调用HAL_SYSTICK_Config函数用于配置systick时基
SystemCoreClock / (1000U /(uint32_t)uwTickFreq)
uint32_t SystemCoreClock = 16000000UL;
16000000 / 1000 / 1 = 16000
将16000作为参数传递给了HAL_SYSTICK_Config函数
在这里插入图片描述
Systic_Config函数对Systick的重装值、初值、优先级和校准值都进行了配置。
在这里插入图片描述

  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //如果systick初值大于最大值0xFFFFFF
  {
         return (1UL);        //返回1 说明配置失败                                        
  }
  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* 重载的计数值 */     16000 - 1
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                      
  return (0UL); 

在这里插入图片描述

SysTick->LOAD  = (uint32_t)(ticks - 1UL);  //即16000 - 1

从16000 - 1开始递减到0,总共需要计数16000次
当前时钟频率16Mhz,说明计一个数用时1/16M s
计16000个数需要用时 16000 * 1/16000000 s = 1/1000 s = 1ms
因此Systick每隔1ms会触发一次异常。

Systick练习

利用Systick异常,实现1秒打印“helloworld”
在这里插入图片描述

每次Systick触发异常时让flag自加1
在这里插入图片描述

在主函数中判断,当flag加到1000时,说明systick异常触发了1000次,此时刚好用时1s。打印“helloworld”
在这里插入图片描述

2. HAL_Delay函数分析

__weak void HAL_Delay(uint32_t Delay)
{
 	 uint32_t tickstart = HAL_GetTick();   //获取当前时间
  	 uint32_t wait = Delay;      //获取用户要延时的时间
        /* Add a freq to guarantee minimum wait */
 	 if (wait < HAL_MAX_DELAY)
       {
          wait += (uint32_t)(uwTickFreq);
        }
        while ((HAL_GetTick() - tickstart) < wait)
       {   //如果当前系统时间 - 初始时间 < 延时时间 则继续循环
           //当达到延时条件时,循环结束。
       }
}

在这里插入图片描述

GetTick函数返回当前系统uwTick的值
uwTick每个1ms会自加1
因此HAL_Delay的实现依靠Systick,以达到毫秒为单位的延时效果。

3. 定时器

基本概念

定时器本质上是一个计数器,可对输入的时钟进行计数,并在计数值达到设定值时触发中断,当这个计数器的输入是一个准确可靠的基准时钟时,对基准时钟计数的过程就是计时的过程。

定时器分类

定时器的基本结构是通用的,很多模块电路都能用到,所以STM32定时上扩展了非常多的功能,根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。
在这里插入图片描述
F103
在这里插入图片描述

F407
在这里插入图片描述

定时器组成

计数器

在这里插入图片描述
向上计数模式: 计数器从0开始计数,当达到自动装载寄存器(TIMx_ARR)里的值时,自动清零且产生一个溢出事件,然后再从0开始向上计数。
向下计数模式: 计数器从自动装载寄存器(TIMx_ARR)里的值开始递减计数,当计数值达到0时产生一个定时器溢出事件,并重装初值,继续向下计数。
中央对齐模式: 又称为向上/向下计数,计数器从0开始递增达到ARR的值,产生一个定时器溢出事件,再从ARR的值递减到0,产生一个定时器溢出事件。

自动重装寄存器

在这里插入图片描述

预分频器

在这里插入图片描述

定时器计数原理

时钟频率配置成了48Mhz,如何让定时器产生1s中断?
分频值写0相当于不分频 48/1 => 48
先对主频进行48分频得到1Mhz的频率,则分频值为48-1
48Mhz / 48 => 1Mhz
1Mhz的时钟频率,相当于计一个数需要1/1000000秒,
所以如果想得到1s中断,则需要从0开始计数到1000000-1,即计1000000个数需要1秒。

定时器练习

利用定时器中断实现1s打印一个“hellowolrd”

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在main.c中重写定时器溢出中断回调函数
在这里插入图片描述

启动定时器以中断模式计数
在这里插入图片描述

4. 软件定时器

概念

在STM32微控制器中,通常使用软件定时器来执行特定的定时任务。软件定时器是通过编程实现的,而不是通过硬件计时器。以下是一种实现软件定时器的方法:

  1. 初始化计时器参数:选择一个适当的定时器变量,例如一个32位的计数器变量,以便能够表示较长的时间。另外,设置一个定时器间隔,即希望定时器每隔多久触发一次。

  2. 计时器启动:在合适的时机,例如在系统初始化时或任务启动时,将计时器变量设置为0,并启动计时器。

  3. 定时器中断处理:在每次计时器溢出时,触发一个中断。在中断服务程序(ISR)中,将计时器变量递增,并检查是否已经达到预定的定时器间隔。

  4. 定时任务执行:如果达到了定时器间隔,执行所需的定时任务,然后重置计时器变量为0,以便下一次定时器中断时再次触发任务。

这是一个基本的软件定时器框架,可以根据具体的应用场景进行调整和扩展。需要注意的是,软件定时器是基于系统时钟的,因此在设计定时器间隔时,需要考虑系统时钟频率和定时器的精度。

设计思想

1)设计一个定时器(软件层次,结构体内含有开始的时间和想要延时的时间)
2)设置定时器时间 和 比较定时器是否到达 两个函数

代码

1)设计定时器(记录起始时间,记录用户延时时间)

typedef struct
{
    uint32_t  start; //保存起始时间
    uint32_t  delay; //保存延时时间
}MyTim;	

2)提供一个用于传递定时时间的软件定时器配置函数

//定时器初始化函数
void setTim(MyTim *timer,uint32_t delayms)
{
    timer->start = HAL_GetTick();  
    timer->delay = delayms;
}	

3)提供一个用于比对是否达到定时要求的函数

uint32_t compareTim(MyTim *timer)
{
	if(HAL_GetTick() - timer->start >= timer->delay)
	{
	    return 1; //返回1说明达到了定时要求	
	}else
	{
		return 0; 
	}
}	

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据分享】1929-2022年全球站点的逐日平均风速数据(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 对于具体到监测站点的气象数据&#xff0c;之前我们分享过1929-2022年全球气象…

考上了!成为图技术大师的第一步!

好消息&#xff01;&#xff01; 自创邻科技GBCA课程开设以来 截至6月20日 已有近20名学员通过考试 获得GBCA认证证书&#xff01; 距离成为图技术认证专家 跨出关键一步&#xff01; 前不久&#xff0c;创邻科技为了让更多图技术爱好者能够快速了解、上手图数据库&#xff0c…

【一些随笔】艰难存折,恨不睡觉:大话年轻人的钱包囧境与梦想退休

一些随笔 1️⃣ 存钱难吗&#xff1f;难&#xff01;它难在哪&#xff1f;2️⃣ 关于年轻人如何攒钱理财的一点建议3️⃣ 关于裸辞的一些经验及看法4️⃣ 谁又不想攒够钱了提前退休呢&#xff1f;但要存够多少呢&#xff1f; 1️⃣ 存钱难吗&#xff1f;难&#xff01;它难在哪…

【HISI IC萌新虚拟项目】ppu模块基于spyglass的lint清理环境搭建与lint清理

关于整个虚拟项目,请参考: 【HISI IC萌新虚拟项目】Package Process Unit项目全流程目录_尼德兰的喵的博客-CSDN博客 前言 RTL代码在交付给验证同时进行功能验证时,可以同步进行lint的清理工作。一般而言影响编译和仿真的问题会在vcs的error和warning中被修正,因此清理lin…

[RocketMQ] Broker启动流程源码解析 (二)

文章目录 1.Brocker介绍2.BrokerStartup启动入口3.createBrokerController创建BrokerController3.1 创建各种配置类3.2 创建broker控制器3.3 初始化broker控制器3.3.1 加载配置文件3.3.2 创建消息存储对象MessageStore3.3.3 Load加载恢复消息文件3.3.4 初始化Broker通信层3.3.5…

知道了,去卷后端 →「Nest.js 入门及实践」:)

为什么学习 Nest &#xff1f; 前端已 &#x1f648;&#xff0c;去卷后端 &#x1f412; → 广度和深度的问题&#xff0c;不可代替性仅前端开发的应用没有记忆&#xff0c;不能互联 &#x1f914; → 学习后端&#xff0c;为应用赋能同为 JS 语言&#xff0c;学习成本较小&a…

EALLOW和EDIS指令的使用

1.EALLOW与EDIS 汇编指令 #define EALLOW __asm("EALLOW") #define EDIS __asm("EDIS") #define ESTOP0 __asm("ESTOP0")EALLOW(Edit allow)&#xff1a;防止cpu错误地写保护&#xff0c;ST1状态寄存器的EALLOW位显示是否允许写&#xff0c;0…

手机蓝牙功能测试点大全,都帮你总结好了

蓝牙是现在智能设备上一个必不可少的模块&#xff0c;支持大容量的近距离无线通信&#xff0c;典型的传输距离是10米左右&#xff0c;通过增加发射功率可达到100米&#xff0c;支持多链接&#xff0c;安全性高。 蓝牙工作在2.4GHZ的 ISM频段上&#xff0c;采用跳频扩谱技术避免…

微信小程序开发公司,小程序接单

小程序开发接单&#xff0c;公司开发&#xff0c;售后有保障&#xff0c;专属售后群对接&#xff0c;1对1 服务&#xff0c;下面是一些常见的小程序&#xff0c;全行业小程序都可开发 1.商城小程序 商城小程序是一种集购物、支付、订单管理等多种功能于一体的应用程序。为了使…

【使用OpenFeign在微服务中进行服务间通信】—— 每天一点小知识

&#x1f4a7; 使用 O p e n F e i g n 在微服务中进行服务间通信 \color{#FF1493}{使用OpenFeign在微服务中进行服务间通信} 使用OpenFeign在微服务中进行服务间通信&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微…

Python | cx_Oracle | DPI-1047报错处理(Win\Mac\Linux)

文章目录 Python | cx_Oracle | DPI-1047报错处理&#xff08;Win\Mac\Linux)测试代码报错信息解决步骤 Python | cx_Oracle | DPI-1047报错处理&#xff08;Win\Mac\Linux) 测试代码 import cx_Oracle# 建立与 Oracle 数据库的连接 connection cx_Oracle.connect("{lo…

【Redux】redux的使用详解

Redux的使用详解 Redux的核心思想 理解纯函数 1. 为什么要使用redux JavaScript开发的应用程序&#xff0c;已经变得越来越复杂了&#xff1a; JavaScript需要 管理的状态越来越多&#xff0c;越来越复杂&#xff1b;这些状态包括&#xff1a;服务器返回的数据、缓存数据、用户…

精细运营、数据赋能、生态联动…银行大零售数字化转型攻略

当前我国银行业的内外部环境正在发生深刻的变化&#xff0c;数字化转型已经成为行业的普遍共识。尤其在银行大零售数字化转型的过程中&#xff0c;各家银行差异性较大&#xff0c;虽然都开始突破传统零售模式&#xff0c;但仍面临一些共性的挑战&#xff0c;比如缺乏科学的顶层…

Java设计模式——装饰者模式

装饰者模式 一、概述 装饰者模式&#xff08;装饰器模式&#xff09;是一种结构型模式 定义&#xff1a; 在不改变现有对象结构的情况下&#xff0c;动态地给该对象增加一些额外职责&#xff08;功能&#xff09;的模式。 装饰者&#xff08;Decorator&#xff09;模式中的…

8年测试老鸟整理,接口自动化测试mock总结,这些你会多少?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Mock原理/实现机制…

【youcans动手学模型】MobileNet 模型-CIFAR10图像分类

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【youcans动手学模型】MobileNet 模型-CIFAR10图像分类 1. MobileNet 卷积神经网络模型1.1 模型简介1.2 论文介绍 2. 在 PyTorch 中定义 MobileNet V1 模型类2.1 深度可分离卷积&#xff08;DSC&…

前端vue入门(纯代码)11

【11.全局事件总线(Global Event Bus)】 全局事件总线&#xff1a;实现任意组件间通信 【原理图】 结合上图&#xff0c;假若C组件想要传递数据给A组件&#xff0c;那么&#xff0c;就通过全局事件总线在A组件中绑定【$on】一个自定义事件demo&#xff0c;并界定一个参数来接…

如果我们20年后仍然在讨论Kubernetes,那将是技术上悲哀的时刻

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 Kelsey Hightower Google Cloud首席开发者 引子 在 Kubecon 上&#xff0c;Kelsey Hightower 曾经遇到过一个带有 Kubernetes 纹身的人&#xff0c;这让他开始…

工业相机的镜头如何选择?

相机的镜头如何计算&#xff0c;如果看公式的话&#xff0c;需要知道相机sensor的尺寸&#xff0c;相元的尺寸&#xff0c;计算起来数据也比较复杂&#xff0c;下面教大家一个简单的方法&#xff0c;就是如何借助镜头计算工具来使用。 巴斯勒相机的镜头选型地址 工业镜头选型…

我们该如何提升测试效率?

在大部分研发项目经理心中&#xff0c;进度往往会放在第一位&#xff0c;其次是成本&#xff0c;最后是质量&#xff0c;当然人员队伍最好也要稳定。天下武功&#xff0c;唯快不破&#xff1a;进度 > 成本 > 质量 > 人。 这个说法并不是绝对&#xff0c;今天我们并不是…