STM32单片机(六)TIM定时器 -> 第六节:TIM输入捕获练习(输入捕获模式测频率和PWMI模式测频率占空比)

news2025/4/5 14:16:34

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习STM32单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

STM3单片机安装软件、各种资料以及源码的路径:
链接:https://pan.baidu.com/s/1snD0uuTfMhchFqOMWvAiHA?pwd=asdf#list/path=%2F
提取码:asdf

链接里压缩包的解压密码:32

本大节主要学习TIM定时器的相关知识,包含八小节:
第一小节主要学习定时器基本定时的功能,第二小节是对第一小节的内容写两个程序进行练习,分别是定时器定时中断和定时器外部时钟;
第三小节主要学习定时器输出比较的功能,第四小节是对第三小节的内容写三个程序进行练习,分别是PWM驱动LED呼吸灯、PWM驱动舵机以及PWM驱动直流电机;
第五小节主要学习定时器输入捕获的功能,第六小节是对第五小节的内容写两个程序进行练习,分别是输入捕获模式测频率和PWMI模式测频率占空比;
第七小节主要学习定时器的编码器接口功能,第八小节是对第七小节的内容写一个程序进行练习,即编码器接口测速;
最终附上所有的源代码;

本小节是对第五小节TIM输入捕获的内容写两个程序进行练习,分别是输入捕获模式测频率和PWMI模式测频率占空比;

文章目录

  • 一、本节目标
    • 目标1:输入捕获模式测频率
    • 目标2:PWMI模式测频率占空比
  • 二、示例1:输入捕获模式测频率
    • 2.1 接线图
    • 2.2 程序源码
  • 三、示例2:PWMI模式测频率占空比
    • 3.1 接线图
    • 3.2 程序源码

一、本节目标

目标1:输入捕获模式测频率

本节目标是测量外部信号的频率;为了测量外部信号的频率,首先我们得有个外部信号源,产生一个频率和占空比可调的波形,但是考虑到大家可能没有信号发生器,所以本节就借用上一小节的代码,先用PWM模块,再PA0端口输出一个频率和占空比可调的波形,然后本节的代码,测量波形的输入口是PA6,所以直接用一根线,把PA0和PA6连在一起,这样就能测量自己PWM模块产生的波形的频率了; 如下图所示,OLED上显示的频率是1000Hz,说明通过PA6的测试,PA0输出的是一个1000Hz的信号;
在这里插入图片描述
看下代码里PA0输出频率部分:
在这里插入图片描述

这两行时设置PA0输出频率和占空比的参数调节部分,将PSC为720带入公式可得到Freq正好是1000;说明OLED显示是对的;

如果把720改为7200,则算得Freq为100Hz,看下现象:

在这里插入图片描述
如果再把7200改为3600,则算得Freq为200Hz,看下现象:

在这里插入图片描述

目标2:PWMI模式测频率占空比

OLED第一行显示频率,第二行显示占空比;
在这里插入图片描述
对应程序里设置的值,发现正好对应上
在这里插入图片描述

二、示例1:输入捕获模式测频率

2.1 接线图

在这里插入图片描述

示例1和示例2的接线是一样的,都是接一根线,从PA0到PA6;

实物接线图如下所示:
在这里插入图片描述

2.2 程序源码

代码路径:

  • STM32入门教程资料\程序源码\STM32Project\6-6 输入捕获模式测频率\User
  • STM32入门教程资料\程序源码\STM32Project\6-6 输入捕获模式测频率\Hardware

具体代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1, 1, "Freq:00000Hz");
	
	PWM_SetPrescaler(720 - 1);			//Freq = 72M / (PSC + 1) / 100
	PWM_SetCompare1(50);				//Duty = CCR / 100
	
	while (1)
	{
		OLED_ShowNum(1, 6, IC_GetFreq(), 5);
	}
}

IC.c

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);
}

void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}

三、示例2:PWMI模式测频率占空比

3.1 接线图

在这里插入图片描述
示例1和示例2的接线是一样的,都是接一根线,从PA0到PA6;

实物接线图如下所示:
在这里插入图片描述

3.2 程序源码

代码路径:

  • STM32入门教程资料\程序源码\STM32Project\6-7 PWMI模式测频率占空比\User
  • STM32入门教程资料\程序源码\STM32Project\6-7 PWMI模式测频率占空比\Hardware

具体代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1, 1, "Freq:00000Hz");
	OLED_ShowString(2, 1, "Duty:00%");
	
	PWM_SetPrescaler(720 - 1);			//Freq = 72M / (PSC + 1) / 100
	PWM_SetCompare1(50);				//Duty = CCR / 100
	
	while (1)
	{
		OLED_ShowNum(1, 6, IC_GetFreq(), 5);
		OLED_ShowNum(2, 6, IC_GetDuty(), 2);
	}
}

IC.c

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

uint32_t IC_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);
}

void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}

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

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

相关文章

docker inspect

docker inspect 命令用于获取有关 Docker 容器、镜像、网络等的详细信息。它提供了关于指定对象的元数据和配置的完整视图,包括运行状态、网络设置、卷挂载、环境变量等。 以下是一些常见的字段和属性,可以根据需要选择其中一些或全部列出: …

【算法与数据结构】202、LeetCode快乐数

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:先用一个dowhile循环计算整数各个位数字的平方和,然后在unordered_set里面插入n&#xff0…

C语言学习笔记:函数

✨博文作者:烟雨孤舟 💖 喜欢的可以 点赞 收藏 关注哦~~ ✍️ 作者简介: 一个热爱大数据的学习者 ✍️ 笔记简介:作为大数据爱好者,以下是个人总结的学习笔记,如有错误,请多多指教! 目录 简介 …

关于OpenCV中minAreaRect角度记录

一、问题引出 最近看到stackflow关于minAreaRect的讨论: MinAreaRect angles - Unsure about the angle returnedOpenCV’s RotatedRect angle does not provide enough information 大概问题是minAreaRect这个接口返回的角度信息不足以反应返回的旋转矩形的旋转…

appium辅助自动化工具-- Appium studio

这里我要给大家介绍一款appium辅助自动化测试工具appium studio,你没看错,不是android studio,也不是appium android studio,就是appium studio! 下载地址: Appium Studio | Digital.ai Continuous Test…

架构-计算机体系结构

章节架构 分值约 3 分 #mermaid-svg-nV7dvQlYnuXaOVOf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-nV7dvQlYnuXaOVOf .error-icon{fill:#552222;}#mermaid-svg-nV7dvQlYnuXaOVOf .error-text{fill:#552222;strok…

如何优雅的使用 React Context

在开始今天的文章之前,大家不妨先想一下触发 React 组件 re-render 的原因有哪些,或者说什么时候 React 组件会发生 re-render 。 先说结论: 状态变化父组件 re-renderContext 变化Hooks 变化 ❝ 这里有个误解:props 变化也会导致…

力扣日记2481

1. 题目 LeetCode 2481. 分割圆的最少切割次数 1.1 题意 可以使用直接或半径切分,管他叫一次切分,求切分圆为n等份的最少次数。 1.2 分析 可以想到,对圆做n等分,然后每个半径看出一次切分,这是最多次数,…

实验篇(7.2) 13. 站对站安全隧道 - 走对方宽带上网(FortiGate-IPsec) ❀ 远程访问

【简介】前面实验已经知道,FortiClient客户端拨号到远端防火墙,包括上网流量等所有流量都可以通过隧道到达远端防火墙,并从对方宽带上网。那么两台防火墙之间连接的安全隧道,可以实现这个功能吗? 实验要求与环境 OldMe…

uniapp中使用mixins(混入)使用

mixins 选项接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用的是和 Vue.extend() 一样的选项合并逻辑。也就是说,如果你的混入包含一个 created 钩子,而创建组…

虚拟网络namespace到bridge

前言 容器的网络是一大难点,不管是docker 还是kubernetes 都绕不开计算机网络。以下的介绍主要以计算机网络的namespace 和bridge 两个方面来展开介绍,方便深入理解容器的网络原理。 1.namespace分析 linux 支持六种资源的namespace :mount ns 、UTS ns…

HTML日期选择器:简化日期输入与交互

Date Picker 控件 HTML提供了<input>元素的type="date"属性,用于创建日期选择器(Date Picker)控件。日期选择器允许用户从一个交互式日历中选择日期值。以下是关于HTML日期选择器的详细解释: 创建日期选择器: 使用<input>元素,并将其type属性设置…

java从零开始系统性学习完整超全资源+笔记(下)

java从零开始系统性学习完整超全资源笔记&#xff08;下&#xff09; java从零开始系统性学习完整超全资源笔记&#xff08;上&#xff09; 文章目录 java从零开始系统性学习完整超全资源笔记&#xff08;下&#xff09;第十七章 泛型与常见数据结构ArrayListCollection接口的…

linux + lnmp + tp6部署项目问题集

部署完毕后&#xff0c;访问域名&#xff0c;报错502 Gateway 1:查看防火墙&#xff0c;需要的端口是否被关闭了&#xff0c;需要开启 vi /etc/sysconfig/iptables 发现有端口没空&#xff0c;就先i,然后把该端口后面的DROP改成ACCEPT&#xff0c;然后esc :wq 再回车&#xf…

轻松搞定文件复制备份,教你用快速的时间将文件复制另一个文件夹里并自动编号。

通常情况下&#xff0c;我们会将文件复制到另一个文件夹中&#xff0c;这很容易实现。但是如果需要将大量文件复制到同一个文件夹中&#xff0c;并且需要给每个文件自动编号&#xff0c;这时就需要用到一些技巧了。下面是一个简单的办法&#xff0c; 首先&#xff0c;第一步我…

node笔记_读写excel

文章目录 ⭐前言⭐安装依赖⭐读取excel&#x1f496; 按行读取&#x1f496; 按列读取 ⭐写入excel⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于node读取excel内容 往期文章 node_windows环境变量配置 node_npm发布包 linux_配置node node_nvm安装配置…

微服务开发系列 第十一篇:XXL-JOB

总概 A、技术栈 开发语言&#xff1a;Java 1.8数据库&#xff1a;MySQL、Redis、MongoDB、Elasticsearch微服务框架&#xff1a;Spring Cloud Alibaba微服务网关&#xff1a;Spring Cloud Gateway服务注册和配置中心&#xff1a;Nacos分布式事务&#xff1a;Seata链路追踪框架…

【AIGC】baichuan-7B大模型

百川智能&#xff5c;开源可商用的大规模预训练语言模型baichuan-7B大模型 概述 baichuan-7B 是由百川智能开发的一个开源可商用的大规模预训练语言模型。基于 Transformer 结构&#xff0c;在大约1.2万亿 tokens 上训练的70亿参数模型&#xff0c;支持中英双语&#xff0c;上…

day53_spring

今日内容 零、 复习昨日 零、 复习昨日 略 一、代理设计模式 代理的设计理念是限制对象的直接访问&#xff0c;即不能通过 new 的方式得到想要的对象&#xff0c;而是访问该对象的代理类。 这样的话&#xff0c;我们就保护了内部对象&#xff0c;如果有一天内部对象因为 某个原…

MIT 6.S081 (BOOK-RISCV-REV1)教材第三章内容

MIT 6.S081 教材第三章内容 引言页表分页硬件内核地址空间物理内存分配代码&#xff08;物理内存分配&#xff09;kinit函数kfree函数kalloc函数 代码&#xff1a;创建一个地址空间kvminit 函数kvmmap函数walk函数kvminithart函数procinit函数 进程地址空间代码&#xff1a;sbr…