stm32定时器

定时器介绍

软件定时
缺点:不精确、占用 CPU 资源

还记得以前在开发C51的时候,经常使用stc助手生成的定时代码,形如:

void Delay500ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}
定时器工作原理:
使用精准的时基,通过硬件的方式,实现定时功能。定时器核心就是计数器。

定时器分类

基本定时器(TIM6,TIM7)没有输入输出通道,常用作时基,即定时功能

通用定时器(TIM2~TIM5)具有多路独立通道,可用于输入捕获/输出比较,也可用作时基

高级定时器(TIM1,TIM8)除具备通用定时器所有功能外,还具备带死区控制的互补信号输出刹车输入等功能(可用于电机控制、数字电源设计等)

STM32F103C8T6 定时器资源:
所以32 STM32F103C8T6 的定时器资源是:一个高级定时器TIM1和三个通用定时器TIM2,3,4!
通用定时器介绍:

可见,和51/52相比,stm32的定时器复杂得多

定时器计数模式

定时器时钟源

下图是手册P56,主要关注红圈部分

根据上图的原理,可以推出下面的公式,十分重要!!!

Tout = 设定时间 (单位秒s)

Tclk = 通过预分频后输出的TIMxCLK(上图右侧红线)

PSC = 预分频系数 (+1是因为计算机是从0开始的)

ARR = 自动重装载值(+1是因为计算机是从0开始的)

例如:要定时500ms,则可以在配置定时器时使用: PSC = 7199,ARR = 4999,TClk = 72M(72 000 000)(有多种组合)

((7199+1)/72000000)/(4999+1)=0.5s

使用定时器中断实现LED灯的状态反转 

需求:使用定时器中断方法,每 500ms 翻转一次 LED1 灯状态。
1. RCC 配置
2. LED1 灯配置
3. 时钟数配置
4. TIM2 配置
打开CubeMX,先进行惯例配置

配置时钟(上图)最右侧一列的“APB1 Timer clocks”和“APB2 Timer clocks”就是刚刚提到的计算公式中的Tclk,单位是MHz,此处就是Tclk = 72MHz,具体详情查看上图的时钟原理图

配置PB8(LED1)为GPIO_out模式且初始值为HIGH

Timer 配置

1. 在左侧选择Timers选项,此处选择通用定时器Timer2(Timer1是高级定时器,故不选用)

第一个参数就是预分频器,第三个参数就是ARR:

 回顾刚刚的计算公式:

要定时500ms,则可以在配置定时器时使用: PSC = 7199,ARR = 4999,TClk = 72M(72 000 000)(可选其他多种组合)

同时打开第五个参数的自动重载!(因为希望LED连续不断的翻转状态,而不是翻转一次就结束)

进行如下设置:(目前可以只关心 Clock Source),在设置为Internal Clock后,下方会自动弹出NVIC界面,选择打开中断。

打开Keil

此时自动弹出Keil工程,记得先编译一下,养成良好编程习惯!

通过 stm32f1xx_it.c --> TIM2_IRQHandler() --> HAL_TIM_IRQHandler() --> 然后就和之前不大一样了,之前进行到这里就会出现一个 weak 类型的可重写中断处理函数,但此时是一个巨长无比的函数:

void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{/* Capture compare 1 event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET){{__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;/* Input capture event */if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U){
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->IC_CaptureCallback(htim);
#elseHAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}/* Output compare event */else{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->OC_DelayElapsedCallback(htim);htim->PWM_PulseFinishedCallback(htim);
#elseHAL_TIM_OC_DelayElapsedCallback(htim);HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;}}}/* Capture compare 2 event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;/* Input capture event */if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U){
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->IC_CaptureCallback(htim);
#elseHAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}/* Output compare event */else{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->OC_DelayElapsedCallback(htim);htim->PWM_PulseFinishedCallback(htim);
#elseHAL_TIM_OC_DelayElapsedCallback(htim);HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;}}/* Capture compare 3 event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;/* Input capture event */if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U){
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->IC_CaptureCallback(htim);
#elseHAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}/* Output compare event */else{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->OC_DelayElapsedCallback(htim);htim->PWM_PulseFinishedCallback(htim);
#elseHAL_TIM_OC_DelayElapsedCallback(htim);HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;}}/* Capture compare 4 event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;/* Input capture event */if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U){
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->IC_CaptureCallback(htim);
#elseHAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}/* Output compare event */else{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->OC_DelayElapsedCallback(htim);htim->PWM_PulseFinishedCallback(htim);
#elseHAL_TIM_OC_DelayElapsedCallback(htim);HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;}}/* TIM Update event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->PeriodElapsedCallback(htim);
#elseHAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}}/* TIM Break input event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->BreakCallback(htim);
#elseHAL_TIMEx_BreakCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}}/* TIM Trigger detection event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->TriggerCallback(htim);
#elseHAL_TIM_TriggerCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}}/* TIM commutation event */if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET){if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) != RESET){__HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)htim->CommutationCallback(htim);
#elseHAL_TIMEx_CommutCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}}
}

但是,我们现在只关注:如果定时时间到了之后,定时器会做什么的函数

因此,可以找到这样一个函数:HAL_TIM_PeriodElapsedCallback(htim);

对于这个函数进行跳转,终于出现了可以重写的中断处理函数:

 然后在main.c中重写这个函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM2){ //注意,htim是一个结构体指针,所以对于结构体中成员变量的访问要用“->”HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);}
}

经查找,要在main函数中添加一句,启动定时器:(当然,也是在生成的初始化之后)

HAL_TIM_Base_Start_IT(&htim2);

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

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

相关文章

Macos docker安装达梦数据库

官网下载达梦docker镜像安装包 导入安装包 docker load -i /Users/yeungsinsin/Downloads/dm8_20230808_rev197096_x86_rh6_64_single.tar查看导入的镜像 docker images4. docker run 启动容器 docker run -d -p 30236:5236 --restartalways --name dm8 --privilegedtrue -e…

基于深度学习的心律异常分类系统设计——算法设计

基于深度学习的心律异常分类系统——算法设计 第一章 研究背景算法流程本文研究内容 第二章 心电信号分类理论基础心电信号产生机理MIT-BIH 心律失常数据库 第三章 心电信号预处理心电信号噪声来源与特点基线漂移工频干扰肌电干扰 心电信号读取与加噪基于小波阈值去噪技术的应用…

手机抓包也太简单好玩了吧!

我们选择Charles来作为抓包工具,本文将从0到1讲解从电脑端抓包到手机端抓包。 Charles是一款被广泛使用的网络抓包工具,它可以用来监控和调试通过HTTP和HTTPS协议发送和接收的所有网络请求和响应。Charles通常用于网页和网络应用的开发过程中&#xff0…

基于python+vue家政服务系统flask-django-php-nodejs

相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低家政公司的运营人员成本,实现了家政服务的标准化、制度化、程序化的管理,有效地防止了家政服务的随意管理,提高了信息的处理速度和精确度,能够及时、准确地…

9.测试教程-性能测试概述

文章目录 1.常见的性能问题2.为什么要进行性能测试3.性能测试实施的流程4.概念和术语介绍5.性能测试模型6.性能测试方法介绍7.性能测试实施与管理8.性能测试前期准备9.测试工具引入10.性能测试方案11.性能测试设计与开发12.性能测试设计与管理13.性能测试设计与调优14.性能测试…

【.net/.net core】后台生成echarts图片解决方案及.net core html转word方法

工具环境下载: EChartsConvert:https://gitee.com/saintlee/echartsconvert EChartsConvert为生成echarts图片的服务端,用于接收参数和生成echarts图表图片BASE64编码 PhantomJS:Download PhantomJS PhantomJS用来发布EChartsConvert服务…

在 3D 虚拟城市中展示自定义建筑

在本教程中,您将学习如何创建 Cesium 应用程序,用您自己的 3D 模型替换真实城市中的建筑物。您可以使用它来可视化拟建建筑的影响,及如何改变天际线?从特定楼层或房间看到的景色会是什么样子? 我们将介绍如何&#xf…

Web and HTTP

Web and HTTP First, a review… ▪ web page consists of objects ▪ object can be HTML file, JPEG image, Java applet, audio file,… ▪ web page consists of base HTML-file which includes several referenced objects ▪ each object is addressable by a URL, e.g.,…

MAC本安装telnet

Linux运维工具-ywtool 目录 1.打开终端1.先安装brew命令2.写入环境变量4.安装telnet 1.打开终端 访达 - 应用程序(左侧) - 实用工具(右侧) - 终端 #注意:登入终端用普通用户,不要用MAC的root用户1.先安装brew命令 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/H…

Databend x CubeFS:面向未来的企业级云原生数据存储与分析

用场景的丰富,企业面临着前所未有的数据存储挑战。大规模数据存储变得日常化,伴随着超大容量和快速变化的I/O需求,传统的存储解决方案已经难以满足企业对弹性、运维效率及总体拥有成本(TCO)的更高要求。这些挑战促使基…

基于傅里叶描述子的手势动作识别,Matlab实现

博主简介: 专注、专一于Matlab图像处理学习、交流,matlab图像代码代做/项目合作可以联系(QQ:3249726188) 个人主页:Matlab_ImagePro-CSDN博客 原则:代码均由本人编写完成,非中介,提供…

数学建模(灰色关联度 python代码 案例)

目录 介绍: 模板: 案例:哪些原因影响结婚率 数据标准化: 灰色关联度系数: 完整代码: 结果: 介绍: 灰色关联度是一种多指标综合评价方法,用于分析和评价不同指标之…

由浅到深认识Java语言(9):Eclipse IDE简介

该文章Github地址:https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.c…

华为配置蓝牙终端定位实验

配置蓝牙终端定位示例 组网图形 图1 配置蓝牙终端定位示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 商场管理员希望在已有WLAN覆盖业务的基础上,使用蓝牙定位技术,根据顾客所在的位置,提供商场导航、导…

php 对接Vungle海外广告平台收益接口Reporting API

今天对接的是Vungle广告reporting api接口,拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到Vungle后台就能看到文档地址以及参数: 文档地址:https://support.vungle.com/hc/en-us/articles/211365828-Publisher-Reporting…

AI助力生产制造质检,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建工业生产制造场景下的瓷砖瑕疵检测识别分析系统

瓷砖生产环节一般经过原材料混合研磨、脱水、压胚、喷墨印花、淋釉、烧制、抛光,最后进行质量检测和包装。得益于产业自动化的发展,目前生产环节已基本实现无人化。而质量检测环节仍大量依赖人工完成。一般来说,一条产线需要配数名质检工&…

【C++】1416. 求长方形的周长和面积

问题:1416. 求长方形的周长和面积 类型: 基本运算、整数运算 题目描述: 从键盘读入2个整数,分别代表一个长方形的长和宽,请计算长方形的周长和面积; 输入: 从键盘读入2个整数,用…

STM32利用串口外设发送数据

今天2024.3.21日上午学习了一下基本的串口初始化,利用串口发送一个字节的数据,看时间也快11点了,上午就学习这么多吧,把上午的知识总结一下,串口初始化的过程: 看着图来编写串口初始化的过程: …

GPT-4 vs. ChatGPT:19个弱项问题(多步逻辑推理、概念间接关联)的横向对比

测试对比:在逻辑推理和概念关联方面,GPT-4 显著优于 ChatGPT,准确率从37%提升至100%。智力水平:GPT-4 的思维智力表现可能超过了95%的人。技术进步:短时间内,GPT-4 显著进步,尤其在逻辑能力和多…

超越 GPT-4V 和 Gemini Pro!HyperGAI 发布最新多模态大模型 HPT,已开源

随着AI从有限数据迈向真实世界,极速增长的数据规模不仅赋予了模型令人惊喜的能力,也给多模态模型提供了更多的可能性。OpenAI在发布GPT-4V时就已经明确表示: 将额外模态(如图像输入)融入大语言模型(LLMs&am…