使用定时器外设的输入捕捉功能及测量脉冲宽度

使用定时器外设的输入捕捉功能及测量脉冲宽度

文章目录

  • 使用定时器外设的输入捕捉功能及测量脉冲宽度
    • Introduction
    • 硬件定时器外设输入捕获功能的机制
    • 使用两个通道(引脚)的单边沿触发输入捕获
    • 使用单通道(引脚)的双边沿触发输入捕获
      • 利用通道的IO电平判定跳变沿方向
      • 动态按需切换捕获不同的边沿实现状态机
    • 使用硬件专门设计的测量脉宽功能
    • Conclusion

Introduction

在汽车电子系统中,经常需要通过编码器反馈机械结构的位置信息,微控制器芯片解析编码器的信号时,会使用到定时器的输入捕获功能测量编码器输出的脉冲宽度。绝大多数带有多通道输入输出的定时器,都设计了输入捕获功能。基本的硬件输入捕获功能只是对外部的触发事件(通道引脚上的上升沿、下降沿)进行响应,将定时器当前的计数值快照到通道的输入数据寄存器中,还需要配合少量软件和硬件中断服务进行计算,才能得到表示脉冲宽度的量化值。

本文以国产云途半导体的YTM32B1ME05微控制器为例,介绍使用硬件定时器eTMR外设的输入捕获功能,实现测量脉冲宽度的方法。特别地,eTMR外设在硬件上还设计了专门测量脉冲宽度的功能,以简化软件处理的过程。

硬件定时器外设输入捕获功能的机制

在《YTM32的增强型定时器eTMR外设模块详解》一文中曾介绍过,硬件定时器功能的核心,是一个在选定时钟源驱动下的计数器。其中,若配置某个定时器的通道为输入捕获模式,软件可预设检测通道引脚上的信号变化边沿触发事件(上升沿、下降沿),当定时器硬件捕获到对应的触发信号时,会自动将定时器计数器当前的计数值写入到该通道对应的输入捕获数据寄存器中,记录该值作为预设触发信号的时间戳。

YTM32B1ME05微控制器芯片中集成的eTMR模块,最多支持8个通道,并且每个通道可以配置成输入捕获模式(设置寄存器eTMR_CHn_CTRL[CHMODE]),并且可以检测通道引脚上的单独的上升沿、单独的下降沿或是任一边沿(设置寄存器eTMR_CHn_CTRL[CAPEDGE]),每个通道设计有专门的eTMR_CHn_CVAL寄存器,专用于存放最近一次捕获到的触发事件的时间戳。

图x中描述的信号时序,解释了eTMR通道的输入捕获模式的工作机制。其中:

  • clock是驱动计数器的时钟源信号,counter对每个时钟源的脉冲进行计数。
  • valid input是通道引脚上的电平信号。
  • positive edge flagnegative edge flag分别为eTMR检测到valid input信号上的上升沿和下降沿的事件标志。注意,这两个标志存在于芯片电路系统的内部,使用脉冲的方式传递信号。

在这里插入图片描述

图x 输入捕获的时序图
  • 若使用单独检测上升沿,产生positive edge flag信号时(上升沿),当前counter的值CNT0被载入到CHXCVAL寄存器中,保持,直到下一个上升沿到来。在下降沿时不做更新。
  • 若使用单独检测下降沿,产生negative edge flag信号时(下降沿),当前counter的值CNT1被载入到CHXCVAL寄存器中,保持,直到下一个下降沿到来。在上升沿时不做更新。
  • 若使用检测双边沿,产生positive edge flagnegative edge flag任一信号时,当前counter的值都会被载入到CHXCVAL寄存器中。

使用两个通道(引脚)的单边沿触发输入捕获

测量脉冲的宽度,具体就是分别捕获脉冲方波的上升沿和下降沿的时刻(若是测量负脉冲则先捕获下降沿再捕获上升沿),然后使用后一个时刻减去前一个时刻,即可得到脉冲的时间长度。这里面还有个情况需要考虑,输入捕获记录的一个周而复始的计数器,在未能限定输入脉冲宽度的最大范围的场景下,第二次捕获的时刻可能会出现在后续的计数“轮回”中,因此还需计入脉冲宽度中计数器绕圈的次数。

这里有计算公式如下:

脉冲宽度 = 计数器周期的时间长度 * 计数器周期的次数(从捕获第一边沿开始至捕获第二边沿结束中间)
        + 捕获第二边沿的时刻 - 捕获第一边沿的时刻

通常,定时器输入捕获通道都只设计了一个输入捕获数据寄存器,但软件可以配置在捕获上升沿或者下降沿的时刻。此时,若要测量脉冲宽度,可以在芯片外面(PCB板电路)将两个输入捕获的通道连在一起接入即将捕获的信号,然后分别配置两个输入捕获的通道事件,一个是上升沿,一个是下降沿。因为两个引脚的信号方向都是输入,不会相互影响。还要记得启用计数器溢出中断,并在中断程序中设计一个软件计数器,记录测量脉冲宽度中可能包含的溢出周期的个数pulse_width_period_count。若正脉冲到来:

  • 预先配置捕获上升沿信号的通道硬件将自动先记录第一个边沿的时刻,存入通道输入捕获数据寄存器eTMR_CH0_CVAL,同时触发本通道的中断,在服务程序中,将pulse_width_period_count计数器清零。
  • 如果脉冲宽度很长,计数器的溢出中断会持续到来,在对应的中断服务程序中,pulse_width_period_count计数器将被累加。这里还可以加入超时判断,即软件设计判定,若pulse_width_period_count计数器的值被递增至某个预设值时,即可为判定脉宽过长,然后向应用逻辑反馈。
  • 预先配置捕获下降沿信号的通道硬件再记录第二个边沿的时刻,存入通道输入捕获数据寄存器eTMR_CH1_CVAL,同时触发本通道的中断,在服务程序中,将使用上述计算公式计算测量的脉冲宽度,然后向应用逻辑反馈。

分析测量脉冲宽度的实现过程可知,程序运行过程对中断服务有比较多的依赖,测量一路脉冲宽度信号,需要配合三个中断服务程序。下文中可以看到,eTMR外设模块针对这种应用场景,专门设计了测量脉宽的功能,可以使用硬件自动记录有效的pulse_width_period_count计数器,并自行完成计算脉冲宽度的过程。

细心的读者可能会顾虑,若测量一路脉冲宽度时,使用了公共的定时器溢出中断的资源,是不是别的测量通路就不能它来参与额外的脉宽测量了呢?实际上,这里可以通过软件实现多路共用同一个时基,即为多个测量脉冲宽度的通道各自设计一个pulse_width_period_count计数器,在计数器溢出中断服务程序中将这些脉宽可能包含的溢出周期数都递增。

void eTMR0_IRQHandler(void)
{
    ...
    for (uint32_t i = 0u; i < PULSE_WIDTH_NUM; i++)
    {
        pulse_width_period_count[i]++;
        if (pulse_width_period_count > PULSE_WIDTH_TIMEOUT_PERIOD_COUNT)
        {
            pulse_width_period_timeout_flag = true; /* timeout event. */
        }
    }
}

void eTMR_CH0_IRQHandler(void)
{
    ...
    pulse_width_period_count[0] = 0u; /* clear the period counter. */
}

void eTMR_CH1_IRQHandler(void)
{
    /* calc the pulse width between the ch0 and ch1. */
    pulse_width[0] = eTMR0->MOD * pulse_width_period_count[0] + eTMR0->CH[1].CVAL - eTMR0->CH[0].VAL;
}

使用单通道(引脚)的双边沿触发输入捕获

定时器通道的输入捕获事件,可以是仅上升沿、仅下降沿,或者是上升沿或下降沿的任一事件。既然是捕获一对边沿事件,一些开发者就想把这个上升沿或下降沿的任一事件利用起来,这样还能减少在芯片外面将两个引脚连在一起的奇怪设计。。。中间的计算过程同上文相同,这里就不再赘述了。但要特别提示的是,如果使用这个二者均可的触发模式,就需要硬件额外提供判定当前捕获的边沿是上升沿还是下降沿的机制,几种可能的实现方式,这里做一些推演。

利用通道的IO电平判定跳变沿方向

当跳变沿到来(此时软件还不知道上升沿还是下降沿)时,在中断服务程序中,软件通过硬件提供的可用机制读输入通道的电平信号,若为高电平,则判定为上升沿,若为低电平,则判定为下降沿。例如,eTMR外设使用eTMR_STS寄存器中的对应字段记录跳变沿事件到来时,同时还会在eTMR_IOSTS寄存器中记录对应通道的电平状态,因此可用来判定边沿的方向。

void eTMR_CH0_IRQHandler(void)
{
    ...
    if (eTMR0->STS & eTMR_STS_CH0F_MASK)
    {
        if (0u == (eTMR0->IOSTS | eTMR_IOSTS_CH0IO_MASK) )
        {
            /* falling edge. */
        }
        else
        {
            /* rising edge. */
        }
    }
    ...
}

如果定时器外设模块没有这种硬件机制,就得靠软件临时切换引脚的复用功能成GPIO的输入功能,利用GPIO外设模块读电平。记得读完电平后,还得将引脚的复用功能切换回定时器功能,否则就抓不到下个跳变沿了。

如果担心中间软件执行指令比较慢,那就外接一个专门的引脚配置成GPIO输入功能,不用动态切换引脚复用功能,专门用于测量脉冲信号的瞬时电平。但这就又变成两个引脚的方案的,只是不要求另一个引脚具有输入捕获的功能,可以使用宝贵的带输入捕获功能的引脚测量更多路脉冲信号。

动态按需切换捕获不同的边沿实现状态机

如果定时器硬件能接受运行时改工作模式(重新写入寄存器),也可以有针对性地在特定时间段捕获特定边沿,相当于基于软件实现了一个检测信号模式的状态机,那么这个状态机中的各个状态将由软件接管,不再依赖于硬件已有的实现。例如,若要测量正脉冲,则先配置捕获通道的事件为仅上升沿,当上升沿信号到来之时,软件在通道的中断服务中,使用软件变量暂存当前捕获时刻的计数值后,再重新配置本通道捕获的通道事件为仅下降沿。之后,下降沿到来时,就可以使用之前缓存的前一个捕获的计数值配合当前的捕获值计算脉宽。

eTMR外设为计数器数据相关的寄存器设计了“影子寄存器”,需要特定的同步机制才能更改,但通道的配置寄存器eTMR_CHn_CTRL不在其中,可以支持这种用法。

etmr_ch_input_edge_dir_t etmr_ch0_dir = eTRM_CH_INPUT_EDGE_FALLING_EDGE;
void eTMR0_CH0_IRQHandler(void)
{
    ...
    eTMR0->CH[0].CTRL &= ~eTMR_CH_CTRL_CAPEDGE_MASK;
    switch (etmr_ch0_dir)
    {
        case eTRM_CH_INPUT_EDGE_FALLING_EDGE:
            /* falling edge event. */
            eTMR0->CH[0].CTRL |= eTMR_CH_CTRL_CAPEDGE(1); /* next is rising edge. */
            break;
        case eTRM_CH_INPUT_EDGE_RISING_EDGE:
            /* rising edge event. */
            eTMR0->CH[0].CTRL |= eTMR_CH_CTRL_CAPEDGE(2); /* next is falling edge. */
            break;
        default:
            break;
    }
}

使用硬件专门设计的测量脉宽功能

针对汽车电子系统中,MCU在一些关键阶段对计算实时性要求比较高,多个中断的协同配合对CPU的相应时序要求比较高。为了降低多线程相互配合完成计算的风险,YTM32集成在车规MCU的eTMR定时器模块,专门在芯片硬件上完全实现了测量脉冲的全部操作过程,不全程不需要软件介入,只需要在对应的通道中断服务程序中从硬件寄存器中读取自动计算的结果即可。

RM手册中提供给开发者的说明并不多,只是简单介绍了寄存器接口。本节可以作为手册的补充,扩展说明芯片内部的工作过程,便于读者理解芯片手册,使用合适的方式集成到自己的软件中。

RM手册中的eTMR外设寄存器清单中,列出了每个通道为测量脉冲宽度设计的4个寄存器,CH_PPCNTNCH_PPCNTVCH_NPCNTNCH_NPCNTV,如图x所示。

在这里插入图片描述

图x eTMR硬件测量脉宽的寄存器

这里先声明,所谓的正脉冲(Positive Pulse),是指由上升沿开始、下降沿结束形成的方波信号,对应地,负脉冲(Negative Pulse),是指由下降沿开始、上升沿结束形成的方波信号。如图x所示。

在这里插入图片描述

图x 正脉冲和负脉冲

eTMR硬件为每个通道可能出现的正脉冲和负脉冲都各自配备了一组内部的寄存器。以测量正脉冲为例,在上升沿捕获到的数值记录在专属的buf0寄存器中,下降沿捕获到的数值记录在buf1寄存器中,用eTMR_CH_PPCNTN寄存器对脉宽内部可能包含的定时器溢出周期进行计数。当下降沿(结束边沿)到来之时,硬件自动将buf1减去buf0的值,存入eTMR_CH_PPCNTV寄存器中。如果最初的结果是负数,则硬件也会自动从eTMR_CH_PPCNTN寄存器中借1位(数值也减1回存),确保存入eTMR_CH_PPCNTV寄存器中的有效值是正数。类似地,eTMR_CH_NPCNTNeTMR_CH_NPCNTV对应的是负脉冲测量数值。

eTMR_STS寄存器中,也专门为有效的脉冲捕获事件设计的标志位。如图x所示。

在这里插入图片描述

图x eTMR_STS寄存器中设计的脉冲事件标志位

当前版本的eTMR并没有对应地专门为脉宽检测设计专门的中断事件,但可以借用边沿事件的中断,例如,使用输入捕获下降沿的中断服务程序读eTMR_CH_PPCNTNeTMR_CH_PPCNTV寄存器并完成计算。

RM手册中提供了第一张关于输入捕获脉冲的时序图,如图x所示。这里也作一个补充说明,详细解释其中时序的含义。

在这里插入图片描述

图x eTMR的脉宽调试功能
  • clock是计数器计数的时基。
  • valid data是引脚上实际的电平信号。
  • counter是计数器当前的计数值。
  • CNT0时,valid data信号线上产生上升沿,对应positive edge flag产生一个触发信号。
  • CNT1时,valid data信号线上产生下降沿,对应nagative edge flag产生一个触发信号。同时,之前在CNT0产生的上升沿和当前产生的下降沿组合成一个正脉冲,对应positive pulse flag信号线上产生一个触发信号,PPCNTVPPCVTN寄存器也被硬件写入了经过基本处理的数值,可用于计算正脉冲的宽度。
  • CNT2时,valid data信号线上产生上升沿,对应positive edge flag产生一个触发信号。同时,之前在CNT1产生的下降沿和当前产生的上升沿组合成一个负脉冲,对应negative pulse flag信号线上产生一个触发信号,NPCNTVNPCNTN寄存器也被硬件写入了经过基本处理的数值,可用于计算负脉冲的宽度。

Conclusion

一些微控制器的多通道带有IO引脚的定时器具有输入捕获功能,可以通过记录通道引脚出现跳变沿的时刻,用以计算两个相反边沿组成的脉冲的宽度。除了需要配合定时器溢出中断对溢出周期计数之外,本文梳理了常用的实现测量包含两个边沿的脉冲的方法:

  • 使用两个输入捕获通道分别捕获两个边沿
  • 使用一个输入捕获通道配合一个IO信号/引脚
  • 使用一个输入捕获通道,配合软件控制电路实现的状态机

还特别介绍了YTM32的eTMR定时器中基于硬件实现的脉宽测量方法,实际上是将典型测量方法由硬件逻辑自动实现,开发者在使用这个功能时,需要了解其中的工作机制,以便于以合适的方式整合到具体的应用逻辑中。

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

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

相关文章

16.5 参考文献——深度学习定位

16.5 一种高效鲁棒的多楼层室内环境指纹定位方法 同济大学 Zhao Y, Gong W, Li L, et al. An Efficient and Robust Fingerprint Based Localization Method for Multi Floor Indoor Environment[J]. IEEEa Internet of Things Journal, 2023. 2.相关工作 B.基于深度学习的…

SAI实例研究

实例1 creature.id 15937&#xff08;smart_script.entryorguid&#xff09;的SAI设置&#xff1a; 第1条(id 0&#xff09; 当 creature 进入战斗后&#xff08;event_type 0&#xff09;&#xff0c;creature 对当前目标&#xff08;target_type 2&#xff09;周期性施…

VS里那些实用的调试(debug)技巧

前言——————希望现在在努力的各位都能感动以后享受成功的自己&#xff01; 首先我们要来了解什么是bug——————bug本意是“昆虫”或“虫子”&#xff0c;现在⼀般是指在电脑系统或程序中&#xff0c;隐藏着的⼀些未被发现的缺陷或 问题&#xff0c;简称程序漏洞。 “…

【Flink-1.17-教程】-【四】(1)Flink DataStream API - 源算子(Source)

【Flink-1.17-教程】-【四】&#xff08;1&#xff09;Flink DataStream API - 源算子&#xff08;Source&#xff09; 1&#xff09;执行环境&#xff08;Execution Environment&#xff09;1.1.创建执行环境1.2.执行模式&#xff08;Execution Mode&#xff09;1.3.触发程序执…

PostgreSQL的date_part()函数

date_part() 函数从指定的时间戳或者时间间隔中抽取指定的部分并返回。 date_part(field TEXT, source TIMESTAMP) -> DOUBLE PRECISION date_part(field TEXT, source DATE) -> DOUBLE PRECISION date_part(field TEXT, source TIME) -> DOUBLE PRECISION date_part…

qemu使用

百度qemu bios 问题 坑爹的玩意&#xff0c;编译qemu 还需要python3.5以上 解决方法&#xff1a; CentOS7安装Python3.8-CSDN博客 https://www.cnblogs.com/Oliver.net/p/7211967.html 编译python3.8还由于openssl过低 参考 QEMU启动x86-Linux内核_qemu-system-x86-…

进程间协同:从进程启动、同步与互斥到进程间通信

进程间协同的目的 在操作系统中&#xff0c;进程是计算机进行任务分配和调度的基本单位。在计算机系统中&#xff0c;有很多任务是无法由单个进程独立完成的&#xff0c;需要多个进程共同参与并协作完成。这就像在现实生活中&#xff0c;有些工作需要一个团队来完成&#xff0…

Vue 组件通信方式

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

三、MySQL库表操作

3.1 SQL语句基础&#xff08;SQL命令&#xff09; 3.1.1 SQL简介 SQL&#xff1a;结构化查询语言(Structured Query Language)&#xff0c;在关系型数据库上执行数据操作&#xff0c;数据检索以及数据维护的标准化语言。使用SQL语句&#xff0c;程序员和数据库管理员可以完成…

关于C语言整型提升的讲解

目录 1.什么是整型提升 2.整型提升的意义 3.整型提升是怎么提升的 4.整型提升的实例 1.什么是整型提升 C语言中的整型算术运算总是以缺省&#xff08;默认&#xff09;整型类型的精度来进行的。为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前会被转换…

Android学习之路(22) 从模块化到组件化

从模块化到组件化 一、从模块化到组件化 Android 应用项目 , 都存在一个应用模块 ( Application Module ) , 在 build.gradle 构建脚本中 , 第一个插件配置 com.android.application , 表明 该 Module 编译打包后的输出是 APK 安装包 ; 该项目可以直接运行 ; plugins {id co…

回溯法:澳大利亚地图染色问题及伪代码(模版)

问题背景 澳大利亚地图染色问题&#xff1a; 用红绿蓝3色标出各省&#xff0c; 相邻者颜色不同。 对应于澳大利亚地图的约束图&#xff0c; 相互关联的节点用边连接。 − 西澳大利亚 – WA − 北领地 – NT − 南澳大利亚 – SA − 昆士兰 – Q − 新南威尔士 – NSW − …

79、avx2 向量指令集优化卷积运算

上一节 介绍了 avx2 向量指令集中的 load/store 操作,本节介绍如何使用 avx2 的向量指令集来实现乘累加运算。 因为我们实战中用到的 resnet50 神经网络中,卷积运算在整个模型中的比例占据是相当高,而卷积运算的核心计算就是乘累加计算。因此,只要将最核心的乘累加计算效率…

Shiro框架:Shiro用户访问控制鉴权流程-Aop注解方式源码解析

目录 1.Spring Aop嵌入点解析 2.Shiro框架Aop切面逻辑解析 2.1 通过注解实现切点 2.2 通过增强逻辑执行校验过程 2.2.1 增强实现类AopAllianceAnnotationsAuthorizingMethodInterceptor 2.2.1.1 类图解析 2.2.1.2 实现增强方法 2.2.1.3 Shiro校验逻辑实现 2.2.1.3.1 …

JVM篇--垃圾回收器高频面试题

1 你知道哪几种垃圾收集器&#xff0c;各自的优缺点是啥&#xff0c;重点讲下cms和G1&#xff0c;包括原理&#xff0c;流程&#xff0c;优缺点&#xff1f; 1&#xff09;首先简单介绍下 有以下这些垃圾回收器 Serial收集器&#xff1a; 单线程的收集器&#xff0c;收集垃圾时…

Flink(十四)【Flink SQL(中)查询】

前言 接着上次写剩下的查询继续学习。 Flink SQL 查询 环境准备&#xff1a; # 1. 先启动 hadoop myhadoop start # 2. 不需要启动 flink 只启动yarn-session即可 /opt/module/flink-1.17.0/bin/yarn-session.sh -d # 3. 启动 flink sql 的环境 sql-client ./sql-client.sh …

Tomcat Notes: Web Security

This is a personal study notes of Apache Tomcat. Below are main reference material. - YouTube Apache Tomcat Full Tutorial&#xff0c;owed by Alpha Brains Courses. https://www.youtube.com/watch?vrElJIPRw5iM&t801s 1、Overview2、Two Levels Of Web Securi…

深入Matplotlib:画布分区与高级图形展示【第33篇—python:Matplotlib】

文章目录 Matplotlib画布分区技术详解引言方法一&#xff1a;plt.subplot()方法二&#xff1a;简略写法方法三&#xff1a;plt.subplots()实例展示添加更多元素 进一步探索Matplotlib画布分区自定义子图布局3D子图结语 Matplotlib画布分区技术详解 引言 Matplotlib是一个强大…

1.6万字全面掌握 BERT:自然语言处理(NLP)从初学到高级的全面指南

BERT&#xff08;双向编码器表示来自Transformer的模型&#xff09;是由Google开发的一种革命性的自然语言处理&#xff08;NLP&#xff09;模型。它改变了语言理解任务的格局&#xff0c;使机器能够理解语言中的上下文和细微差异。 在本博客中&#xff0c;我们将带您从 BERT …

动态路由协议 - OSPF 基本配置 详解 (反掩码,宣告,三张表,Cost默认值修改 )

目录 预备工作 &#xff1a; 基础配置 &#xff1a; 先启动 OSPF 的进程 &#xff1a; 创建区域 &#xff1a; 宣告 &#xff1a; 查看三张表 邻居表 &#xff1a; 数据库表 &#xff1a; 路由表 &#xff1a; 以下示拓扑为 OSPF 示范 &#xff1a; 第一步…