STM32输入捕获详解

目录

一、引言

二、输入捕获原理

三、寄存器介绍

四、配置步骤 

1.开启时钟

2.GPIO 初始化

3.初始化定时器

4.配置输入捕获模式

5.使能捕获和更新中断

6.设置中断分组并编写中断服务函数

 7.使能定时器

五、程序示例

六、总结


一、引言

        在嵌入式系统开发中,STM32 系列微控制器因其强大的性能和丰富的功能被广泛应用。其中,输入捕获功能是 STM32 定时器的一个重要特性,它可以用来测量外部信号的周期、频率和占空比等参数,在电机控制、速度测量、通信同步等众多领域都有着重要的应用。本文将详细介绍 STM32 的输入捕获功能,包括其原理、配置步骤以及程序示例。

二、输入捕获原理

STM32 的输入捕获,简单来说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿/上升沿和下降沿均触发)的时候,将当前定时器计数器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断或 DMA 等操作。

例如,我们要测量一个高电平脉冲的宽度,首先设置定时器通道为上升沿捕获,在上升沿到来时,会捕获到当前的 TIMx_CNT 值,然后立即清零 TIMx_CNT,并设置通道为下降沿捕获,当下降沿到来时,又会发生捕获事件,得到此时的 TIMx_CNT 值。这样,前后两次 TIMx_CNT 的差值,就是高电平的脉宽。如果脉宽比较长,定时器可能会产生多次溢出,这就需要我们对定时器溢出进行处理,以保证测量结果的准确性。

三、寄存器介绍

  1. TIMx_ARR:自动重装载寄存器,用来设置定时器的计数周期。当定时器计数器的值达到 ARR 的值时,会重新从 0 开始计数。
  2. TIMx_PSC:预分频寄存器,用于对定时器的时钟源进行分频,以得到合适的计数频率。
  3. TIMx_CCMR1:捕获/比较模式寄存器 1,用于配置输入捕获的通道方向、触发极性、输入分频等参数。
  4. TIMx_CCER:捕获/比较使能寄存器,用来使能或禁止捕获/比较通道的输入捕获功能。
  5. TIMx_DIER:DMA/中断使能寄存器,用于开启或关闭捕获/比较通道的中断或 DMA 请求。
  6. TIMx_CR1:控制寄存器 1,用于控制定时器的启动、停止、计数模式等。
  7. TIMx_CCR1:捕获/比较寄存器 1,用来存储捕获发生时的 TIMx_CNT 值。

四、配置步骤 

以下是以 STM32F4 为例,配置输入捕获的一般步骤:

1.开启时钟

  • 开启定时器的时钟。例如,如果要使用 TIM5,需要调用 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE) 来使能 TIM5 的时钟。
  • 开启对应 GPIO 引脚的时钟。例如,如果捕获信号连接到 PA0 引脚,需要调用 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) 来使能 GPIOA 的时钟。

2.GPIO 初始化

  • 将捕获信号对应的 GPIO 引脚配置为复用功能。例如,如果使用 TIM5 的通道 1 捕获信号,且信号连接到 PA0 引脚,需要将 PA0 引脚配置为复用功能,并设置复用功能为 AF2(具体的复用功能值根据芯片手册确定)。
  • 根据需要配置 GPIO 引脚的上拉、下拉电阻等。

 

3.初始化定时器

        设置 TIM_TimeBaseInitTypeDef 结构体的参数,包括自动重装载值 TIM_Period、预分频值 TIM_Prescaler、计数模式 TIM_CounterMode 等。例如,如果要设置定时器的计数周期为 1000,预分频值为 7199(使得定时器的计数频率为 10kHz),计数模式为向上计数,可以这样设置:

 如果需要,可以设置定时器的重复计数器值 TIM_RepetitionCounter,该参数在高级定时器中使用较多。

4.配置输入捕获模式

        设置 TIM_ICInitTypeDef 结构体的参数,包括捕获通道 TIM_Channel、触发极性 TIM_ICPolarity、输入选择 TIM_ICSelection、输入分频 TIM_ICPrescaler、输入滤波 TIM_ICFilter 等。例如,如果要配置 TIM5 的通道 1 为上升沿捕获,不分频,不滤波,可以这样设置:

IM_ICInitTypeDef TIM5_ICInitStructure;
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);

5.使能捕获和更新中断

如果需要在捕获事件发生时产生中断,需要调用 TIM_ITConfig 函数开启捕获中断和更新中断。例如:

TIM_ITConfig(TIMx, TIM_IT_Update | TIM_IT_CC1, ENABLE);

6.设置中断分组并编写中断服务函数

设置中断分组,通常使用 NVIC_Init 函数来完成。中断分组的设置决定了中断的优先级。

在中断服务函数中,需要判断中断类型,并进行相应的数据处理。例如,如果是捕获中断,需要读取捕获寄存器的值;如果是更新中断,可能需要处理定时器溢出等情况。以下是一个简单的中断服务函数示例:

void TIMx_IRQHandler(void)
{
    if (TIM_GetITStatus(TIMx, TIM_IT_Update)!= RESET)
    {
        // 处理更新中断
    }
    if (TIM_GetITStatus(TIMx, TIM_IT_CC1)!= RESET)
    {
        // 处理捕获中断
        // 读取捕获寄存器的值,进行数据处理
        uint16_t captureValue = TIM_GetCapture1(TIMx);
        // 清除中断标志位
        TIM_ClearITPendingBit(TIMx, TIM_IT_CC1 | TIM_IT_Update);
    }
}

 7.使能定时器

调用 TIM_Cmd 函数使能定时器,开始输入捕获。例如:

TIM_Cmd(TIMx, ENABLE);

 

五、程序示例

以下是一个完整的 STM32 输入捕获程序示例,用于测量 PA0 引脚上输入信号的高电平脉宽,并通过串口打印结果:

#include "stm32f4xx.h"
#include <stdio.h>

// 定义捕获状态和捕获值变量
volatile uint8_t TIM5CH1_CAPTURE_STA = 0;
volatile uint16_t TIM5CH1_CAPTURE_VAL = 0;

// 定时器 5 中断服务函数
void TIM5_IRQHandler(void)
{
    if ((TIM5CH1_CAPTURE_STA & 0X80) == 0) // 还未成功捕获
    {
        if (TIM_GetITStatus(TIM5, TIM_IT_Update)!= RESET) // 检测是否发生更新中断
        {
            if (TIM5CH1_CAPTURE_STA & 0X40) // 已经捕获到高电平
            {
                if ((TIM5CH1_CAPTURE_STA & 0X3F) == 0X3F) // 定时器溢出
                {
                    TIM5CH1_CAPTURE_STA |= 0X80; // 标记为成功捕获
                    TIM5CH1_CAPTURE_VAL = 0XFFFF;
                }
                else
                {
                    TIM5CH1_CAPTURE_STA++; // 对溢出次数进行计数
                }
            }
        }
        if (TIM_GetITStatus(TIM5, TIM_IT_CC1)!= RESET) // 判断是否发生捕获事件
        {
            if (TIM5CH1_CAPTURE_STA & 0X40) // 如果已经捕获到上升沿
            {
                // 捕获到下降沿,计算脉宽
                TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);
                TIM5CH1_CAPTURE_STA |= 0X80; // 标记为成功捕获
            }
            else
            {
                // 捕获到上升沿,记录当前定时器值,并设置为下降沿捕获
                TIM_SetCounter(TIM5, 0);
                TIM5CH1_CAPTURE_STA = 0X40;
                TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);
            }
        }
    }
    // 清除中断标志位
    TIM_ClearITPendingBit(TIM5, TIM_IT_CC1 | TIM_IT_Update);
}

int main(void)
{
    // 开启 TIM5 和 GPIOA 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // GPIOA 引脚初始化
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 连接 PA0 到 TIM5 的通道 1
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5);

    // 定时器 5 初始化
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
    TIM_TimeBaseStructure.TIM_Prescaler = 7199;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

    // 输入捕获配置
    TIM_ICInitTypeDef TIM5_ICInitStructure;
    TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM5_ICInitStructure.TIM_ICFilter = 0x00;
    TIM_ICInit(TIM5, &TIM5_ICInitStructure);

    // 使能捕获和更新中断
    TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);

    // 设置中断分组
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能定时器
    TIM_Cmd(TIM5, ENABLE);

    while (1)
    {
        if (TIM5CH1_CAPTURE_STA & 0X80)
        {
            // 计算高电平脉宽
            uint32_t pulseWidth = (TIM5CH1_CAPTURE_STA & 0X3F) * 65536 + TIM5CH1_CAPTURE_VAL;
            // 打印结果
            printf("高电平脉宽:%d us\n", pulseWidth);
            // 清除捕获状态
            TIM5CH1_CAPTURE_STA = 0;
        }
    }
}

在上述程序中,首先初始化了定时器和 GPIO 引脚,配置了输入捕获模式和中断。在中断服务函数中,根据上升沿和下降沿的捕获情况,记录定时器的值并计算高电平脉宽。在主循环中,不断检查是否成功捕获到高电平脉宽,并打印结果。

六、总结

        STM32 的输入捕获功能是一个非常强大的工具,可以帮助我们准确地测量外部信号的参数。通过合理地配置定时器和相关寄存器,以及编写中断服务函数,我们可以轻松地实现输入捕获功能。在实际应用中,我们需要根据具体的需求选择合适的定时器和捕获通道,并注意处理定时器溢出等情况,以保证测量结果的准确性。希望本文对大家理解和使用 STM32 的输入捕获功能有所帮助。

 

 

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

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

相关文章

聚类及Python下实现 K-means 算法

聚类 聚类是无监督学习中的一种重要方法&#xff0c;旨在将数据集中相似的数据对象划分到同一个簇中&#xff0c;使得不同簇之间的数据对象差异尽可能大。在大数据环境下&#xff0c;聚类可以帮助挖掘数据中的隐藏结构和模式&#xff0c;应用场景十分广泛&#xff0c;比如在客…

开源分布式系统追踪-01-Zipkin-01-入门介绍

分布式跟踪系列 CAT cat monitor 分布式监控 CAT-是什么&#xff1f; cat monitor-02-分布式监控 CAT埋点 cat monitor-03-深度剖析开源分布式监控CAT cat monitor-04-cat 服务端部署实战 cat monitor-05-cat 客户端集成实战 cat monitor-06-cat 消息存储 skywalking …

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

【6】数据分析检测(DataFrame 1)

学习目标3 昨天&#xff0c;我们学习了Series。 而Pandas的另一种数据类型&#xff1a;DataFrame&#xff0c;在许多特性上和Series有相似之处。 今天&#xff0c;我们将学习DataFrame的相关知识&#xff1a; 1. DataFrame的概念 2. 构造一个DataFrame 3. DataFrame的常用…

LeetCode 热题 100_环形链表 II(26_142_中等_C++)(单链表;哈希表;快慢指针)

LeetCode 热题 100_环形链表 II&#xff08;26_142&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;代码实现&#xff08;思路一&#xff08;哈希表&#xff09;&#xff09;&#xff1a;代码实现&#xff08;思路二&#xff0…

如何通过看板进行跨境电商的圣诞商品数据分析与优化选品流程?

引言 随着圣诞季的临近&#xff0c;跨境电商迎来了重要的销售时机。选品工作对于跨境电商的成功至关重要&#xff0c;直接关系到销售业绩和利润。本文结合相关网页信息&#xff0c;深入探讨跨境电商在圣诞期间如何利用信息整合工具展开选品工作&#xff0c;并优化选品流程。同…

PHP开发设计模式:单例模式

PHP开发设计模式&#xff1a;单例模式 特点&#xff1a; 三私一公&#xff1a;私有的静态变量&#xff08;存放实例&#xff09;&#xff0c;私有的构造方法&#xff08;防止创建实例&#xff09;&#xff0c;私有的克隆方法 (防止克隆对象)&#xff0c;公有的静态方法&#…

使用HTML获取商品详情:技术实现与最佳实践

1. 引言 在电子商务领域&#xff0c;获取商品详情是提升用户体验和增强网站功能性的关键。本文将探讨如何使用HTML结合其他技术手段获取商品详情&#xff0c;并展示如何将这些信息有效地呈现给用户。 2. 理解商品详情页面的结构 在开始编码之前&#xff0c;我们需要了解商品…

MR30分布式IO在新能源领域加氢站的应用

导读 氢能被誉为21世纪最具发展潜力的清洁能源&#xff0c;氢能科技创新和产业发展持续得到各国青睐。氢能低碳环保&#xff0c;燃烧的产物只有水&#xff0c;是用能终端实现绿色低碳转型的重要载体。氢能产业链分别为上游制氢、中游储运以及下游用氢。上游制氢工艺目前大部分…

WEB安全基础知识

WAF全称为Web Application Firewall&#xff08;网页应用防火墙&#xff09;是一种专门设计用来保护web应用免受各种网络攻击的安全防护措施。它位于客户端与服务器之间&#xff0c;监控和过滤HTTP流量&#xff0c;从而拦截恶意请求、识别并防御常见的web攻击。 WAF的主要功能…

【数据结构】B树家族解析:B树、B+树与B*树的理论与B树插入实现(C++)

文章目录 一、常见的搜索结构二、B树2.1 B树概念2.2 开销 三、代码实现3.1 B树节点的设计3.2 B树设计3.3 插入操作实现1. 查找插入位置&#xff08;Find 函数&#xff09;2. 插入关键字到节点&#xff08;InsertKey 函数&#xff09;3. 处理节点分裂&#xff08;Insert 函数&am…

protobuf c++开发快速上手指南

1、环境准备 在c环境使用 protobuf&#xff0c;需要安装protobuf runtime以及protobuf的编译器&#xff1a;protoc&#xff0c;其作用如下表格&#xff1a; 需要安装的环境作用protoc将proto文件编译成c源码protobuf runtime编译c源码需要链接到protobuf库 注意&#xff1a;…

【实践·专业课】内存管理-存储管理-文件系统

1. 基于Linux的简单区块链实现 1.1. 环境准备 确保使用的 Linux 系统&#xff08;如 Ubuntu、CentOS 等&#xff09;已安装 Python 3。 在终端输入python3命令&#xff0c;若出现 Python 解释器的版本信息等提示&#xff0c;则表示已安装&#xff1b; 若提示未找到命令&…

科技潮头浪接天,一桥飞架两界连。EthernetIP转Profinet互译连

本案例介绍的是西门子1200PLC通过稳联技术PROFINET转EtherNetIP网关&#xff08;WL-ABC2006&#xff09;连接HCS-6100系统配置案例。 打开稳联技术Ethernetip转profient网关(WL-ABC2006)配置软件&#xff0c;因为网关作为EtherNetIP从站&#xff0c;所以选择PN2EIP。设置网关Pr…

【网络篇】TCP知识

TCP首部格式&#xff1f; 为什么需要 TCP 协议&#xff1f; TCP 工作在哪一层&#xff1f; IP 层是不可靠的&#xff0c;它不保证网络包的交付、不保证网络包的按序交付也不保证网络包中的数据的完整性。如果需要保障网络数据包的可靠性&#xff0c;那么就需要由上层&#xff0…

PDFMathTranslate,PDF多语言翻译,批量处理,学术论文,双语对照(WIN/MAC)

分享一个非常实用的PDF文档翻译项目——PDFMathTranslate。作为一个经常逛GitHub的开发者&#xff0c;我总喜欢翻看各种项目附带的论文&#xff0c;虽然大多时候是瞎研究&#xff0c;但却乐在其中。该项目能够完美保留公式、图表、目录和注释&#xff0c;对于需要阅读外文文献的…

Ape-DTS:开源 DTS 工具,助力自建 MySQL、PostgreSQL 迁移上云

Ape-DTS 是一款高效、轻量级且功能强大的开源工具&#xff0c;专注于解决数据迁移、同步、校验、订阅与加工的需求。无论是将自建的 MySQL/PostgreSQL 数据库迁移到云端&#xff0c;还是在不同数据库间进行数据迁移&#xff0c;Ape-DTS 都能为您提供便捷且可靠的解决方案。它特…

【经典论文阅读】Latent Diffusion Models(LDM)

Latent Diffusion Models High-Resolution Image Synthesis with Latent Diffusion Models 摘要 动机&#xff1a;在有限的计算资源下进行扩散模型训练&#xff0c;同时保持质量和灵活性 引入跨注意力层&#xff0c;以卷积方式实现对一般条件输入&#xff08;如文本或边界框…

使用torch模拟 BMM int8量化计算。

使用torch模型BMM int8计算。 模拟&#xff1a;BMM->softmax->BMM 计算流程 import torch import numpy as np torch.manual_seed(777) def int8_quantize_per_token(x: torch.Tensor, axis: int -1, attnsFalse):if x.dtype ! torch.float32:x x.type(torch.float32)…

Leetcode 每日一题 219.存在重复元素 II

目录 问题描述 输入输出格式 示例 算法分析 过题图片 代码实现 复杂度分析 题目链接 总结 问题描述 给定一个整数数组nums和一个整数k&#xff0c;我们需要判断数组中是否存在两个不同的索引i和j&#xff0c;使得nums[i] nums[j]且|i - j| < k。如果存在这样的i和…