正点原子--STM32基本定时器学习笔记(2)

目录

1. 相关寄存器介绍

1.1 控制寄存器 1(TIMx_CR1)​编辑

1.2 DMA/中断使能寄存器(TIMx_DIER)

1.3 状态寄存器(TIMx_SR)

1.4 计数器(TIMx_CNT)

1.5 预分频器(TIMx_PSC)

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

2. 工程建立

3. 导入tim.c文件

4. 相关HAL库函数介绍 

4.1 HAL_TIM_Base_Init()

4.2 HAL_TIM_Base_MspInit()

4.3 HAL_TIM_Base_Start_IT()

5. 编写代码


书接上文,本篇是对基本定时器实验部分进行总结!

实验目标:通过TIM6基本定时器定时500ms,让LED0每隔500ms闪烁。

解决思路:使用定时器6,实现500ms产生一次定时器更新中断,在中断里执行“翻转LED0”。

定时器什么时候会产生更新中断呢?

有两种情况:第一种是定时器计数到ARR值后溢出,这时会伴随更新事件和更新中断的产生;第二种是通过软件的方式,设置UG位产生软件的更新中断,从而产生更新中断。


1. 相关寄存器介绍

首先我们来学习控制寄存器 1(TIMx_CR1)、DMA/中断使能寄存器(TIMx_DIER)、状态寄存器(TIMx_SR)、计数器(TIMx_CNT)、预分频器(TIMx_PSC)、自动重装载寄存器(TIMx_ARR)的功能。

1.1 控制寄存器 1(TIMx_CR1)

首先介绍位7,由上篇理论部分的笔记中我们知道:

影子寄存器:是实际起作用的寄存器,不能直接访问,而ARPE位决定了ARR是否具有缓冲,当设置为有缓冲时,ARR的预装载寄存器写入某个值,这个值不会立即起作用,必须等到更新事件发生时,才会把ARR的预装载寄存器的值转移到影子寄存器,从而真正起作用生效;而设置无缓冲时,给ARR的预装载寄存器写入某个值,它会立即转移到影子寄存器中,会立即生效。(立即生效的时间可能在ns或是us级)

预装载寄存器实际上起到一个缓冲的作用。

 比如:我们想让LED灯实现亮1s灭2s的功能,那么我们就需要对应操作ARR寄存器的值。假设系统时钟为72MHz,定时器预分频系数为7200,72000000/(7199+1)=10000,定时器将以10KHz的频率计数,即1s计10000个数,那么ARR值就为9999,倘若定时2s,ARR值需要修改为19999。

当ARPE配置为0,即ARR寄存器无缓冲时,我们先把ARR的值设为9999,定时1s,1s时间到达之后,需要再次操作ARR寄存器的值变为19999来定时2s,而操作ARR寄存器也需要一定时间(可能是ns或us级),相对于秒级来说微秒可以忽略不计了,但是如果定时的是50us,而操作ARR寄存器的时间也是微秒级,那就会有误差了!

当ARPE配置为1,即ARR寄存器有缓冲时,先让ARR设为9999生效,定时1s,这时我们再次修改ARR的值为19999,当1s到之后更新事件发生,才会把19999从ARR预装载寄存器转移到影子寄存器,从而节省了操作ARR寄存器的时间,精度也会很准确!

总结一下:有缓冲,提前写入,减少误差;无缓冲,按时写入,有误差。

再者介绍位0(CEN:计数器使能),默认情况下该位为0,计数器是关闭的状态;开启时把该位置1。

总结控制寄存器1在该实验的功能:用于设置ARR寄存器是否具有缓冲,使能/关闭计数器

1.2 DMA/中断使能寄存器(TIMx_DIER)

默认条件下,位8和位0都是0都是禁止状态。

当把位8置1即使能更新DMA请求,计数器计数溢出时就会产生DMA请求;

同理,把位0置1,当计数器溢出时会产生更新中断。此次实验用到了位0,没有用到位8。

总结中断使能寄存器在该实验的功能:用于使能更新中断

1.3 状态寄存器(TIMx_SR)

该寄存器只有位0有效,当计数器溢出时产生更新中断,该位被硬件置1,由程序编写清除。

总结:用于判断是否发生了更新中断,由硬件置1,软件清零

1.4 计数器(TIMx_CNT)

 16位的计数器,实时数值,可用于设置计时器初始值,范围:0~65535

1.5 预分频器(TIMx_PSC)

用于设置预分频系数,范围:0~65535,实际预分频系数等于PSC+1。

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

当更新时间发生时,才会把预装载寄存器的值传送到其对应的影子寄存器当中,用于设置自动重装载值,范围:0~65535。

总结:预分频器和自动重装载寄存器实际起作用的都是对应的影子寄存器。


2. 工程建立

介绍完相关寄存器之后,现在开始实操训练了。也是以正点原子HAL库 实验1 跑马灯实验为基础,相当于是工程模板了,我们复制工程,在“Drivers--BSP”目录下建立TIMER文件夹,并创建tim.c和tim.h文件;

3. 导入tim.c文件

导入方法和上篇帖子一样,不清楚的小伙伴可以参考⬇⬇⬇⬇⬇

正点原子--STM32中断系统学习笔记(2)

在tim.h文件中添加这部分代码(之后自己新建的.c和.h文件都会按照此模板创建)

#ifndef _TIM_H
#define _TIM_H
#include "./SYSTEM/sys/sys.h"#endif

重要的一点是要添加hal库tim的驱动文件!!!不然编译不通过

4. 相关HAL库函数介绍 

4.1 HAL_TIM_Base_Init()

我们找到这个函数的定义,分别去HAL_StatusTypeDef和TIM_HandleTypeDef里面看看。

返回值: 

形参为定时器的句柄 :

下图为TIM6定时器的基地址 

定时器初始化结构体成员: 

Prescaler/*预分频系数*/      对应操作PSC寄存器;

CounterMode/*计数模式*/        基本定时器只有向上计数模式;

Period/*自动重载值*/        对应操作ARR寄存器;

ClockDivision/*时钟分频因子*/        基本定时器无该寄存器,只有通用/高级寄存器才需要配置;

RepetitionCounter/*重复计数器寄存器的值*/        基本/通用定时器都无该寄存器,只有高级定时器才有用

AutoReloadPreload/*自动重载预装载使能*/        对应控制寄存器1的位7:ARPE

在这次实验当中,我们只用到了三个:Prescaler、Period、AutoReloadPreload.

4.2 HAL_TIM_Base_MspInit()

该函数没有对应的寄存器,__weak是弱定义,用户可自己编写,主要在函数里存放NVIC、CLOCK、GPIO初始化代码。

4.3 HAL_TIM_Base_Start_IT()

中断处理函数和更新中断回调函数在之前的中断帖子有介绍,大同小异!

正点原子--STM32中断系统学习笔记(1)

5. 编写代码

配置思路:我们按照正点原子给的步骤一步步来配置,最重要的是学习配置思路,一通百通!!

①在定时器中断初始化函数里对定时器的参数进行配置(包括:基地址、自动重装载值、预分频值),以及使能更新中断并开启计数器;

②在定时器基础MSP初始化函数里,先进行检测是否为TIM6定时器,如果是TIM6,那么就使能TIM6时钟,并设置中断优先级和使能中断;这点和标准库配置有些差别,标准库是一开始就先使能时钟,而HAL库是在这个函数里完成那些功能!

③在TIM6中断服务函数里调用定时器中断公共处理函数,在定时器中断公共处理函数里进行清中断标志位,调用定时器中断回调函数HAL_TIM_IC_CaptureCallback()的操作。

④ 在定时器溢出中断回调函数里,先进行检测是否为TIM6定时器,如果是TIM6,那么就进行LED0的翻转。

执行流程:

在main函数里先进行定时器中断初始化配置,tim_it_init(4999, 7199);
定时500ms,时间一到便会产生定时器更新中断,进入TIM6中断服务函数,执行定时器中断公共处理函数(进行清中断标志位,调用定时器中断回调函数,在回调函数里进行LED灯的翻转)

以下是tim.c的代码:

#include "./BSP/TIMER/tim.h"
#include "./BSP/LED/led.h"TIM_HandleTypeDef tim_handle;/* 定时器中断初始化函数 */
void tim_it_init(uint16_t arr, uint16_t psc)
{tim_handle.Instance = TIM6;tim_handle.Init.Prescaler = psc;tim_handle.Init.Period = arr;HAL_TIM_Base_Init(&tim_handle);		        /* 配置定时器基础工作参数 */HAL_TIM_Base_Start_IT(&tim_handle);		    /* 使能更新中断并启动计数器 */
}/* 定时器基础MSP初始化函数 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM6)						/* 判断定时器的基地址是否为TIM6 */{__HAL_RCC_TIM6_CLK_ENABLE();			    /* 使能定时器6时钟 */HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);		/* 设置优先级 */HAL_NVIC_EnableIRQ(TIM6_IRQn);				/* 使能中断 */}
}/* 定时器6中断服务函数 */
void TIM6_IRQHandler(void)
{HAL_TIM_IRQHandler(&tim_handle);		/* 定时器中断公共处理函数 */
}/* 定时器溢出中断 中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM6)			/* 判断定时器的基地址是否为TIM6 */{LED0_TOGGLE();LED1_TOGGLE();}
}

main.c代码: 

#include "stm32f1xx_it.h"
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/tim.h"int main(void)
{HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */delay_init(72);                             /* 初始化延时函数 */led_init();                                 /* 配置STM32操作LED相关的寄存器 */tim_it_init(4999, 7199);					/* 初始化定时器 */while(1){}
}

以上就是基本定时器实验的所有内容了! 


本篇完。

本人博客仅代表个人见解方便记录成长笔记。

若有不足,请指出,感谢您的阅读!

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

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

相关文章

[linux]-总线,设备,驱动,dts

1. 总线BUS 在物理层面上,代表不同的工作时序和电平特性: 总线代表着同类设备需要共同遵守的工作时序,不同的总线对于物理电平的要求是不一样的,对于每个比特的电平维持宽度也是不一样,而总线上传递的命令也会有自己…

动态扩缩容下的全局流水号设计

关于全局流水号,业内用的比较多的就是雪花算法,一直没理解在动态扩缩容下其中的workId和 datacenterId如何设置,查到了几个方法:reidis中取,待后期实践下。 先简单的介绍一下雪花算法,雪花算法生成的Id由…

零代码3D可视化快速开发平台

老子云平台 老子云3D可视化快速开发平台,集云压缩、云烘焙、云存储云展示于一体,使3D模型资源自动输出至移动端PC端、Web端,能在多设备、全平台进行展示和交互,是全球领先、自主可控的自动化3D云引擎。此技术已经在全球申请了专利…

6.0 Zookeeper session 基本原理详解教程

客户端与服务端之间的连接是基于 TCP 长连接,client 端连接 server 端默认的 2181 端口,也就 是 session 会话。 从第一次连接建立开始,客户端开始会话的生命周期,客户端向服务端的ping包请求,每个会话都可以设置一个…

飞天使-k8s知识点13-kubernetes散装知识点2-statefulsetdaemonset

文章目录 RC RS DeploymentStatefulSet有状态服务控制器DaemonSet守护进程与任务job cronjob RC RS Deployment StatefulSet有状态服务控制器 statefulset StatefulSet 是 Kubernetes 1.9 版本引入的一个新的 API 对象,主要用于处理有状态的服务。StatefulSet 与 De…

12.JavaScript(WebAPI) - JS api文献精解

文章目录 1.WebAPI 背景知识1.1什么是 WebAPI1.2什么是 API1.3API 参考文档 2.DOM 基本概念2.1什么是 DOM2.2DOM 树 3.获取元素3.1querySelector3.2querySelectorAll 4.事件初识4.1基本概念4.2事件三要素4.3简单示例 5.操作元素5.1获取/修改元素内容5.1.1innerText5.1.2innerHT…

EMC学习笔记(二十一)降低EMI的PCB设计指南(一)

降低EMI的PCB设计指南(一) 1.概述2.射频3.连接器与过孔元件4.静态引脚和动态引脚和输入5.基本回路6.差模与共模 tips:资料主要来自网络,仅供学习使用。 1.概述 印刷电路板(PCB)的一般布局准则,基本上都有相对的文件进…

C++重新入门-C++变量作用域

目录 1.C变量定义 2.C作用域 3.局部变量 4.全局变量 5.块作用域变量 6.初始化局部变量和全局变量 1.C变量定义 一般来说有三个地方可以定义变量: 在函数或一个代码块内部声明的变量,称为局部变量。 在函数参数的定义中声明的变量,称为…

【教程】Linux使用git自动备份和使用支持文件恢复的rm命令

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 背景介绍 首先非常不幸地告诉你:Linux 系统的标准 rm 命令不支持文件恢复功能。一旦使用 rm 删除了文件或目录,它们就会从文件系统中永久删除,除非你使用专门的文件恢复工具尝试…

2.7作业

分别通过select、多进程、多线程实现一个并发服务器 select #include <myhead.h> #define PORT 8888 #define IP "192.168.250.100" int main(int argc, const char *argv[]) {//1、创建用于接受连接的套接字int sfd socket(AF_INET, SOCK_STR…

C++ || 模板初阶 | 函数模板 | 类模板

泛型编程 泛型编程&#xff0c;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 可以理解为活字印刷术类似的方式。 函数模板 函数模板概念 函数模板&#xff0c;代表一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用…

Centos7.9安装SQLserver2017数据库

Centos7.9安装SQLserver2017数据库 一、安装前准备 挂载系统盘 安装依赖 yum install libatomic* -y 二、yum方式安装 # 配置 yum 源 wget -O /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/7/mssql-server-2017.repoyum clean all yum…

洛谷:P1219 [USACO1.5] 八皇后 Checker Challenge(dfs深度优先遍历求解)

题目描述 一个如下的 6666 的跳棋棋盘&#xff0c;有六个棋子被放置在棋盘上&#xff0c;使得每行、每列有且只有一个&#xff0c;每条对角线&#xff08;包括两条主对角线的所有平行线&#xff09;上至多有一个棋子。 上面的布局可以用序列 2 4 6 1 3 52 4 6 1 3 5 来描述&am…

Bagging的随机森林;Boosting的AdaBoost和GBDT

集成学习应用实践 import numpy as np import os %matplotlib inline import matplotlib import matplotlib.pyplot as plt plt.rcParams[axes.labelsize] 14 plt.rcParams[xtick.labelsize] 12 plt.rcParams[ytick.labelsize] 12 import warnings warnings.filterwarnin…

【保姆级教程|YOLOv8改进】【7】多尺度空洞注意力(MSDA),DilateFormer实现暴力涨点

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

websocket具体实践

websocket具体实践 参考&#xff1a; 如何使用websocket WebSocket客户端连接不上和掉线的问题以及解决方案 继6月份对websocket一顿了解之后&#xff0c;我们的项目也要上websocket了&#xff0c;虽然这部分不是我做&#xff0c;但是借此机会&#xff0c;我也想要尝试一下&am…

VS无法使用万能头文件#include <bits/stdc++.h> 的解决办法

第一步在vs中打出可以使用的头文件 如#include<cmath> 点击F12转到文档 上面窗口右键找到打开所在文件夹 创建一个名字为bits的文件夹 里面创建一个text文件 // C includes used for precompiling -*- C -*-// Copyright (C) 2003-2015 Free Software Foundation, In…

【开源】JAVA+Vue.js实现开放实验室管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实验管理模块2.4 实验设备模块2.5 实验订单模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示五、样例代码5.1 查询实验室设备5.2 实验放号5.3 实验预定 六、免责说明 一、摘…

TryHackMe-Vulnerability Capstone练习

本文相关的TryHackMe实验房间链接&#xff1a;TryHackMe | Vulnerability Capstone 先nmap扫一下 接下来我们访问一下 接下来我们searchsploit找一下漏洞 searchsploit Fuel CMS 执行漏洞exp&#xff08;此处使用TryHackMe中的box&#xff09; 如果使用本地机需要下载exp&am…

孙思邈中文医疗大模型

孙思邈, 唐代医药学家、道士, 被后人尊称为"药王". 其十分重视民间的医疗经验, 不断积累走访, 及时记录下来, 写下著作《千金要方》. 唐朝建立后, 孙思邈接受朝廷的邀请, 与政府合作开展医学活动, 完成了世界上第一部国家药典《唐新本草》. 孙思邈中医药大模型(简称:…