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 - 1NVIC_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; }
}

STM32的定时器详解(嵌入式学习)相关推荐

  1. STM32基础定时器详解

    目录 01.定时器介绍 02.时钟源 03.时基单元 04.计数模式 4.1.向上计数模式 4.2.向下计数模式 4.3.中央对齐(向上/向下计数模式) 05.基础定时代码 定时器最基本的功能就是定时 ...

  2. STM32之定时器详解

    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 出去看门狗定时器和系统滴答定时器的八个定时器列表; 8个 ...

  3. STM32 定时器详解

    STM32 定时器详解 吃了一个猛亏,自己理解花了大半天时间,结果一看代码发现巨简单 算了,把自己理解的放上来吧 目录 STM32 定时器详解 前言 一.定时器种类和区分 二.时钟源 三.计数过程 3 ...

  4. STM32蜂鸣器实例详解

    //======================================================// **基于STM32的蜂鸣器实例详解 //===================== ...

  5. STM32 CAN通信协议详解—小白入门(二)

    文章目录 (一)CAN通信协议简介 (二)CAN物理层 2.1.闭环总线网络2.2.开环总线网络2.3.通信节点2.4.差分信号2.5.CAN协议的差分信号 (三)协议层 3.1.CAN的波特率及位同 ...

  6. STM32串口通信详解以及通信异常或者卡死常见问题分析

    STM32串口通信详解以及通信异常或者卡死常见问题分析 目录 STM32串口通信详解以及通信异常或者卡死常见问题分析 一.常见的异常问题 二.STM32的串口简介 1.串口的通讯方式 ①按数据传输方向 ...

  7. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  8. 斯坦福CS231n 2017最新课程:李飞飞详解深度学习的框架实现与对比

     斯坦福CS231n 2017最新课程:李飞飞详解深度学习的框架实现与对比 By ZhuZhiboSmith2017年6月19日 13:37 斯坦福大学的课程 CS231n (Convolutio ...

  9. 【阿里云课程】详解深度学习优化:泛化与正则化,学习率与最优化

    大家好,继续更新有三AI与阿里天池联合推出的深度学习系列课程,本次更新内容为第6课中两节,介绍如下: 第1节:泛化与正则化 第1节课内容为:泛化与正则化,讲述泛化的概念与重要性,各种正则化方法,包括显 ...

最新文章

  1. GridView自定义分页导航
  2. Win7搭建Telnet服务器 解决Access Denied: Specified user is not is not a member of TelnetClients group
  3. 程序员面试题精选100题(51)-顺时针打印矩阵[算法]
  4. 逍遥法外第一季/全集How To Get Away With Murder迅雷下载
  5. Direct2D (3) : 使用浮点参数绘制基本图形
  6. Python 爬虫进阶一之爬虫框架概述
  7. 新炬首架梁铭图:从70万字SRE神作提炼出7千字精华与君共勉
  8. zabbix 通过import批量导入新增主机和批量删除旧的主机
  9. Json Formatter 1.0 Json格式化工具
  10. nginx强制下载txt等文件
  11. unity算法面试_Unity面试准备
  12. Hibernate框架搭建
  13. 澳大利亚麦考瑞大学计算机系杨坚教授团队招收2022-2023年博士研究生
  14. React Fullpage
  15. python get pip.py_get-pip.py 安装
  16. 指纹特征提取及描述(附Python代码)
  17. 安装最新版本zlib
  18. iPad最值得期待的切实改进构想
  19. 【5G RLC】AM模式的数据传输详解
  20. 地理坐标系,投影坐标系区别

热门文章

  1. 链中链?造成3CX 软件供应链事件的是另外一起供应链事件?
  2. [摘录]quarts :overview
  3. java springboot整合zookeeper入门教程(增删改查)
  4. text无法使用空格 unity_Unity-Text空格造成自动换行+自定义Text
  5. 苦难是一种经历,回头看看,煎熬过后发现这也许是一种财富!
  6. 标题 标题 标题 标题
  7. css设置利用伪元素设置三角形
  8. 程序的链接与装入过程
  9. MySQL-关系代数运算
  10. HoloLens 开发总结