STM32标准库通用定时器输入捕获
STM32标准库定时器输入捕获
1.输入捕获介绍
输入捕获为STM32定时器的一个功能,可以用来测量输入信号的频率和占空比。
具体原理:当输入信号经过比较捕获通道时,STM32会依据通道的极性设置决定是否触发捕获中断TIM_IT_CCx。此时定时器会将当前计数值TIMx->CNT的值保存在TIMx->CCRx中,通过计算两次捕获中断的时间差便可计算出捕获的电平时长,由此可计算出输入信号的频率、周期、占空比等信息。
在本文中,使用野火指南者开发板,配置TIM2定时器的通道4为输入通道,TIM3定时器的通道1为输出通道。
2. 输入捕获通道与定时器初始化
需要引用头文件
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
void TIM2_Init() // 定时器2初始化
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); // 使能定时器2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 使能GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure; // 定义GPIO_InitTypeDef类型的结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; // 定义TIM_TimeBaseInitTypeDef类型的结构体
TIM_ICInitTypeDef TIM_IC_nitStructure; // 定义TIM_ICInitTypeDef类型的结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; // 选择通道4的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 设置通道4为浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度为50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); // 初始化GPIOA
TIM_TimeBaseInitStructure.TIM_Period = 1000-1; // 设置定时器2的自动重装值,计数到1000-1
TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1; // 设置定时器2的预分频值,分频720-1
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 设置计数器模式为向上计数
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); // 初始化定时器2
TIM_IC_nitStructure.TIM_Channel = TIM_Channel_4; // 选择通道4
TIM_IC_nitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 设置通道4的上升沿触发
TIM_IC_nitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 设置通道4的输入分频器
TIM_IC_nitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 设置通道4映射到TI4
TIM_IC_nitStructure.TIM_ICFilter = 0x00; // 设置通道4的滤波器
TIM_ICInit(TIM2,&TIM_IC_nitStructure); // 初始化定时器2的通道4
NVIC_InitTypeDef NVIC_InitStructure; // 定义NVIC_InitTypeDef结构体变量
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 选择定时器2的中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 设置中断优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 设置中断子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC_InitTypeDef结构体变量
TIM_ITConfig(TIM2,TIM_IT_CC4 | TIM_IT_Update ,ENABLE); // 使能定时器2的通道4的中断和更新中断
TIM_Cmd(TIM2,ENABLE); // 使能定时器2
}
需要注意输入通道引脚为GPIO_Mode_IN_FLOATING模式,TIM_Period为定时器溢出值。
TIM_ICInitTypeDef:输入捕获通道配置结构体。
TIM_Channel:输入通道,可选参数为TIM_Channel_x。
TIM_ICPolarity:输入通道极性设置,可选参数为TIM_ICSelection_DirectTI、TIM_ICSelection_IndirectTI、TIM_ICSelection_TRC。
TIM_ICSelection_DirectTI:将定时器输入通道1、2、3、4依次映射到IC1、IC2、IC3、IC4。
TIM_ICSelection_IndirectTI:将定时器输入通道1、2、3、4依次映射到IC2、IC1、IC4、IC3。
TIM_ICSelection_TRC:将定时器输入通道1、2、3、4连接至TRC我暂时也不知道这个TRC是啥。
TIM_ICFilter:输入通道滤波器设置,可选参数为0x0~0xF。决定了多少次边沿变换会触发一次输入捕获。
3. 中断函数编写
输入捕获中断与定时器中断共用一个中断NVIC。
uint16_t Up_Capture_Cnt,Down_Capture_Cnt,Up_Capture,Up_Capture_Cnt_Temp,Down_Capture;
uint16_t timer_cnt2,timer_cnt1 = 0;
uint16_t Get_State = 0,Get_State1 = 0;
void TIM2_IRQHandler() // 定时器2中断函数
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET) // 定时器2更新中断
{
timer_cnt1++; // 定时器计数标志量1每溢出一次加一
timer_cnt2++; // 定时器计数标志量2每溢出一次加一
if(timer_cnt1 == 10000) // 定时器计数标志量1溢出时清零
{
timer_cnt1 = 0; // 定时器计数标志量1清零
}
if(timer_cnt2 == 10000) // 定时器计数标志量2溢出时清零
{
timer_cnt2 = 0; // 定时器计数标志量2清零
}
}
if(TIM_GetITStatus(TIM2,TIM_IT_CC4) == SET) // 定时器2输入捕获中断
{
switch(Get_State) // 判断输入捕获状态
{
case 0 :
Up_Capture_Cnt_Temp = Up_Capture_Cnt; // 保存上一次输入捕获通道的值
Down_Capture_Cnt = TIM_GetCapture4(TIM2); // 获取当前输入捕获通道的值
Down_Capture = Down_Capture_Cnt + (timer_cnt2 * 1000) - Up_Capture_Cnt_Temp; // 计算脉冲宽度
timer_cnt1 = 0; // 定时器计数标志量1清零
timer_cnt2 = 0; // 定时器计数标志量2清零
TIM_ClearITPendingBit(TIM2,TIM_IT_CC4); // 清除输入捕获通道的中断标志位
TIM_OC4PolarityConfig(TIM2,TIM_ICPolarity_Falling); // 设置输入捕获通道的极性为下降沿
Get_State = 1; // 设置输入捕获通道的状态为1
break; // 跳出switch语句
case 1:
Up_Capture_Cnt = TIM_GetCapture4(TIM2); // 获取当前输入捕获通道的值
Up_Capture = Up_Capture_Cnt + (timer_cnt1 * 1000) - Down_Capture_Cnt; // 计算脉冲宽度
timer_cnt1 = 0; // 定时器计数标志量1清零
timer_cnt2 = 0; // 定时器计数标志量2清零
TIM_ClearITPendingBit(TIM2,TIM_IT_CC4); // 清除输入捕获通道的中断标志位
TIM_OC4PolarityConfig(TIM2,TIM_ICPolarity_Rising); // 设置输入捕获通道的极性为上升沿
Get_State = 0; // 设置输入捕获通道的状态为0
break; // 跳出switch语句
}
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); // 清除定时器溢出中断标志位
}
4. 中断函数代码具体逻辑解释
光看代码可能捋不清先后关系,来看下图就知道了,如图1所示:

在图中可以看到,当输入捕获通道的信号周期要长于输入捕获的通道时钟周期时,会导致第二次读取的值比第一次读取的值小,如果不使用定时器溢出次数进行辅助运算会导致算出来的是负数。之后第一次读取的值+溢出时间-第二次读取的值,得到的结果就是脉冲宽度,第二次读取的值+溢出时间-第一次读取的值,得到的就是周期中另一部分的宽度。有了这些信息,就可以得到频率、周期和占空比了。
STM32标准库通用定时器输入捕获的更多相关文章
- 单片机stm32零基础入门之--初识STM32 标准库
CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...
- STM32 标准库
CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...
- stm32cube--通用定时器--输入捕获
用定时器输入捕获做红外线接收实验.(此次试验以通道2为例) ①stm32cube配置 ② ③ ④程序中主要用到的输入捕获相关寄存器 uint16_t tim_sr,tim_ccer,tim_ccr; ...
- STM32标准库GPIO操作
STM32标准库GPIO操作 STM32任何外围设备的使用都分为两部分:初始化和使用.体现在代码上就是:(1)有一个初始化函数(2)main函数中的使用 1.初始化GPIO 初始化GPIO函数代码: ...
- 初识STM32标准库
1.CMSIS 标准及库层次关系 CMSIS 标准中最主要的为 CMSIS 核心层,它包括了: STM32标准库可以从官网获得: 在使用库开发时,我们需要把 libraries 目录下的库函数文件添加 ...
- STM32之定时器输入捕获
1.输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能.STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿 ...
- stm32f103_高级定时器——输入捕获/输出比较中断+pwm=spwm生成
****************************首选我们了解一下它们的功能吧********************************************************** ...
- STM32 标准库V3.5启动文件startup_stm32f10xxx.s分析
layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 前言 分析startu ...
- STM32 标准库3.5修改默认外部8M晶振为16M晶振
ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...
- STM32 HAL库的定时器中断回调函数跟串口中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { //添加回调后的程序逻辑 if (htim->Instance == ...
随机推荐
- windows共享文件创建----局域网办公
一.共享文件设置 1.选择要共享的文件夹-----右键点击属性--------在上方选项栏选择共享----然后点击"高级共享" 2.勾选"共享此文件夹"---- ...
- 【6】opencv采用映射技术实现鱼眼镜头校正和鱼眼镜头还原全景图。
相关文章: [1]windows下安装OpenCV(4.3)+VS2017安装+opencv_contrib4.3.0配置 [2]Visual Studio 2017同时配置OpenCV2.4 以及O ...
- 8.2 C++ 引用与取别名
C/C++语言是一种通用的编程语言,具有高效.灵活和可移植等特点.C语言主要用于系统编程,如操作系统.编译器.数据库等:C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统.图形用户界面 ...
- 驱动开发:通过SystemBuf与内核层通信
内核层与应用层之间的数据交互是必不可少的部分,只有内核中的参数可以传递给用户数据才有意义,一般驱动多数情况下会使用SystemBuf缓冲区进行通信,也可以直接使用网络套接字实现通信,如下将简单介绍通过 ...
- 【奶奶看了都会】ComfyUI+SVD制作AI视频教程,附效果演示
AI一天,人间一年 大家好啊,我是小卷,最近AI绘画又发展出一些新玩意了,小卷因为工作的关系有一个月没关注AI的发展了,都有点跟不上版本节奏了... 1.comfyui的使用效果 今天给大家介绍下AI ...
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第10章)-- 读书笔记
第 10 章 部署 10.1 部署到 IIS ASP.NET Core 应用程序支持部署到 IIS 中,之后它将作为应用程序的反向代理服务器和负载均衡器,向应用程序中转传入的 HTTP 请求 默认情况 ...
- C#开源免费的Windows右键菜单管理工具
前言 今天分享一个C#开源.免费.纯粹的Windows右键菜单管理工具:ContextMenuManager. 工具主要功能 程序支持国际化多语言显示. 启用或禁用文件.文件夹.新建.发送到.打开方式 ...
- Codeforces Round #884 (Div. 1 + Div. 2) A-E
比赛链接 A 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { i ...
- YOLOV3目标检测模型训练实例
YOLOV3目标检测 从零开始学习使用keras-yolov3进行图片的目标检测,比较详细地记录了准备以及训练过程,提供一个信号灯的目标检测模型训练实例,并提供相关代码与训练集. DEMO测试 YOL ...
- win32 - 富文本控件的文本突出显示和文本撤销
#define UNICODE #define _UNICODE #include <tchar.h> #include <windows.h> #include <wi ...