STM32---基本定时器(含源码)小白可入

news2024/11/15 23:54:38

写在前面:定时器是STM32中一个十分重要的外设,并且在STM32中具有多个定时器。定时器的包括基本定时器、通用定时器以及高级控制定时器,这些定时器相关独立,不共享任何资源。当然,其难易程度也是逐渐增加的,我们当然是从简答的开始学习。本节就学习基本定时器。

一、定时器概述

1.1软件延时原理

        定时器的一个设计初衷就是为了延时,而我们前面学习过使用软件延时;例如下面这段代码:

void Delay1us()		//@11.0592MHz
{
	_nop_();
	_nop_();
	_nop_();
}

        其作用就是使晶振为11.0529Mhz的51单片机延时1微秒,它是如何进行延时的呢?是因为对于单片机来说,运行每一条程序都是需要一定的时间的,那么执行一定长度的没有实际作用的代码就能够延时CPU的一些时间,这就是软件延时的原理。

        但是这种延时方式具有一些缺点,最明显的就是:延时时间不准确以及CPU死等

1.2定时器定时原理

        使用精确的时基,通过硬件的方式,实现定时功能,其核心是:计数器。与前面学习的看门狗有一定的相似之处。

1.3定时器分类 

1.4STM32定时器特性

类型名称计数器类型预分频系数能否产生DMA请求功能区别
基本定时器

TIM6

TIM6

递增1-65536可以没有输出通道,常用作时基,即定时功能。
通用定时器

TIM2

TIM3

TIM4

TIM5

递增

递减

中央对齐

1-65536可以具有多路通路,可以用于输入捕获/输出比较,也可以做时基。
高级定时器

TIM1

TIM8

递增

递减

中央对齐

1-65536可以除了具备通用定时器所有功能外,还具备带死区控制的互补信号输出、刹车等功能。

二、基本定时器 

2.1基本定时器介绍

基本定时器:TIM6\TIM7;

特性:16位递增计数器,计数值:0-65535;

                 16位预分频系数,分频系数:1-65536;

可用于触发DAC,在更新时间下可产生中断/DMA;

2.2基本框图 

1、时钟源 

        定时器的核心在于计数,首先需要给一个时钟源。基本定时器的时钟挂载在APB1总线上,所以它的时钟来自于APB1总线,但是基本定时器时钟不是直接APB1总线直接提供,而是先经过一个倍频器,当 APB1 的预分频器系数为 1 时,这个倍频器系数为 1, 即定时器的时钟频率等于 APB1 总线时钟频率;当 APB1 的预分频器系数≥2 分频时,这个倍频器系数就为 2 , 即定时器 的 时钟频率等于APB1总线时钟频率的两倍 。APB1 总线的预分频器分频系数是 2,所以挂载在 APB1 总线的定时器时钟频率为 72Mhz。

2、控制器

        控制器除了控制定时器复位、使能、计数等功能之外,还可以用于触发 DAC 转换。

3、时基单元

        时基单元包括:计数器寄存器(TIMx_CNT)预分频器寄存器(TIMx_PSC)自动重载寄存器 (TIMx_ARR) 。基本定时器的这三个寄存器都是 16 位有效数字,即可设置值范围是 0~65535。

预分频器 PSC

        有一个输入和一个输出。输入CK_PSC来源于控制器部分,实际上就是来自于内部时钟(CK_INT),即 2 倍的 APB1 总线时钟频率(72MHz)。

        输出CK_CNT 是分频后的时钟,它是计数器实际的计数时钟,通过设置预分频器寄存器(TIMx_PSC)的值可以得到不同频率 CK_CNT。

                fCK_CNT= fCK_PSC / (PSC[15:0]+1)

其中,PSC[15:0]是写入预分频器寄存器的值。

自动重载寄存器(TIMx_ARR)

        自动重载寄存器的值是由用户自行定义的,它的值设定后,作为一个评判标准同CNT计数器的值进行比较,从而判断是否溢出,是否产生对应的响应。它是作为溢出条件的重要组成部分。

计数器寄存器(TIMx_CNT)

        基本定时器的计数器是一个递增的计数器,当寄存器(TIMx_CR1)的 CEN 位置 1,即使能定时器,每来一个 CK_CNT 脉冲,TIMx_CNT 的值就会递增加 1。当 TIMx_CNT 值 与 TIMx_ARR 的设定值相等时,TIMx_CNT 的值就会被自动清零并且会生成更新事件,然后下一个 CK_CNT 脉冲到来,TIMx_CNT 的值就会递增加 1,如此循环。在此过程中,TIMx_CNT 等于 TIMx_ARR(溢出条件) 时,我们称之为定时器溢出,因为是递增计数,故而又称为定时器上溢。定时器溢出就伴随着更新事件的发生。

影子寄存器

        在上述基本框图中,我们可以看见,在预分频器 PSC自动重载寄存器(TIMx_ARR)的背后各含有一个影子寄存器,影子寄存器是一个实际起作用的寄存器,不可直接访问。

        举个例子:我们可以把预分频系数写入预分频器寄存器(TIMx_PSC), 但是预分频器寄存器只是起到缓存数据的作用,只有等到更新事件发生时,预分频器寄存器的值才会被自动写入其影子寄存器中,这时才真正起作用。

更新事件

        更新事件的产生有两种情况,一是由软件产生,将 TIMx_EGR 寄存器的位 UG 置 1,产生更新事件后,硬件会自动将 UG 位清零。二是由硬件产生,满足以下条件即可: 计数器的值等于自动重装载寄存器影子寄存器的值。

2.3定时器计数模式

计数模式条件
递增CNT==ARR(影子)
递减CNT==0
中心对齐

CNT==ARR(影子)-1

CNT==1

三、定时器相关寄存器 

3.1控制寄存器 1(TIMx_CR1)

         该寄存器,我们需要注意的是:位 0(CEN)用于使能或者禁止计数器,该位置 1 计数器 开始工作,置 0 则停止。还有位 7(APRE)用于控制自动重载寄存器 ARR 是否具有缓冲作用, 如果 ARPE 位置 1,ARR 起缓冲作用,即只有在更新事件发生时才会把 ARR 的值写入其影子寄存器里;如果 ARPE 位置 0,那么修改自动重载寄存器的值时,该值会马上被写入其影子寄存器中,从而立即生效。

3.2中断使能寄存器(TIMx_DIER)

        该寄存器位 0(UIE)用于使能或者禁止更新中断,因为本实验我们用到中断,所以该位需要置 1。位 8(UDE)用于使能或者禁止更新 DMA 请求,我们暂且用不到,置 0 即可。

3.3状态寄存器(TIMx_SR)

         该寄存器位 0(UIF)是中断更新的标志位,当发生中断时由硬件置 1,然后就会执行中断服务函数,需要软件去清零,所以我们必须在中断服务函数里把该位清零。如果中断到来后,不把该位清零,那么系统就会一直进入中断服务函数,这显然不是我们想要的。

3.4计数器(TIMx_CNT)

用于设定计数器的值;

3.5预分频器(TIMx_PSC)

用于设定预分频器的值;

3.6自动重装载寄存器(TIMx_ARR)

用于设定自动重装载寄存器的值。

3.7定时器溢出时间计算

计算公式:

Tput=(ARR+1)*(PSC+1)/Ft

其中:Ft为时钟源频率;ARR为自动重装载值;PSC为预分频器值

例如:我们需要一个 500ms 周期的定时器更新中断,一般思路是先设置预分频寄存器,然后才是自动重载寄存器。考虑到我们设置的 CK_INT 为 72MHz,我们把预分频系数设置为 7200,即写入预分频寄存器的值为 7199,那么 fCK_CNT=72MHz/7200=10KHz。这 样就得到计数器的计数频率为 10KHz,即计数器 1 秒钟可以计 10000 个数。我们需要 500ms 的 中断周期,所以我们让计数器计数 5000 个数就能满足要求,即需要设置自动重载寄存器的值为 4999,另外还要把定时器更新中断使能位 UIE 置 1,CEN 位也要置 1。

四、实验配置步骤与相关库函数

4.1配置步骤

1、配置定时器基础工作参数:HAL_TIM_Base_Init()

2、定时器基础Msp初始化函数:HAL_TIM_Base_MspInit()

3、使能更新中断并启动计数器:HAL_TIM_Base_Start_IT()

4、设置中断优先级并使能中断:HAL_NVIC_SetPriority、HAL_NVIC EnablePQ()

5、编写中断服务函数:TIMx_IPQHandler()----HAL_TIM_IPQHandler()

6、编写定时器更新中断服务函数:HAL_TIM_Periodlapsed Callback()

4.2相关库函数

HAL_TIM_Base_Init 函数

HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);

形参 1 是 TIM_HandleTypeDef 结构体类型指针变量(亦称定时器句柄);

其中主要关注:

Instance:指向定时器寄存器基地址。

TIM_Base_InitTypeDef:

1)Prescaler:预分频系数,即写入预分频寄存器的值,范围 0 到 65535。

2)CounterMode:计数器计数模式,这里基本定时器只能向上计数。

3)Period:自动重载值,即写入自动重载寄存器的值,范围 0 到 65535。

4)ClockDivision:时钟分频因子,也就是定时器时钟频率 CK_INT 与数字滤波器所使用的 采样时钟之间的分频比,基本定时器没有此功能。

5)RepetitionCounter:设置重复计数器寄存器的值,用在高级定时器中。

6)AutoReloadPreload自动重载预装载使能,即控制寄存器 1 (TIMx_CR1)的 ARPE 位。

该寄存器需要设置的就是标红的部分;其余不需要进行修改。

HAL_TIM_Base_Start_IT 函数

是更新定时器中断和使能定时器的函数。

其声明如下: HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);

该函数调用了__HAL_TIM_ENABLE_IT 和__HAL_TIM_ENABLE 两个函数宏定义,分别是更新定时器中断和使能定时器的宏定义。

五、基本定时器实验

5.1实验描述

 LED0的进行状态翻转,将在定时器更新中断里进行500ms 周期的定时器更新状态。

5.2源码

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIM/tim.h"

int main(void)
{
    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);      /* 设置时钟, 72Mhz */
    delay_init(72);                          /* 延时初始化 */
    led_init();                              /* LED初始化 */
    tim_init(5000-1,7200-1);                 /* 定时器初始化并传参 */
    while(1)
    {   
    }
}

tim.c

#include "./BSP/TIM/tim.h"
#include "./BSP/LED/led.h"
TIM_HandleTypeDef tim_handler;
//定时器中断初始化函数

void tim_init(uint32_t arr,uint32_t psc)//arr自动重装载计数器值,psc预分频系数
{
    __HAL_RCC_TIM6_CLK_ENABLE();//使能时钟
    tim_handler.Instance=TIM6;//设置外设基地址
    tim_handler.Init.Period=arr;//设置自动重装载计数器值
    tim_handler.Init.Prescaler=psc; //设置预分频系数
     tim_handler.Init.CounterMode=TIM_COUNTERMODE_UP;//计数模式
    HAL_TIM_Base_Init(&tim_handler);//初始化库函数
    HAL_TIM_Base_Start_IT(&tim_handler);//更新定时器中断和使能定时器的函数
}
//定时器基础Msp初始化
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
  HAL_NVIC_EnableIRQ(TIM6_IRQn);//中断使能
  HAL_NVIC_SetPriority(TIM6_IRQn, 2, 2); //设置中断优先级
}

//定时器6中断服务函数
void TIM6_IRQHandler(void)
{
 HAL_TIM_IRQHandler(&tim_handler);
}    

//定时器溢出中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);//LED0状态翻转

}
    

led.c

#include "./BSP/LED/led.h"

void led_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitTypeDef led0_init;
    led0_init.Mode=GPIO_MODE_OUTPUT_PP;
    led0_init.Pin=GPIO_PIN_5;
    led0_init.Pull=GPIO_PULLUP;
    led0_init.Speed=GPIO_SPEED_FREQ_HIGH;  
    HAL_GPIO_Init(GPIOB, &led0_init);
    
    __HAL_RCC_GPIOE_CLK_ENABLE();
    GPIO_InitTypeDef led1_init;
    led1_init.Mode=GPIO_MODE_OUTPUT_PP;
    led1_init.Pin=GPIO_PIN_5;
    led1_init.Pull=GPIO_PULLUP;
    led1_init.Speed=GPIO_SPEED_FREQ_HIGH;  
    HAL_GPIO_Init(GPIOE, &led1_init);
    
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5, GPIO_PIN_SET);

} 

 链接:https://pan.baidu.com/s/1z1SW6zDqTskoBmJs6rVEtA 
提取码:1022

5.3实验现象

基本定时器视频

总结:本节我们学习了STM32定时器中的基本定时器,主要内容包括:定时器的概述、基本定时器的内容、相关寄存器的讲解,实验的配置步骤与相关库函数,最后利用实验证明了的基本定时器的使用。内容不难,还望各位读者多多阅读,最好能自己实践一下。

创作不易,还请大家多多点赞支持!!!

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

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

相关文章

U盘启动安装win11遇到缺少计算机所需的介质驱动程序问题

一、使用U盘制作启动盘遇到问题 下载了windows原版镜像,验证了md5,确保文件没有损坏。使用ultroiso制作u盘启动盘,开始安装后出现下图的报错: 在网上搜索解决方案,主要有以下几种: 安装的时候&#xff0c…

2024年【电工(初级)】最新解析及电工(初级)模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 电工(初级)最新解析根据新电工(初级)考试大纲要求,安全生产模拟考试一点通将电工(初级)模拟考试试题进行汇编,组成一套电…

直接写一区! ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别程序,特征可视化,实验多!图多!

适用平台:Matlab2023版本及以上 本原创程序提出的ZOA-PCNN-AT-SVM故障识别模型还没有人写!在此基础上进一步对参考模型进行多重改进,程序注释清晰,干货满满,下面对文章和程序做简要介绍! ①识别模型部分参…

【竞技宝】DOTA2:梦幻联赛开战在即 中国区前两名将晋级正赛

北京时间2024年1月12日,近期DOTA2刚刚结束了别墅杯东南亚/中国区的封闭预选赛,而别墅杯的正赛还要等到下个月才会正式开打,而即将在明天开始进行的是梦幻联赛S22的中国区预选赛,除官方直邀的XG战队直接晋级正赛之外,其…

C++力扣题目106,105--中序和后序,前序和中序遍历构造二叉树

106.从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 中序遍历 inorder [9,3,15,20,7]后序遍历 postorder [9,15,7,20,3] 返回如下的二叉树&am…

功能强大:JMeter 常用插件全解析

JMeter 作为一个开源的接口性能测试工具,其本身的小巧和灵活性给了测试人员很大的帮助,但其本身作为一个开源工具,相比于一些商业工具(比如 LoadRunner),在功能的全面性上就稍显不足。这篇博客,…

ubuntu20.04网络问题以及解决方案

1.网络图标消失,wired消失,ens33消失 参考:https://blog.51cto.com/u_204222/2465609 https://blog.csdn.net/qq_42265170/article/details/123640669 原始是在虚拟机中切换网络连接方式(桥接和NAT), 解决…

MySQL表结构转换为ES索引Mapping

背景 日常开发过程中肯定会存在MySQL表数据迁移至ES的情况,以canal为例,数据迁移时需要提前在ES中创建索引Mapping,但是如果碰到字段特别的表时,创建Mapping将是一件耗费心神的事情。为了解决这些重复工作,我使用Pyth…

mp-html 微信原生小程序渲染富文本

引入组件 "usingComponents": {"mp-html": "/components/mp-html/index"}使用 <mp-html content"{{info.course_info.info}}" />获取组件 介绍 mp-html&#xff0c;小程序富文本解析利器 全面支持html标签 小程序大多数都是…

Docker 方式安装 HertzBeat

一、安装docker docker安装参考https://www.runoob.com/docker/docker-tutorial.html curl -fsSL https://get.docker.com -o get-docker.shsudo sh get-docker.sh二、拉取docker镜像 https://hertzbeat.com/zh-cn/docs/start/docker-deploy部署HertzBeat您可能需要掌握的几条…

【c++】类和对象1

1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完 成 …

第二节课 书生·浦语大模型趣味 Demo笔记及作业

文章目录 笔记作业基础作业&#xff1a;进阶作业&#xff1a; 笔记 书生浦语大模型InternLM-Chat-7B 智能对话 Demo&#xff1a;https://blog.csdn.net/m0_49289284/article/details/135412067书生浦语大模型Lagent 智能体工具调用 Demo&#xff1a;https://blog.csdn.net/m0_…

线性方程组计算

一、题型 1&#xff09;给一个线性方程组&#xff0c;问&#xff1a;唯一解&#xff1f;无解&#xff1f;无穷多解&#xff1f; 2&#xff09;在上面的基础上&#xff0c;给一个未知数λ&#xff0c;问&#xff1a;当λ为几时&#xff0c;方程组唯一解&#xff1f;无解&#…

短视频账号矩阵剪辑分发系统无人直播技术开发源头

一、全行业独家源头最全面的核心技术 短视频矩阵新玩法是指利用批量自动混剪系统来处理大量短视频&#xff0c;通过智能算法自动进行视频剪辑、场景切换、特效添加等操作&#xff0c;最终生成高质量、精彩纷呈的混剪视频作品的方法和技术。这一方法的出现使得大规模短视频制作…

结构体成员 分数比较大小

题目&#xff1a; 代码&#xff1a; #include <bits/stdc.h> #include<cstring>using namespace std;struct Num{double fenzi;double fenmu;char fenhao;};bool cmp(Num r1,Num r2){return r1.fenzi/r1.fenmu<r2.fenzi/r2.fenmu;}int main(){int n;Num num[n…

jmeter--3.使用提取器进行接口关联

目录 1. 正则表达式提取器 1.1 提取单个数据 1.2 名词解释 1.3 提取多个数据 2. 边界值提取器 2.2 名词解释 3. JSON提取器 3.1 Json语法 3.2 名词解释 3.3 如果有多组数据&#xff0c;同正则方式引用数据 1. 正则表达式提取器 示例数据&#xff1a;{"access_to…

2023年毕马威中国金融科技双50榜单揭晓 百望云实力入选

近日&#xff0c;“2023年毕马威中国金融科技企业双50榜单发布暨颁奖典礼”&#xff08;简称“KPMG Fintech 50”&#xff09;在成都举行。此次活动是在“交子千年”系列活动之成都金融科技产业发展大会暨交子金融文化月启动仪式上进行&#xff0c;由中国人民银行四川省分行、成…

【AI视野·今日Robot 机器人论文速览 第七十二期】Mon, 8 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Mon, 8 Jan 2024 Totally 13 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Deep Reinforcement Learning for Local Path Following of an Autonomous Formula SAE Vehicle Authors Harvey Merton, Thoma…

想做鸿蒙开发应该学会哪些知识?

鸿蒙开发学习是一项探索性的工作&#xff0c;旨在开发一个全场景分布式操作系统&#xff0c;覆盖所有设备&#xff0c;让消费者能够更方便、更直观地使用各种设备。 鸿蒙系统定位为面向未来、面向全场景&#xff08;移动办公、运动健康、社交通信、媒体娱乐等&#xff09;的分…

服务器管理平台开发(2)- 设计数据库表

数据库表设计 本篇文章主要对数据管理平台数据库表设计进行介绍&#xff0c;包括单库多表设计、SQL语句、视图构造等 1、整体设计 设备品牌、序列号、型号等使用业务主表进行记录&#xff0c;逻辑磁盘、PCI设备可能出现1对N的情况&#xff0c;分别使用PCI设备表、Mac地址表、逻…