STM32:基本定时器原理和定时程序
一、初识定时器TIM
定时器就是计数器,定时器的作用就是设置一个时间,然后时间到后就会通过中断等方式通知STM32执行某些程序。定时器除了可以实现普通的定时功能,还可以实现捕获脉冲宽度,计算PWM占空比,输出PWM波形,编码器计数等。
STM32共11个定时器,2个高级控制定时器TIM1和TIM8,4个通用定时器TIM2~TIM5,两个基本定时器TIM6和TIM7,两个看门狗定时器和一个系统滴答定时器Systick.
高级定时器TIM1和TIM8的时钟由APB1产生,其它六个通用定时器的时钟由APB2产生。它们的最大频率都可以配置成系统时钟的频率。
| 定时器种类 | 位数 | 计数模式 | 捕获/比较通道 | 应用场景 |
|---|---|---|---|---|
| 通用定时器 TIM2~TIM5 | 16 | 向上,向下,双向 | 4 | 定时计数,PWM,输入捕获,输出比较 |
| 高级定时器 TIM1和TIM8 | 16 | 向上,向下,双向 | 4 | 在通用的基础上,多了刹车信号输入,死区时间互补输出等工业电机功能 |
| 基本定时器 TIM6和TIM7 | 16 | 向上,向下,双向 | 4 | 定时计数 |
二、基本定时器
(1)计数功能原理
在上一期文章提到,时钟树提供稳定频率的方波信号,APB1上的时钟线连接了基本定时器和通用寄存器,APB2上的时钟线连接了高级定时器。

对于实现计数功能,只需要一个寄存器就可以满足,寄存器只需要读到时钟信号的上升沿数值就加1。假如72MHZ的时钟信号作为输入,当该寄存器数值累加到7.2*10^7,就代表时间过去了1秒。但是寄存器通常只有16bit,最多能计数 65536个数。因此在该寄存器前面还要加一个类似的计数器,当计数满足条件时才往后续电路发送高电平,预分频器就可以充当这个角色,其本质也是一个16bit的计数器。当只需要将其设置为n-1,就可以进行n分频,从0开始计数,一直计数到n-1才会向后续电路发送高电平。预分频器最多可以进行65536分频。因此一个由预分频器和一个计数器组合成的定时器,最多可以计数65536^2次。m个定时器串联,就可以计数65536^(2*m)次。

(2) 自动重装载寄存器
自动重装载寄存器,它的作用就是实时监控计数器的值是否与自己的值相同。当计数器的值与自己的值相同时,便将计数器重置为0,并触发定时器更新中断。

(3)影子寄存器
所谓的影子寄存器就是某个寄存器的拷贝。在上图中工作在一线的预分频器和自动重装载寄存器其实都是自己的影子寄存器。当定时器正在工作时,如果重新设置预分频器值或者重新这是自动重装载寄存器的值,那么只有当计数器和自动重装载寄存器的值一样时才会将新值更新到自身影子寄存器中。也就是给定时器设置的新参数值要等下个计数周期才生效。
自动重装载寄存器可以根据程序员选择是否开启影子寄存器。如果不开启,那么将自动重装载寄存器数值调小时,可能会错过计数器的值,使计数器一路上到65536才会归0。
三、定时程序
(1)准备工作
为了发送数据进行模拟,需打开USART2用于设置模式为“异步”,在NVIC Settings中打开中断,打上√,在DMA Settings,打开DMA传输功能,添加传输通道。

为提高计数精度,将外部时钟源设置为"晶振",在时钟设置界面中的HCLK的频率设置为72MHZ,自动调整其它器件的时钟频率。


对于我使用的STM32F108T6芯片只有4个定时器,即1个高级,3个通用寄存器。虽然没有基本定时器,但是这些定时器都包含了基本定时器功能。只需要对定时器的时钟源选择 Internal Clock (内部时钟源)就算打开了定时器。因为本次模拟的时钟频率是72MHZ,设置预分频器7200,自动重装载寄存器为10000,那么完成一个周期的计数就是1s,也就是1s触发一次定时器更新中断。同第一步类似,TIM也可以开启中断和DMA通道。保存并生成代码。

(2)实现定时任务和获取计数器数值:
以下示例代码为开启TIM中断和USART2中断实现,以及开启了自动重装载寄存器的影子寄存器
1.开启定时器
HAL_TIM_Base_Start(&htim); //用阻塞的方式开始定时器
HAL_TIM_Base_Start_IT(&htim); //用中断(非阻塞)的方式开始定时器
HAL_TIM_Base_Start_DMA(&htim); //用DMA(非阻塞)的方式开始定时器
2.中断回调函数
在路径 ~/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c中
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
当计数器数值和自动重装载寄存器值一样时调用
3.读写定时器中寄存器的宏定义操作
__HAL_TIM_GET_ANTORELOAD //获取自动重装载寄存器数值
__HAL_TIM_SET_ANTORELOAD //设置自动重装载寄存器数值
__HAL_TIM_GET_COUNTER //获取计数器数值
__HAL_TIM_SET_COUNTER //设置计数器数值
__HAL_TIM_SET_PRESCALER //设置预分频器数值
4.示例代码
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim4;UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM4_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char message2[]="☺☹";
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim == &htim4){HAL_UART_Transmit_IT(&huart2, (uint8_t*)message2,strlen(message2));}
}
/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART2_UART_Init();//TIM4的初始化MX_TIM4_Init();/* USER CODE BEGIN 2 *///用中断的方式开启定时器HAL_TIM_Base_Start_IT(&htim4);int counter = 0;char message[20];/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){counter = __HAL_TIM_GET_COUNTER(&htim4);sprintf(message,"counter:%d",counter);//每隔100ms发送 counter计数器数值//HAL_UART_Transmit_IT(&huart2, (uint8_t*)message,strlen(message));//延迟100msHAL_Delay(100-1);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
相关文章:
STM32:基本定时器原理和定时程序
一、初识定时器TIM 定时器就是计数器,定时器的作用就是设置一个时间,然后时间到后就会通过中断等方式通知STM32执行某些程序。定时器除了可以实现普通的定时功能,还可以实现捕获脉冲宽度,计算PWM占空比,输出PWM波形&am…...
EntityFramework 批量删除操作
刚刚开始使用Entityframwork 来操作数据库。遇到了批量删除数据。 EF内部用的方法是:dbcontext.Datas.RemoveRange(list); 这总方法,少量数据是可行的。 但遇到大数据量的时候,这个方法完全不能用。 所以找了另一种方法: stri…...
springboot使用的设计模式
设计模式是在软件设计中常用的一些通用解决方案。在开发商城编码时,以下设计模式可能会有用: 工厂模式(Factory Pattern): 用于创建对象的模式。在商城中,可能会涉及到创建不同类型的商品、订单等对象&…...
IP地址定位技术发展与未来趋势
随着互联网的快速发展,人们对网络的需求和依赖程度越来越高。在海量的网络数据传输中,IP地址定位技术作为网络安全与信息追踪的重要手段,其精准度一直备受关注。近年来,随着技术的不断进步,IP地址定位的精准度得到了显…...
AI与交通运输
人工智能(AI)正在改变几乎所有行业,交通运输也不例外。 虽然与某些行业相比,我们运输货物和乘客的方式在过去 50 年里变化相对较小,但人工智能有望引发一场运输革命—如果你正在寻找人工智能的机会,不要错过…...
window.requestAnimationFrame+localStorage+canvas实现跨窗口小球连线效果
文章目录 前言效果代码后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:前端系列文章 🐱👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家…...
使用AndResGuard报错:copy res file not in resources.arsc file:Ezi.xml
Android使用AndResGuard进行资源混淆,压缩。 源码地址:GitHub - shwenzhang/AndResGuard: proguard resource for Android by wechat team 集成完成后编译过程中出现如下错误: 14:57:05 copy res file not in resources.arsc file:IUk.xml…...
插入排序(形象类比)
最近在看riscv手册的时候,里面有一段代码是插入排序,但是单看代码的时候有点迷,没看懂咋操作的,后来又查资料复习了一下,最终才把代码看明白,所以写篇博客记录一下。 插入排序像打扑克牌 这是我听到过比较形…...
ElasticSearch 同步的方式
ElasticSearch 同步的方式 ElasticSearch是一款强大的分布式搜索和分析引擎,支持多种方式同步数据和日志。下面介绍几种常见的同步方式: 1. Logstash Logstash 是 ElasticStack 的一部分,用于收集、处理和转发日志和事件数据。通过配置 Lo…...
easyExcel实现分批导入,动态表头分批导出,以及导出表格样式设置
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version></dependency> 一,分批导入 1.首先配置表格头映射类 Getter Setter EqualsAndHashCode public class …...
Android BottomNavigationView底部菜单栏文字显示问题
1. BottomNavigationView 如果tab栏数据小于等于3个,那么图标和文字都是展示出来; 2. BottomNavigationView 如果tab栏数据大于3个,那么图标会显示出来,但是文字会隐藏; 3. 解决方式: (当底部…...
从零开始学习typescript——运算符(条件运算法、逻辑运算符、类型运算符、位运算)
条件运算符 条件运算符是一个根据条件返回不同运算结果的运算符 关键字:?: 三元运算符 它可以换成if …else 判断 ? true : false 判断为true,返回?号后面的,判断为false ,返回: 号后面的 逻辑运算符 用…...
【开源】基于Vue.js的康复中心管理系统
项目编号: S 056 ,文末获取源码。 \color{red}{项目编号:S056,文末获取源码。} 项目编号:S056,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员…...
抢先看|第二届世界直播电商大会邀您共话时代“新电商”
党的二十大报告指出,要加快发展数字经济,促进数字经济和实体经济深度融合。要深化国家数字经济创新发展试验区建设,打造一批具有国际竞争力的战略性新兴产业集群和数字产业集群。电子商务作为数字经济中规模最大、表现最活跃、发展势头最好的…...
火爆火爆!影响超250万读者,Python入门圣经全新升级!
人生苦短,快学Python! 什么?你没用过,也没开始学习,甚至没有认真了解过这门语言?那你一定这一秒就开始发力——下面让我们先简单看看 Python 有多火。权威编程语言排行榜 TIOBE,2022 和 2023 都…...
大数据学习(23)-hive on mapreduce对比hive on spark
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦ᾑ…...
通过这个简单的技巧让我们的 JavaScript 代码变得异常快
通过这个简单的技巧让我们的 JavaScript 代码变得异常快 秘诀:了解JavaScript 虚拟机(VM)的内部工作原理。 首先,我们来谈谈像 V8 这样的JavaScript 虚拟机(VM)。可以把它想象成我们的操作的大脑 —— 它将我们简洁的代码变成计算机可以理解和执行的东…...
vue怎么实现国际化? vue-i18n 插件实现国际化,支持切换不同语言
依赖的文档开始 | Vue I18n 一、安装 npm install vue-i18n 如果在一个模块系统中使用它,你必须通过 Vue.use() 明确地安装 vue-i18n: import Vue from vue import VueI18n from vue-i18nVue.use(VueI18n)二、使用 在 src 下创建 lang 文件夹 1.准…...
rabbit MQ的延迟队列处理模型示例(基于SpringBoot延时插件实现)
rabbitMQ安装插件rabbitmq-delayed-message-exchange 交换机由此type 表示组件安装成功 生产者发送消息时设置延迟值 消息在交换机滞纳至指定延迟后,进入队列,被消费者消费。 组件注解类: package com.esint.configs;import org.springfra…...
虽不想承认,但这就是CSGO游戏搬砖行业的现状
CSGO搬砖日常出货更新 其实整个搬砖市场,现在已经变得乌烟瘴气,散发着“恶臭”。我个人非常鄙视那些虚有其表,大小通吃的做法,那些甚至连搬砖数据都看不懂的人,也出来吹嘘着“实力强大,经验丰富”。这个世界…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
