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所需要的时钟 APB1
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	TIM_TimeBaseStructInit(&TIM3_Cfg);
	// 配置使用内部时钟 72M Hz
	TIM_InternalClockConfig(TIM3);

    // 这里配置定时器更新频率是1000HZ
	TIM3_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输出	BEGIN

	TIM_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 	BEGIN

	RCC_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所需要的时钟 APB1
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	TIM_TimeBaseStructInit(&TIM2_Cfg);
	// 配置使用内部时钟 72M Hz
	TIM_InternalClockConfig(TIM2);

    // 这里配置定时器更新频率是1000HZ
	TIM2_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进行输入捕获		BEGIN

	TIM_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.mfbz.cn/a/602310.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[C++基础编程]----预处理指令简介、typedef关键字和#define预处理指令之间的区别

目录 引言 正文 01-预处理指令简介 02-typedef关键字简介 03-#define预处理指令简介 04-#define预处理指令和typedef关键字的区别 (1)原理不同 (2)功能不同 &#xf…

【YOLOv8改进[Backbone]】使用SCINet改进YOLOv8在黑暗环境的目标检测效果

目录 一 SCINet 1 本文方法 ① 权重共享的照明学习 ② 自校准模块 ③ 无监督训练损失 二 使用SCINet助力YOLOv8在黑暗环境的目标检测效果 1 整体修改 2 配置文件 3 训练 其他 一 SCINet 官方论文地址:https://arxiv.org/pdf/2204.10137 官方代码地址&…

26_Scala集合常用API汇总

文章目录 1.mkString2.size,length,isEmpty,contains3.reverse ,length,distinct4.获取数据相关4.1数据准备4.2准确获取尾部last4.3 除了最后一个元素不要其他都要4.4从集合获取部分数据 5.删除数据5.1删除3个从左边5.2删除3个右边 6.切分数据splitAt(n:…

解决“您的连接不是私密连接”

目录 那么为什么会出现这样提示呢 https访问有什么不同 将http访问更改为https访问 当您在浏览网页时,遇到“您的连接不是私密连接”的提示,这通常表示浏览器认为您的连接不够安全。这是因为浏览器无法信任网站使用的SSL证书,或者网站没有…

【系统架构师】-UML-用例图(Use Case)

1、概述 用于表示系统功能需求,以及应用程序与用户或者与其他应用程序之间的交互关系。 2、组成 参与者(Actors):与系统交互的用户或其他系统。用一个人形图标表示。用例(Use Cases):系统需要…

平滑矢量图形综述:表示、创建、光栅化和图像矢量化的最新进展

摘要 平滑矢量图形领域探索了轻量级图像表示的表示、创建、光栅化和自动生成,常用于可缩放图像内容。过去几十年中,出现了多种概念性方法来表示具有平滑渐变的图像,每种方法都引发了独立的研究线索,包括流行的梯度网格和扩散曲线…

工程技术SCI期刊,中科院三区,一投就中,国人友刊!

一、期刊名称 Industrial Management & Data Systems 二、期刊简介概况 期刊类型:SCI 学科领域:工程技术 影响因子:5.5 中科院分区:3区 出版方式:订阅模式/开放出版 版面费:$4120 三、期刊征稿范…

QT功能 实现静态内容国际化实验

文章目录 第一步:新建一个QT工程第二步:添加控件第三步:在pro文件中添加内容第四步:更新文件第五步:打开QT的Linguist第六步:添加翻译内容第七步:回到QT Creator中添加文件第八步:给…

Colibri for Mac v2.2.0激活版:专业级无损音乐播放器

Colibri for Mac是一款专为Mac用户设计的高分辨率无损音乐播放器。它基于BASS技术构建,为用户带来极致的音频体验。Colibri支持所有流行的无损和有损音频格式,如FLAC、MP3、AAC等,确保音乐播放的清晰度和完美度。其独特的清晰比特完美播放技术…

月均互动超50万!“仪式感”何以盛行?小红书数据分析揭示消费动力

现代年轻人:“赚不到钱,却爱花钱买仪式感”。审慎消费的当下,“仪式感消费”不减反增,小红书平台相关内容更是持续火爆,成为品牌圈粉消费者的关键词。 这届小红书用户,热衷为“仪式感”氪金 “XX的第一杯奶…

【mysql】mysql单表查询、多表查询、分组查询、子查询等案例详细解析

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

常用的外贸软件有哪些

常用的外贸软件涵盖了多个方面,包括客户开发、订单管理、库存控制、客户关系管理(CRM)、财务管理以及跨境电商平台等。以下是一些代表性的外贸软件和平台: 客户开发与营销软件: 大镜山谷歌搜索大师易谷歌地图数据采集大师米贸搜 外贸管理软件 (ERP): 神卓…

【Kali Linux工具篇】使用Aircrack-ng破解wifi密码

前期准备 1、一个无线网卡 2、密钥爆破字典 实站过程 1、设置wlan为监听模式 airmon-ng start wlan0 #开启网卡wlan0监听模式 iwconfig #查看网卡状态,发现wlan0mon,表示已开启成功2、探测附近WiFi airdump-ng wlan0monBSSID 代表…

零售全渠道营销业务链分析,让企业管控能力大幅加强!

对于传统的、规模化的零售快消企业来讲,面临着很大的渠道管理和建设问题,如何尽快实现整个营销体系的全渠道数字化转型是当务之急、重中之重。 面对错综分散的经销商,零售快消企业订货流程会越复杂,加之对门店管理较为粗放&#…

技术速递|Java on VS Code 3月更新 - 大量 Spring 新功能!测试覆盖率功能正式发布!​

作者:Nick Zhu 排版:Alan Wang 大家好,欢迎来到2024年3月的 Visual Studio Code Java 更新!在本篇博客中,我们将分享大量 Spring 有关的新功能以及测试覆盖率的更新,让我们开始吧! Spring Boot…

【网络】网络层ICMP协议

🦄 个人主页——🎐开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁&am…

新建的springBoot WEB项目无法自动返回html模版(gradle+kotlin版本)

最近研究了springBoot创建web项目, 第一步服务端返回字符串没有问题,第二步返回html时,还是返回的字符串。 文章目录 一、参考方案二、新建springBoot web项目三、启动项目的三种方式 一、参考方案 将控制器类的 RestController 改为 Contro…

【JavaWeb】网上蛋糕商城后台-订单管理

概念 前面通过多篇文章以完全实现了用户在网上蛋糕商城平台上的所有功能和操作,从本文开始,实现网站的后台管理功能的介绍和操作。 订单列表 想要进入后台管理系统,则登入的用户一定是管理员账号,这个账号和密码只有管理员才知…

图搜索算法 - 拓扑排序

相关文章: 数据结构–图的概念 图搜索算法 - 深度优先搜索法(DFS) 图搜索算法 - 广度优先搜索法(BFS) 拓扑排序 概念 几乎所有的工程都可分为若干个称作活动的子工程,而这些子工程之间,通常受…

多个开源的js补环境框架测试

原文链接:https://mp.weixin.qq.com/s/uEMFGpE5bqmTvzSgX2twvA 前言 在做js逆向时肯定会遇到补环境的情况,看到github开源了好几个补环境用的框架,这篇文章做个测试,看看哪个比较好用。 https://github.com/pysunday/sdenvhttp…
最新文章