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标准库通用定时器输入捕获的更多相关文章

  1. 单片机stm32零基础入门之--初识STM32 标准库

    CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...

  2. STM32 标准库

    CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...

  3. stm32cube--通用定时器--输入捕获

    用定时器输入捕获做红外线接收实验.(此次试验以通道2为例) ①stm32cube配置 ② ③ ④程序中主要用到的输入捕获相关寄存器 uint16_t tim_sr,tim_ccer,tim_ccr; ...

  4. STM32标准库GPIO操作

    STM32标准库GPIO操作 STM32任何外围设备的使用都分为两部分:初始化和使用.体现在代码上就是:(1)有一个初始化函数(2)main函数中的使用 1.初始化GPIO 初始化GPIO函数代码: ...

  5. 初识STM32标准库

    1.CMSIS 标准及库层次关系 CMSIS 标准中最主要的为 CMSIS 核心层,它包括了: STM32标准库可以从官网获得: 在使用库开发时,我们需要把 libraries 目录下的库函数文件添加 ...

  6. STM32之定时器输入捕获

    1.输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能.STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿 ...

  7. stm32f103_高级定时器——输入捕获/输出比较中断+pwm=spwm生成

    ****************************首选我们了解一下它们的功能吧********************************************************** ...

  8. STM32 标准库V3.5启动文件startup_stm32f10xxx.s分析

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 前言 分析startu ...

  9. STM32 标准库3.5修改默认外部8M晶振为16M晶振

    ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...

  10. STM32 HAL库的定时器中断回调函数跟串口中断回调函数

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { //添加回调后的程序逻辑 if (htim->Instance == ...

随机推荐

  1. 【Jmeter】按比例分配Api压测

    先看 [Jmeter]基础介绍-详细 [Jmeter]Request1输出作为Request2输入-后置处理器 继续聊提出的第二个问题,即 2.需要按比例分配API请求并发,以模拟真实的API压力场景 ...

  2. 特定领域知识图谱融合方案:文本匹配算法之预训练Simbert、ERNIE-Gram单塔模型等诸多模型【三】

    特定领域知识图谱融合方案:文本匹配算法之预训练模型SimBert.ERNIE-Gram 文本匹配任务在自然语言处理中是非常重要的基础任务之一,一般研究两段文本之间的关系.有很多应用场景:如信息检索.问 ...

  3. 【六】强化学习之DQN---PaddlePaddlle【PARL】框架{飞桨}

    相关文章: [一]飞桨paddle[GPU.CPU]安装以及环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简 ...

  4. 【CSDN浏览器插件测评超详细版】——万能便捷的C功能,直接爱不释手,强烈推荐!更多功能等你探索

    我的界面预览: 1.下载安装 下载链接:https://plugin.csdn.net/?utm_source=chajian-contest-1210#/chrome-index-help 说明:若 ...

  5. uniapp面试题

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...

  6. 【奶奶看了都会】ChatGPT3.5接入企业微信,可连续对话

    1.连续对话效果 小伙伴们,这周ChatGPT放出大招,开放了GPT3.5的API.说简单点,就是提供了和ChatGPT页面对话一样模型的接口.而之前接的ChatGPT接口都是3.0,并不是真正的Ch ...

  7. CF1535

    A:氵 B:排序对两个偶数没影响,对两个奇数没影响.唯一的影响是可能原本偶数在后面,调到前面贡献变多.所以把所有偶数弄到前面就行. C:\(dp[i]\) 表示前 \(i\) 个字符以第 \(i\) ...

  8. .NET 团队公布.NET 9开发目标 并发布.NET9的首个预览版

    在一篇博文中我们对 .NET 9 的愿景[1]: .NET团队概述了.NET 9的开发目标和最终愿景,涵盖两大重点领域:云原生和智能应用程序开发.它在继.NET 8之后,继续强化对云原生应用和性能的支 ...

  9. MAYSQL 2 DAY

    目录 MySQL day02 1.关于查询结果集的去重? 2.连接查询 2.2.连接查询的分类? 2.4.怎么避免笛卡尔积现象?当然是加条件进行过滤. 2.5.内连接之等值连接:最大特点是:条件是等量 ...

  10. 轻松玩转makefile | 函数的使用

    前言 在上一篇文章中,尽管使用了变量和模式,但还是有不够好的地方,在Makefile中要指明每一个源文件,我们接下来利用函数对其进行优化,并介绍其他常用的一些函数. 依旧是以fun.c ,main.c ...