STM32快速入门(定时器之输入捕获)

STM32快速入门(定时器之输入捕获)

前言

本节主要讲解STM32利用通用定时器,在输入引脚出现指定电平跳变时,将CNT的值锁存到CCR寄存器当中,从而计算PWM波形的频率、占空比、脉冲间隔、电平持续时间等。其功能的应用有:波形采样。

导航

图98 通用定时器框图:

总览图

图片引自STM32 F1XX系列的中文参考手册。在通用定时器章节的定时器架构图中,本章讲解的定时器输入捕获功能位于左下角的红色矩形中。

定时器输入捕获的实现细节

参考中文手册,实现细节图123如下:

捕获设计的细节

它内部实现是:根据用户设定的极性,采集输入方波信号上升沿/下降沿,将每次上升沿/下降沿的CNT寄存器的值抓取到CCR寄存器中,从而可以获取到输入信号的特性。

参考图123,从左向右介绍控制细节

对于一个通用定时器,有四个通道可作为输入(或输出),信号输入进来首先会经过滤波器进行滤波,消除不稳定的干扰信号,用户可以通过配置 TIMx_CCMR1.IC1F[7:4] 选择采样模式,可以以不同频率不同次数进行采样滤波。如下图。

滤波器的配置

采样可选频率来源有F_CK_INT和F_DTS。其中,F_CK_INT就是定时器的内部时钟(F103默认72M HZ),而F_DTS其实间接取自F_CK_INT的分频。通过配置 TIMx_CR1.CKD[9:8] 可设置F_DTS的分频系数。如下:

DTS频率配置

经过滤波器滤波后的信号在图123中被标记为TI1F,TI1F会传入中间部分的边沿检测器,边沿检测器会根据输入的TI1F分拣出波形的每个上升沿和下降沿,根据输入信号的每一个上升沿/下降沿,向上升沿输出引脚/下降沿引脚输出一个小方波,从而给后面的选择器进行选择,图中间部分有上下两个矩形,在中文手册中,所有类似这样的矩形都是选择器, TIMx_CCER.CC1P[1] 正是通过控制选择器来实现极性的选择。经过极性选择后的波形在图123被标记为TI1FP1。图中还有一个被标记为TI1F_ED的输出,TI1FP1和TI1F_ED的区别是前者是经过选择的上升沿是下降沿的边沿指示信号,而后者是上升沿下降沿的边沿指示信号,频率上来讲TI1F_ED会更高。注意这里边沿指示信号和源信号的区别,我最开始看这张图的中间部分就非常迷糊。

接着看右边最大的那个选择器,该选择器就是配置三路的哪一路作为IC1的输入。三路输入分别是:TI1FP1(对应TIMX_CH1)、TI2FP1(对应TIMX_CH2)、TRC(主从模式下,来自主定时器的信号),通过配置 TIMx_CCMR1.CC1S[1:0] 可以控制选择器选择哪一路。同时后面的预分频器可以通过 TIMx_CCMR1.IC1PSC[3:2] 来调节。如下图60:

CC1S_IC1PSC

最后配置使能寄存器 TIMx_CCER.CC1E[0] 就能使能定时器的输入啦!

精妙设计一

细心的读者在看到图98 红色矩形部分时,应该会注意通道TIMX_CH1和通道TIMX_CH2中间部分是存在交叉的,这里放一张特写图。

Cross

这TI1FP1和TI1FP2的信号源都是来自TIMX_CH1,图123的描述其实有些瑕疵。TI1FP1和TI1FP2的信号源相同,并且可以分别独立的控制去选择极性。也就是说完整的图123应该是有两路TI1FP的,并且可以单独的控制其极性。 如果只使用一路的捕获,我们一次只能测量信号源的频率;而有了这种交叉的设计,我们就可以实现对一个信号源,同时测量其频率和占空比。图60表述了将ICX映射到哪一路,通过配置 TIMx_CCMR1.CC1S[1:0] 可以选择。

精妙设计二

STM32 F1XX里面定时器的设计特别精妙,利用好定时器的主从模式可以实现硬件全自动化复位操作。比如:我们可以利用TI1FP1的信号实现定时器的自动复位,步骤如下:

  1. 配置 TIMx_SMCR.TS[6:4] 为101,这样滤波后的定时器输入1(TI1FP1)作为定时器触发源。 这里的主次好像是两个定时器,但实际上都是一个定时器扮演。

  2. 配置 TIMx_SMCR.SMS[2:0] 为100,这样在收到TI1FP1的触发信号就会将定时器复位。从而达到清零的目的。

涉及的寄存器如下:

AutoReset

此外,还可以实现定时器级联的效果,比如使用一个定时器作为另一个定时器的预分频。根据中文参考手册配置步骤如下:

MSPSC

除了上面提到的用法,定时器其实还要很多奇妙的用法。具体可以查询中文参考手册。中文参考手册很多东西写的其实非常详细了,就是初学者来说,可能很难耐心去阅读。这点真的要好好锤炼,中文都看不下去,更何况以后还要接触英文的。

定时器实现输入捕获的步骤

综上,可以总结出配置定时器输入部分的套路:

  1. 通过 TIMx_CCMR1.IC1F[7:4] 配置滤波器,选择其频率和采样次数。

  2. 通过 TIMx_CCER.CC1P[1] 配置要捕获的极性(上升沿还是下降沿)。

  3. 通过 TIMx_CCMR1.CC1S[1:0] 可以配置图123中,右边那个最大的选择器,选择三路的哪一路作为IC1的来源。

  4. 通过 TIMx_CCMR1.IC1PSC[3:2] 可以配置图123中,右边那个分频器的分频系数。

  5. 通过 TIMx_CCER.CC1E[0] 可以使能捕获输入。

定时器实现输入捕获的库函数实现

本节输入捕获实验会复用定时器输出PWM(输出在PB5口)的呼吸灯实验的代码,经过查表,会将原PB5端口输出的PWM信号使用杜邦线,引到PA0端口并且作为TIM2定时器输入。 IO口需要的配置如下:

GPIOCfg.

AFIO

核心代码如下:

void LunarInitTIM3() {GPIO_InitTypeDef GPIOB5_Cfg;TIM_TimeBaseInitTypeDef TIM3_Cfg;TIM_OCInitTypeDef TIM3_OCCfg;// 配置GPIO 	BEGIN// 开启复用时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 部分重映射GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);// 初始化GPIOB5为推挽复用输出RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIOB5_Cfg.GPIO_Mode = GPIO_Mode_AF_PP;GPIOB5_Cfg.GPIO_Pin = GPIO_Pin_5;GPIOB5_Cfg.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB, &GPIOB5_Cfg);// 配置GPIO 	END// 定时器时基配置   BEGIN// 打开TIM3所需要的时钟 APB1RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);TIM_TimeBaseStructInit(&TIM3_Cfg);// 配置使用内部时钟 72M HzTIM_InternalClockConfig(TIM3);// 这里配置定时器更新频率是1000HZTIM3_Cfg.TIM_CounterMode = TIM_CounterMode_Up;TIM3_Cfg.TIM_Period = 100 - 1;TIM3_Cfg.TIM_Prescaler = 720 - 1;TIM_TimeBaseInit(TIM3, &TIM3_Cfg);// 因为TIM_TimeBaseInit会置TIMx_EGR.UG[0]为1,产生一个更新事件,// 去同步影子寄存器的值,而该更新事件又会产生一个多余的中断,所以,// 我们需要在开启中断之前,手动清楚更新事件标志位TIM_ClearFlag(TIM3, TIM_FLAG_Update);// 定时器时基配置   END// 配置TIM3的PWM输出	BEGINTIM_OCStructInit(&TIM3_OCCfg);TIM3_OCCfg.TIM_OCMode = TIM_OCMode_PWM1;TIM3_OCCfg.TIM_OCPolarity = TIM_OCPolarity_High;TIM3_OCCfg.TIM_OutputState = TIM_OutputState_Enable;TIM3_OCCfg.TIM_Pulse = 80;TIM_OC2Init(TIM3, &TIM3_OCCfg);// 配置TIM3的PWM输出	END// 使能arr和ccr寄存器的影子功能TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM3, ENABLE);// 使能更新中断// TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);// 开启定时器TIM_Cmd(TIM3, ENABLE);
}void LunarInitTIM2() {GPIO_InitTypeDef GPIOA0_Cfg;TIM_TimeBaseInitTypeDef TIM2_Cfg;TIM_ICInitTypeDef TIM2_IC1Cfg, TIM2_IC2Cfg;// 配置GPIO 	BEGINRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIOA0_Cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIOA0_Cfg.GPIO_Pin = GPIO_Pin_0;GPIOA0_Cfg.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOA, &GPIOA0_Cfg);// 配置GPIO 	END// 定时器时基配置   BEGIN// 打开TIM2所需要的时钟 APB1RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructInit(&TIM2_Cfg);// 配置使用内部时钟 72M HzTIM_InternalClockConfig(TIM2);// 这里配置定时器更新频率是1000HZTIM2_Cfg.TIM_CounterMode = TIM_CounterMode_Up;// TIM2_Cfg.TIM_Period = 100 - 1;TIM2_Cfg.TIM_Period = 0xffff;TIM2_Cfg.TIM_Prescaler = 720 - 1;TIM_TimeBaseInit(TIM2, &TIM2_Cfg);TIM_ClearFlag(TIM2, TIM_FLAG_Update);// 定时器时基配置   END// 配置TIM2进行输入捕获		BEGINTIM_ICStructInit(&TIM2_IC1Cfg);TIM_ICStructInit(&TIM2_IC2Cfg);TIM2_IC1Cfg.TIM_Channel = TIM_Channel_1;TIM2_IC1Cfg.TIM_ICFilter = 0x4;TIM2_IC1Cfg.TIM_ICPolarity = TIM_ICPolarity_Rising;TIM2_IC1Cfg.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM2_IC1Cfg.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIM2, &TIM2_IC1Cfg);// 实现同时捕获上升下降沿。TIM2_IC2Cfg.TIM_Channel = TIM_Channel_2;TIM2_IC2Cfg.TIM_ICFilter = 0x4;TIM2_IC2Cfg.TIM_ICPolarity = TIM_ICPolarity_Falling;TIM2_IC2Cfg.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM2_IC2Cfg.TIM_ICSelection = TIM_ICSelection_IndirectTI;TIM_ICInit(TIM2, &TIM2_IC2Cfg);// 配置TIM2进行输入捕获		END// 利用从模式配置自动重置。TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1);TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);// 使能arr寄存器的影子功能	// ccr寄存器只读TIM_ARRPreloadConfig(TIM2, ENABLE);// 使能更新中断// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);// 开启定时器TIM_Cmd(TIM2, ENABLE);
}int main() {// 初始化串口LunarInitUSART1();// 初始化定时器LunarInitTIM3();LunarInitTIM2();SYSTick_Init();int dir = 0, cr = 0;while(1) {Delay_Ms(100);printf("PWM f = %d ", 100000 / (TIM_GetCapture1(TIM2) + 1));printf("PWM f = %f \n", (float)(TIM_GetCapture2(TIM2) + 1) / (TIM_GetCapture1(TIM2) + 1));}return 0;
}

实验结果就是从串口中,我们可以看到PB5输出的PWM波形的频率和占空比值。


本章完结

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

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

相关文章

浅谈自己用过最好用的AI工具概括

个人最经常用的AI工具的其实是Copilot,但是也有别的一些最好用的AI工具,包括: OpenAI GPT-3:这是一个自然语言生成模型,具有强大的语言理解和生成能力。它可以用于各种任务,如文字生成、自动回复和文本摘要…

brpc profiler

cpu profiler cpu profiler | bRPC MacOS的额外配置 在MacOS下,gperftools中的perl pprof脚本无法将函数地址转变成函数名,解决办法是: 安装standalone pprof,并把下载的pprof二进制文件路径写入环境变量GOOGLE_PPROF_BINARY_PA…

K8S快速入门

K8S快速入门 在学习k8s的过程,虽然官网给出的示例教程很简单,但是由于网络和环境的差异,导致实际操作的时候踩了很多坑,下面记录一下自己的操作步骤,方便需要的人参考,也方便以后的自己。 参考官网的资料…

Windows 10 中使用 Montreal-Forced-Aligner (MFA) 实现音频和文本强制对齐

文章目录 一、实现目标二、安装 Montreal-Forced-Aligner1、使用 Anaconda 虚拟环境2、修改默认下载路径3、安装 montreal-forced-aligner 及相关第三方包4、验证是否安装成功 三、下载声学模型和发音词典1、命令行方式下载2、手动方式下载 四、强制对齐1、准备音频及对应文本2…

短视频矩阵系统电脑端/手机版双端加盟saas技术源头开发

短视频矩阵系统是为了帮助用户更高效地管理、编辑、发布和分析短视频内容而设计的综合性平台。这种系统通常包含电脑端和手机端两个部分,每个部分都有其特定的功能模型,以适应不同设备的操作习惯和使用场景。以下是根据搜索结果中提供的信息,…

Debian是什么?有哪些常用命令

目录 一、Debian是什么? 二、Debian常用命令 三、Debian和CentOS的区别 四、Debian和CentOS的优缺点 五、Debian和CentOS的运用场景 一、Debian是什么? Debian是一种流行的开源Linux操作系统。 Debian是一个以Linux内核为基础的操…

vue3 element-plus表单form验证规则设置的require:true无效

必填项为空校验&#xff0c;valid第一次为true&#xff0c;再点值为false 引入FormInstance &#xff0c;校验代码改为以下&#xff1a; import { ElMessage, FormInstance } from element-plus const ruleFormRef ref<FormInstance>()const submitForm async (formEl:…

大模型市场爆发式增长,但生成式AI成功的关键是什么?

进入2024年&#xff0c;大模型市场正在爆发式增长。根据相关媒体的总结&#xff0c;2024年1-4 月被统计到的大模型相关中标金额已经达到2023年全部中标项目披露金额的77%左右&#xff1b;其中&#xff0c;从项目数量来看&#xff0c;应用类占63%、算力类占21%、大模型类占13%、…

(MATLAB)安装指南

参考链接&#xff1a;MATLAB2019a安装教程&#xff08;避坑版&#xff09;

软考中级-软件设计师(十)网络与信息安全基础知识

一、网络概述 1.1计算机网络的概念 计算机网络的发展&#xff1a;具有通信功能的单机系统->具有通信功能的多机系统->以共享资源为目的的计算机网络->以局域网及因特网为支撑环境的分布式计算机系统 计算机网络的功能&#xff1a;数据通信、资源共享、负载均衡、高…

社区智能奶柜:创业新机遇

社区智能奶柜&#xff1a;创业新机遇 在追求高质量生活的今天&#xff0c;健康食品成为大众焦点。社区智能奶柜适时登台&#xff0c;革新了居民获取新鲜牛奶的传统模式&#xff0c;为创业者开辟了一片蓝海市场。 一、新兴创业蓝海&#xff1a;牛奶随享站 日常膳食中&#xf…

uniapp 如何修改 IPA 文件信息页的本地化语言

实现效果&#xff1a; 最终会对应到苹果商店的语言&#xff1a; 例如微信的语言就有多个&#xff1a; 操作&#xff1a; 在 mainfest.json 源码视图中加入&#xff1a; 具体对应的语言key值可以参考Xcode中的语言代码 这个取决于打包后的 lproj 文件 将后缀ipa改成zip打开即…

MySQL —— 数据类型

一、数值类型 以上表格整理了用来表示数值类型的数据类型&#xff0c;其中&#xff0c;接下来将介绍和展示其中几个类型的使用和各种细节 1.tinyint 越界测试&#xff1a;建立一个包含tinyint类型的表格&#xff0c;插入各中数据去查看结果&#xff0c;并且尝试插入边界数据和…

【接地故障保护】剩余电流继电器及监控产品解决方案

安科瑞电气股份有限公司 祁洁 15000363176 一、产品型号 二、产品功能 1、对直接接触电击事故的防护 对直接接触电击事故的防护中&#xff0c;剩余电流继电器&#xff08;RCD&#xff09;只作为直接接触电击事故基本防护措施的补充保护措施&#xff08;不包括对相与相、相…

SQL注入实例(sqli-labs/less-1)

初始网页 从网页可知传递的参数名为 id&#xff0c;并且为数字类型 1、得知数据表有多少列 1.1 使用联合查询查找列数&#xff08;效率低&#xff09; http://localhost/sqli-labs-master/Less-1/?id1 union select 1,2 -- 1.2 使用order by查找列数&#xff08;效率高&…

OpenCV 入门(六) —— Android 下的人脸识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

思维导图怎么画?一文掌握绘制技巧

思维导图怎么画&#xff1f;你是不是还在为不知道怎么绘制思维导图而困惑&#xff1f;别担心&#xff0c;看完这篇文章就可以掌握绘制思维导图的基础步骤了。一起来看看吧&#xff01; 一、思维导图的基本结构 思维导图通常由中心节点、分支节点和子节点组成。中心节点是思维导…

VTK数据的读写--Vttk学习记录1--《VTK图形图像开发进阶》

读和写操作是VTK可视化管线两端相关的类--Reader和Writer类 Reader:将外部数据读入可视化管线&#xff0c;主要步骤如下 s1:实例化Reader对象 s2:指定所要读取的文件名 s3:调用Update()促使管线执行 对应的Writer: s1:实例化Writer对象 s2输入要写的数据以及指定写入的文…

PyRun_SimpleString(“import cv2“); 报错解决

#include <Python.h> #include <iostream>using namespace std;int main() {Py_Initialize();if (!Py_IsInitialized()){printf("初始化失败&#xff01;");return 0;}PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.ap…

0507华为od二面

只记录自己没回答上的问题 1、ZGC的缺点&#xff1a; 1)只是适用于32位系统 2)最大只是支持4TB内存容量 3)最糟糕的情况下吞吐量会下降15%&#xff0c;这都不是事至于吞吐量&#xff0c;通过扩容分分钟解决 4)分代的原因:不同对象的生命周期不相同&#xff0c;可能会扫描整个堆…