【STM32单片机】#7 定时器输入捕获

主要参考学习资料:

B站@江协科技

STM32入门教程-2023版 细致讲解 中文字幕

开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwd=dspb

单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协

实验:

  • 输入捕获模式测频率
  • PWMI模式测频率占空比

新函数:

  • 定时器库函数(输入捕获和主从触发模式部分)

目录

  • 输入捕获简介
  • 频率测量
  • 输入捕获通道
  • 主从触发模式
  • 输入捕获基本结构
  • PWMI基本结构
  • 函数详解
    • TIM_ICInit函数
      • TIM_ICInitTypeDef结构体
    • TIM_PWMIConfig函数
    • TIM_ICStructInit函数
    • TIM_SelectInputTrigger函数
    • TIM_SelectOutputTrigger函数
    • TIM_SelectSlaveMode函数
    • TIM_SetICxPrescaler函数
    • TIM_GetCapturex函数
  • 实验13 输入捕获模式测频率
    • 接线图
    • PWM驱动
    • 输入捕获驱动
    • 主程序
  • 实验14 PWMI模式测频率占空比
    • 输入捕获驱动
    • 主程序

输入捕获简介

  • IC(Input Capture)输入捕获
  • 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。
  • 每个高级定时器和通用定时器都拥有4个输入捕获通道。
  • 可配置为PWMI模式,同时测量频率和占空比。
  • 可配合主从触发模式,实现硬件全自动测量。

频率测量

  • 测频法:在闸门时间T内,对上升沿计次,得到N,则频率 f x = N / T f_x=N/T fx=N/T,适合测高频信号,数据相对稳定。
  • 测周法:两个上升沿内,以标准频率 f C f_C fC计次,得到 N N N,则频率 f x = f c / N f_x=f_c/N fx=fc/N,适合测低频信号,数据跳变快。
  • 中界频率:测频法与测周法误差相等(N相等)的频率点 f m = f C / T f_m=\sqrt{f_C/T} fm=fC/T ,是选择测频法还是测周法的依据。

定时器外部时钟和对射式红外传感器计次的代码稍加改进,间隔相同时间读取次数并清零即为测频法。本节输入捕获采用测周法。

输入捕获通道

滤波器接收来自引脚的输入TI1并对其进行滤波后输出TI1F, f D T S f_{DTS} fDTS为滤波器采样时钟来源,TIMx_CCMR1寄存器的ICF可以控制滤波器的参数,滤波器以采样频率对输入信号采样,当连续N个值都为高电平,输出才为高电平,当连续N个值都为低电平,输出才为低电平,否则输出保持不变。

滤波后的信号通过边沿检测器捕获上升沿或下降沿,TIMx_CCER寄存器的CC1P可以选择极性,最终得到TI1FP1触发信号,与来自通道2的触发信号一同经过数据选择器,由CC1S进行选择。每个输入捕获通道都有两条独立的滤波器和边沿检测器路线,一路连接当前通道后续电路,另一路连接其他通道后续电路,由此实现一个通道灵活切换两个引脚和两个通道同时捕获一个引脚的功能,其中CH1和CH2交叉,CH3和CH4交叉。

被选择的触发信号继续通过由ICPS控制的分频器,最后CC1E控制输出使能或失能。如果使能,则触发信号可以将CNT的值转运到CCR中。每捕获一次CNT的值,都要将CNT清零以进行下一次捕获,在硬件电路中由TI1FP1到从模式控制器的映射自动完成。

主从触发模式

主从触发模式是主模式、从模式和触发源选择三个功能的简称。主模式将定时器内部信号映射到TRGO引脚,用于触发别的外设。从模式将其他外设或者自身外设的信号映射到TRGI引脚,用于控制自身定时器的运行。触发源选择用于选择从模式的触发信号源,从模式从列表中选择一项执行。输入捕获CNT自动清零即通过TI1FP1信号触发从模式的Reset操作实现(只有通道1和通道2可以,通道3和通道4需在中断函数手动清零)。信号的具体解释参见芯片数据手册。

输入捕获基本结构

使用输入捕获基本结构测量频率,测频法的标准频率即为系统时钟经过预分频后计数器自增的时钟频率。GPIO口输入方波信号,通过滤波器和边沿检测,选择上升沿触发,直连当前通道,分频器不分频。同时触发源选择选择TI1FP1为触发信号,从模式选择复位操作。电路工作时,CCR1的值始终保持为最新一个周期的计数值,即测频法中的N,再计算 f C / N f_C/N fC/N即可得到输入频率。

PWMI基本结构

PWMI模式使用两个通道同时捕获一个引脚,可以同时测量频率和占空比。TI1FP1和输入捕获基本结构中一样,TI1FP2则配置为下降沿触发,通过交叉通道触发通道2的捕获单元。此时CCR2捕获高电平期间的计数值,但不触发清零,CNT继续计数直至上升沿被CCR1捕获到一个周期的计数值,CNT清零。占空比为CCR2/CCR1。

函数详解

TIM_ICInit函数

简介:配置输入捕获单元(单一通道)。

参数一:定时器名称

参数二:指向初始化信息TIM_ICInitTypeDef结构体的指针

TIM_ICInitTypeDef结构体

成员TIM_Channel:输入捕获通道

TIM_Channel_1, ..., TIM_Channel_4

成员TIM_ICFilter:滤波器

成员TIM_ICPolarity:极性

TIM_ICPolarity_Rising, TIM_ICPolarity_Falling, TIM_ICPolarity_BothEdge

成员TIM_ICPrescaler:分频器

TIM_ICPSC_DIV1, TIM_ICPSC_DIV2, TIM_ICPSC_DIV4, TIM_ICPSC_DIV8

成员TIM_ICSelection:数据选择器

TIM_ICSelection_DirectTI(直连通道输入)
TIM_ICSelection_IndirectTI(交叉通道输入)
TIM_ICSelection_TRC(暂时不用)

TIM_PWMIConfig函数

简介:配置输入捕获单元(PWMI模式,限通道1和通道2),函数自动为另一个通道初始化为相反的配置。

参数一:定时器名称

参数二:指向初始化信息TIM_ICInitTypeDef结构体的指针

TIM_ICStructInit函数

简介:给TIM_ICInitTypeDef结构体赋默认值。

参数:指向初始化信息TIM_ICInitTypeDef结构体的指针

TIM_SelectInputTrigger函数

简介:选择输入触发源TRGI。

参数一:定时器名称

参数二:TRGI触发源

TIM_TS_触发源名称

TIM_SelectOutputTrigger函数

简介:选择输出触发源TRGO。

参数一:定时器名称

参数二:TRGO触发源

TIM_TRGOSource_触发源名称

TIM_SelectSlaveMode函数

简介:选择从模式。

参数一:定时器名称

参数二:从模式

TIM_SlaveMode_从模式名称(列表后四个)

TIM_SetICxPrescaler函数

简介:单独配置通道x的分频器(x可选1、2、3、4)。

参数一:定时器名称

参数二:分频器

TIM_GetCapturex函数

简介:读取通道x的CCR(x可选1、2、3、4)。

实验13 输入捕获模式测频率

接线图

在没有信号发生器的情况下,我们使用PA0口输出方波信号,由PA6口测量。

PWM驱动

PWM驱动沿用实验10,新增了调节频率函数。

PWM.h

#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);#endif

PWM.c

#include "stm32f10x.h" void PWM_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//固定ARR为100-1,此时PSC调节频率,CCR调节占空比TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;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;TIM_OC1Init(TIM2, &TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}//配置CCR改变占空比
void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}//配置PSC改变频率
void PWM_SetPrescaler(uint16_t Prescaler)
{//由于要求不高,PSC使用无预装模式TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}

输入捕获驱动

由于同一通道不能同时输入捕获和输出比较,输入捕获我们使用TIM3。

IC.h

#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);#endif

IC.c

#include "stm32f10x.h"void IC_Init(void)
{//配置PA6(TIM3的CH1引脚)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);//配置TIM3的时基单元RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);TIM_InternalClockConfig(TIM3);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//ARR设大,防止计数器溢出TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;//标准频率1MHz,根据信号频率分布范围调整TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;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 = 0x0F;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);//配置TRGI触发源TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//配置从模式ResetTIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);TIM_Cmd(TIM3, ENABLE);
}//读取并计算频率
uint32_t IC_GetFreq(void)
{//实测CCR总是会少1,此处做补偿return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

主程序

#include "stm32f10x.h" 
#include "Delay.h"
#include "PWM.h"
#include "OLED.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1, 1, "Freq:00000Hz");//频率Freq = 72M / (PSC + 1) / 100PWM_SetPrescaler(720 - 1);//占空比Duty = CCR / 100PWM_SetCompare1(50);while(1){OLED_ShowNum(1, 6, IC_GetFreq(), 5);}
}

实验14 PWMI模式测频率占空比

接线图、PWM驱动同实验13,输入捕获驱动新增配置PWMI模式和获取占空比函数。

输入捕获驱动

IC.h

#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);#endif

IC.c

#include "stm32f10x.h"void IC_Init(void)
{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);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);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;TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;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 = 0x0F;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);//配置PWMI模式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);
}

主程序

#include "stm32f10x.h" 
#include "Delay.h"
#include "PWM.h"
#include "OLED.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%");//频率Freq = 72M / (PSC + 1) / 100PWM_SetPrescaler(720 - 1);//占空比Duty = CCR / 100PWM_SetCompare1(50);while(1){OLED_ShowNum(1, 6, IC_GetFreq(), 5);OLED_ShowNum(2, 6, IC_GetDuty(), 2);}
}

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

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

相关文章

【android bluetooth 框架分析 01】【关键线程 3】【bt_jni_thread 线程介绍】

1. bt_jni_thread 职责介绍 bt_jni_thread 这个线程的作用是专门负责处理蓝牙 JNI 层的消息循环,也可以说是 C 层和 Java 层交互的桥梁线程。 1.1 什么是 JNI 层?为什么需要这个线程? JNI(Java Native Interface)是 …

基于视觉语言模型的机器人实时探索系统!ClipRover:移动机器人零样本视觉语言探索和目标发现

作者:Yuxuan Zhang 1 ^{1} 1, Adnan Abdullah 2 ^{2} 2, Sanjeev J. Koppal 3 ^{3} 3, and Md Jahidul Islam 4 ^{4} 4单位: 2 , 4 ^{2,4} 2,4佛罗里达大学电气与计算机工程系RoboPI实验室, 1 , 3 ^{1,3} 1,3佛罗里达大学电气与计算机工程系F…

SpringBoot和微服务学习记录Day2

微服务 微服务将单体应用分割成更小的的独立服务,部署在不同的服务器上。服务间的关联通过暴露的api接口来实现 优点:高内聚低耦合,一个模块有问题不影响整个应用,增加可靠性,更新技术方便 缺点:增加运维…

网站集群批量管理-Ansible剧本与变量

复盘内容:链接指北 查看ansible命令文档 ansible-doc -s systemd一、剧本 何为剧本: playbook 文件,用于长久保存并且实现批量管理,维护,部署的文件. 类似于脚本存放命令和变量 剧本yaml格式,yaml格式的文件:空格,冒号. 剧本未来我们批量管理,运维必会的内容. …

如何在Dify中安装运行pandas、numpy库(离线、在线均支持,可提供远程指导)

pandas和numpy这两个库是数据科学和数据分析中经常使用的工具包,原生的Dify无法直接使用这两个库,需要手动安装后才可以使用。本文将介绍如何在Dify中安装pandas和numpy,并在代码执行节点中运行使用pandas和numpy。 Dify的代码执行节点中的py…

Helm核心概念与常见操作介绍

在管理Kubernetes集群里的应用时,Helm能帮上大忙,它把应用的部署、升级和管理变得简单多了,有如是Kubernetes的 “应用商店”。 Helm的三个重要概念 三大概念最直接的理解:Helm 安装 charts 到 Kubernetes 集群中,每…

rkmpp 解码 精简mpi_dec_test.c例程

rkmpp 解码流程(除 MPP_VIDEO_CodingMJPEG 之外) 源码 输入h264码流 输出nv12文件 /** Copyright 2015 Rockchip Electronics Co. LTD** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file exce…

用一个实际例子快速理解MCP应用的工作步骤

已经有很多的文章介绍MCP server,MCP Client工作原理,这里不做太多介绍。但是很多介绍都只是侧重介绍概念,实际的工作原理理解起来对初学者还是不太友好。本文以一个智能旅游咨询系统为例,详细说明在利用 Model Context Protocol&…

【LeetCode 题解】数据库:1321.餐馆营业额变化增长

一、问题描述 本题给定了一个名为 Customer 的表,记录了餐馆顾客的交易数据,包括顾客 ID、姓名、访问日期和消费金额。作为餐馆老板,我们的任务是分析营业额的变化增长情况,具体来说,就是计算以 7 天(某日…

【Python】读取xlsb或xlsx的单一或连续单元格工具类

代码主要来自Kimi.ai,有修改。 优先使用工作表序号索引工作表,序号从1开始。 运行需要先安装openpyxl和pyxlsb两个第三方库。 import openpyxl from openpyxl.utils import range_boundaries from pyxlsb import open_workbook as open_xlsbclass Exc…

【蓝桥杯】动态规划:背包问题

这篇文章主要记录动态规划方面的学习。 动态规划的核心思想: 把大问题分解成小问题,记住小问题的解,避免重复计算。 动态规划(DP)的三大特点: ①最优子结构:大问题的最优解可以由小问题的最优解推导出来 ②重叠子问题:在求解过程中会反复遇到相同的小问题 ③无后效…

华为数字芯片机考2025合集1已校正

单选 1.以下低功耗措施中,哪种不是降低电路翻转率的方法? A.在不进行算术运算的时候,使这些模块的输入保持不变,不让新的操作数进来 B.采用Gray 码或One‐hot 码作为状态机编码 C.减少电路中的glitch D.重新安排“if‐else”表达…

React 列表渲染

开发环境:Reacttsantd 你可能经常需要通过 JavaScript 的数组方法 来操作数组中的数据,从而将一个数据集渲染成多个相似的组件。在这篇文章中,你将学会如何在 React 中使用 filter() 筛选需要渲染的组件和使用 map() 把数组转换成组件数组。 …

力扣刷题DAY11(动态规划-线性DP)

一、最长上升子序列 300. 最长递增子序列 &#xff08;一&#xff09;初版代码 class Solution { public:int lengthOfLIS(vector<int>& nums) {int n nums.size();vector<int> f(n 1, 1); //初始化为1&#xff0c;因为每个数至少可以作为一个单独的序列in…

DFS--

数字的全排列 #include <bits/stdc.h> using namespace std;//最大的排列数目 const int N10; int n; //存储排列的路径 int path[N]; //标记数字是否已经被使用 bool st[N];void dfs(int u){//到达递归边界&#xff0c;输出一个排列if(un){//输出循环for(int i0; i<…

栈与队列及其基础应用

一.栈 1.栈的定义 栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。其结构可以参考羽毛…

openEuler-22.03-LTS-SP3 编译安装 Greenplum-db 6.20.0

openEuler-22.03-LTS-SP3 编译安装 Greenplum-db 6.20.0 1、配置 yum 华为源2、安装依赖3、源码安装 openssl 1.0.1u3.1、openssl 1.1.1 降级到 openssl 1.0.1 4、源码安装 python 2.75、使用 pip3 安装 Python 相关依赖6、编译安装 Greenplum-db 6.20.06.1、修改配置6.2、基于…

机器学习02——概要

一、简介 机器学习是一门在没有明确编程的情况下让计算机学习的科学。 监督学习是有目标的&#xff0c;输入数据对应明确的输出&#xff1b;无监督学习则是“探索”型的&#xff0c;模型的目标是从数据中发现潜在的模式或结构&#xff0c;而不需要预先知道标签。 二、机器学…

swift-08-属性、汇编分析inout本质

一、Swift中跟实例相关的属性可以分为2大类 1.1 存储属性&#xff08; Stored Property&#xff09; 类似于成员变量这个概念 存储在实例的内存中 结构体、类可以定义存储属性 枚举不可以定义存储属性&#xff08;因为枚举只存储关联值和case&#xff09; 1.2 计算属性&am…

【HarmonyOS Next之旅】DevEco Studio使用指南(十二)

目录 1 -> Code Linter代码检查 2 -> 配置代码检查规则 3 -> 查看/处理代码检查结果 1 -> Code Linter代码检查 Code Linter针对ArkTS/TS代码进行最佳实践/编程规范方面的检查。 可根据扫描结果中告警提示手工修复代码缺陷&#xff0c;或者执行一键式自动修复…