STM32

发布于:2025-07-24 ⋅ 阅读:(16) ⋅ 点赞:(0)

目录

#TIM输入捕获#

输入捕获简介

工作流程:

 频率测量 

用STM实现俩种测频率方法:

输入捕获通道

更详细的电路流程图:

1.输入信号源选择 (TI1, TI2):

2.边沿极性选择与检测器:

3.输入滤波器 (Input Filter):

4.预分频器 (Prescaler) / 捕获分频器:

5.最终捕获路径与寄存器:

6.其他重要连接:

主从触发模式

1.主模式选择:

2.从模式触发源可选择信号

3.触发从模式后执行的操作

4.补充外部时钟模式知识点:

一、 外部时钟模式1 (External Clock Mode 1)

二、 外部时钟模式2 (External Clock Mode 2)

三、 核心区别总结

输入捕获基本结构

输入捕获过程:

注意:

PWMI基本结构

输入捕获模式测频率

1.输入捕获初始化

2.初始化输入捕获单元

1.IC.c

2.IC.h

3.pwm.c(修改)

4.main.c

PWMI测量频率和占空比

1.IC.c代码改编

2.main.c

测评率的性能:

误差分析:

输入捕获预输出比较区别

简单类比:


#TIM输入捕获#

输入捕获简介

  • ICInput Capture)输入捕获
  • 输入捕获模式下,当通道输入引脚出现指定电平跳变(上升沿/下降沿)时,当前CNT的值将被锁存到CCR中(将当前CNT的值读出来写道CCR中),可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
  • 每个高级定时器和通用定时器都拥有4个输入捕获通道
  • 可配置为PWMI模式(PWM输入模式,专门测量PWM频率和占空比),同时测量频率和占空比
  • 可配合主从触发模式,实现硬件全自动测量
  • 结合PWMI模式和主从触发模式,测量频率占空比就是硬件全自动执行,需要测量时,直接读取CCR寄存器即可
  • 由于输入捕获的CH1~CH4四个通道引脚和CCR寄存器与输出比较通道共用,同一个定时器只能使用其中一个

输入捕获IC电路(四个通道)原理图中的位置👇

工作流程:

四个通道引脚(CH1~CH4三输入异或门(执行逻辑是当三个输入引脚的任何一个有电平翻转时,输出引脚就产生一次电平翻转,输入接在输入引脚123端口→数据选择器(往①走TIx为三个引脚异或值,往②走TIx为各个引脚的值)→输入滤波器(俩套)(对信号进行滤波,避免一些高频毛刺信号误触发)和边沿检测器(与外部中断一样,选择高/低电平触发,出现指定电平,边沿检测电路就会触发后续电路执行工作)(①一个滤波和极性选择得到TIxFP1-TIx Filter Polarity 1输入给通道1(IC1)的后续电路②另一个滤波和极性选择得到TIxFP2-Tix Filter Polarity 2输入给通道2(IC2)的后续电路)(TRC引脚也可作为捕获部分的输入,来源于外部时钟1)→(俩个通道的信号可以交叉-CH1引脚输入给通道2(IC2),CH2引脚输入给通道1(IC1(目的:①灵活切换后续捕获电路的输入②一个引脚的输入同时映射到俩个捕获单元)TI1FP1上升沿触发,用来捕获周期;TI1FP1下降沿触发,用来捕获占空比,俩个通道同时对一个引脚进行捕获,就可以同时测量占空比和周期——PWMI模式预分频器(对前面信号进行分频,触发捕获电路进行工作)→捕获/比较寄存器(来一个触发信号,CNT值向CCR转运一次,同时发生一个捕获事件,并在状态寄存器ICxPS置标志位和产生中断,如果需要在捕获的瞬间处理一些事情的话,就可以开启这个捕获中断。)

 频率测量 

图上是只有高低电平的数字信号,STM32只能测高电平3.3v,低电平0v的数字信号的频

若需要测量一个正弦波,加一个信号预处理电路(eg.运放搭一个比较器),将正弦波转换为数字信号,再输入给STM32;若测量信号的电压非常高,考虑用隔离放大器、电压互感器等元件,隔离高电压和低压端,保证电路安全

  • 测频法(高频信号):在闸门时间T内,对上升沿计次,得到N(越大误差越小),则频率


测量这一块信号的频率,就可以制定一个闸门时间T,通常设置为一秒。

在一秒时间内对信号上升沿计次,从零开始计,每来一个上升沿计次加一,每来一个上升沿,其实就是来了一个周期的信号。所以在一秒时间内来了多少个周期,它的频率就是多少Hz,这符合频率的基本定义。频率的定义就是一秒内出现了多少个重复的周期。频率就是多少Hz

测量结果更新慢,结果是一段时间的平均值,值比较平滑,会出现正负1误差(一个T内,测量的N不完整)

  • 测周法(低频信号):两个上升沿内,以标准频率fc计次,得到N ,则频率

测量时间的方法,实际上也是定时器计次,我们使用一个已知的标准频率fc的计次时钟来驱动计数器,从一个上升沿开始,从零开始一直计到下一个上升沿停止,计一个数的时间是1/fc,计N个数时间就是N/fcN/fc就是周期,频率就是再取个倒数就得到了公式fx等于fc除以N

测量结果更新快,只测量一个周期,就能出结果,但结果值会受噪声影响,波动比较大,会出现正负1误差(fc计次记到一半停止)

  • 中界频率(判断高低电频信号):测频法与测周法误差相等的频率点(N相同时误差相同,N越大,正负1误差越小)

当待测信号频率小于中界频率时,测周法误差更小,选用测周法更合适。

当待测信号频率大于中界频率时,测频法误差更小,选用测频法更合适。

用STM实现俩种测频率方法:

①测频法:对射式红外传感器计次(每来一个上升沿计次+1)+定时器外部时钟(定一个1s的定时中断,在中断里,每隔1s取一下计次值,同时清0计次,为下一次做准备)=计数器读取的计次值为频率

②测周法:配置上升沿触发捕获,每来一个上升沿,CNT转运到CCR一次,由于CNT计数器由内部标准时钟驱动,即CNT的数值可以用来记录俩个上升沿之间的时间间隔(周期),取倒数为频率

(上升沿用于触发输入捕获,CNT用于计数计时,每来一个上升沿取下CNT的值自动存在CCR里,CCR捕获到的值就是计数值N。CNT的驱动时钟就是fc,fc/N就得到了待测信号的频率)

(每次捕获之后,CNT清零,下一次上升沿触发就是俩个上升沿之间的时间间隔;再一次捕获将CNT清零的步骤——主从触发模式自动完成)

测频法:定时器中断,并记录捕获次数;

测周法:捕获中断,并记录定时器次数。

输入捕获通道

TIMx_CCMR1中CC1E位:输入/捕获1输出使能 (Capture/Compare 1 output enable)

CC1通道配置为输出:

0: 关闭- OC1禁止输出。

1: 开启- OC1信号输出到对应的输出引脚。

 CC1通道配置为输入:

该位决定了计数器的值是否能捕获入TIMx_CCR1寄存器。

0:捕获禁止;

1:捕获使能。

更详细的电路流程图:

1.输入信号源选择 (TI1, TI2):

TI1F (Filtered Timer Input 1): 这是通道1的主输入信号,通常直接连接到芯片的某个GPIO引脚(例如PA0对应TIM2_CH1, TIM5_CH1等)。这个信号直接来自外部世界(如PWM信号、编码器信号)。

TI2F (Filtered Timer Input 2): 这是通道2的主输入信号。它也能被路由到通道1的捕获路径上。

通过配置寄存器TIMx_CCMR1捕获模式寄存器1的位CC1S[1:0](Capture/Compare 1 Selection),可以选择通道1的捕获信号源(TI1或者TI2):

  • 00: 禁止捕获(通道配置为输出)
  • 01: 映射到TI1 (即TI1FP1或TI1FP2路径)
  • 10: 映射到TI2 (即TI2FP1或TI2FP2路径)
  • 11: 保留

2.边沿极性选择与检测器:

CC1P, CC1NP (Capture/Compare 1 Output Polarity, 输入捕获模式下实际控制输入极性): 这两个位位于控制寄存TIMx_CCER捕获使能寄存器 (Capture/Compare Enable Register) 中。在输入捕获模式下:

CC1P: 控制TI1FP1和TI2FP1的有效边沿极性。(CC1通道配置输入)

  1. 0: 不反相,上升沿有效。
  2. 1: 反相,下降沿有效。

CC1NP: 控制TI1FP2和TI2FP2的有效边沿极性(主要用于PWM输入模式或双边沿捕获的特殊配置)。

  • 通俗讲: 这个选择器决定“通道1的耳朵”是听自己专用的引脚(TI1),还是去听隔壁通道2的引脚(TI2)。

边沿检测器 (Edge Detector): 这个硬件模块根据CC1P和CC1NP的设置,检测输入信号上发生的有效边沿。

当检测到TI1FP1上的有效边沿(由CC1P决定是上升沿还是下降沿)时,它会输出一个内部捕获触发信号 (TRC - Trigger for Capture)。

图中标注了TI1FP1_Rising和TI1FP1_Falling,表示检测器能识别这两种边沿,但哪个有效由CC1P控制。

  • 作用: 告诉系统“什么类型的信号跳变才算数”。你想在信号变高时捕获?还是变低时捕获?还是两者都要(双边沿)?就是这里配置。
  • 通俗讲: CC1P/CC1NP是“开关”,决定检测器是响应“上台阶”(上升沿)还是“下台阶”(下降沿)。检测器就是“眼睛”,盯着信号看有没有发生指定的跳变。

3.输入滤波器 (Input Filter)

        IC1F[3:0]输入捕获1滤波器  (Input Capture 1 Filter): 这些位位于配置寄存器TIMx_CCMR1中。它控制滤波器的采样频率和次数。

滤波器 (Filter) / 向下计数器 (Down Counter): 这是一个数字滤波器,用于消除信号上的噪声(毛刺)。在实际应用中,如果波形噪声大,参数设置大一些,可以过滤噪声。

它的工作方式:

  1. 系统时钟(f_CK_INT)经过一个预分频器(图中未明确标出,通常由TIMx_CR1的CKD[1:0]控制)得到采样时钟f_DTS
  2. 滤波器配置N个采样点(N由IC1F[3:0]的值决定,可以是1, 2, 4, 8...)。
  3. 当输入信号发生变化时,滤波器会用f_DTS频率连续采样N次。
  4. 只有连续N次采样到的电平都一致,滤波器才认为这是一个有效的电平变化,并输出这个新的稳定电平给后面的边沿检测器。否则,输出保持原电平不变。
  • 作用: 抗抖动! 比如按钮按下时会产生多次快速跳变的毛刺信号,滤波器能确保只有稳定、持续一段时间的电平变化才被认为是真正的边沿事件,避免误触发捕获。
  • 通俗讲: 滤波器就像一个“防抖小卫士”。信号跳一下它不立刻相信,要连续看好几眼(N次),确认信号真的稳定在新状态了,才报告给后面的“眼睛”(边沿检测器)。

4.预分频器 (Prescaler) / 捕获分频器:

IC1PSC[1:0] (Input Capture 1 Prescaler): 这些位位于配置寄存器TIMx_CCMR1中。

分频器 (Divider): 这个硬件模块位于边沿检测器之后、捕获动作之前。它对有效的捕获触发信号(TRC) 进行分频。可配置的分频比:

  • 00: 不分频。每个有效边沿都触发捕获。
  • 01: 2分频。每2个有效边沿触发一次捕获。
  • 10: 4分频。每4个有效边沿触发一次捕获。
  • 11: 8分频。每8个有效边沿触发一次捕获。
  • 作用: 降低捕获事件的频率。当你只关心信号的周期(需要连续2个上升沿)或者频率很高导致CPU处理不过来中断时,这个分频器非常有用。例如,配置为2分频(01)时,第一个上升沿到来它忽略,第二个上升沿到来它才真正发出捕获命令,这样捕获到的时间差就是信号的一个完整周期。
  • 通俗讲: 这个分频器是“事件选择器”。它可以让捕获通道“偷点懒”,比如设定“每隔两次有效跳变我才记录一次时间”。

5.最终捕获路径与寄存器:

IC1 (Input Capture 1 to Register): 这是经过滤波器、边沿检测器、预分频器处理后的最终捕获信号。当这个信号有效(一个被允许的、有效的边沿事件)时,就会触发核心的捕获动作。

捕获动作: 在IC1信号有效的瞬间,硬件会自动将当前定时器计数器TIMx_CNT的值复制(锁存) 到捕获/比较寄存器TIMx_CCR1中。这个动作是硬件完成的,速度极快,保证了时间的精确性。

TIMx_CCR1 (Capture/Compare Register 1): 这就是存放捕获结果的“宝箱”!捕获发生后,你需要读取这个寄存器来获取事件发生时的精确时间点(TIMx_CNT的值)。

6.其他重要连接:

  • TRC (Trigger for Capture): 如前所述,这是边沿检测器输出的内部触发信号。它不仅通向通道1的预分频器,还会被送到从模式控制器 (Slave Mode Controller)。
  • 从模式控制器 (Slave Mode Controller): 这个强大的模块可以接收各种触发源(包括TRC),并根据配置控制定时器的工作模式(如复位计数器、启动/停止计数器、启动注入通道转换等)。例如,在PWM输入模式下,就利用TRC(来自第一个通道的边沿)复位计数器,然后捕获第二个通道的边沿来测量周期和占空比。
  • TI1F_ED (TI1 Filtered Edge Detection): 这是TI1F信号经过滤波器后,直接进行双边沿检测的输出。它不受CC1P/CC1NP控制,只要TI1F上发生任何有效的边沿(上升或下降),它都会输出一个脉冲。这个信号主要用作从模式控制器的触发源(TRGI),尤其是在需要双边沿触发的应用(如某些编码器模式)中。

每捕获一次CNT的值,都要把CNT清零一下,以便于下一次的捕获。在这里硬件电路就可以在捕获之后自动完成CNT的清零工作。

自动清零CNT方式:

TI1FP1信号和TI1的边沿信号TI1F_ED都可以通向从模式控制器。

比如TI1FP1信号的上升沿触发捕获,同时TI1FP1还可以触发从模式。这个从模式里面就有电路,可以自动完成CNT的清零。

主从触发模式

主从触发模式就是主模式,从模式和触发源选择这三个功能的简称。

主模式:将定时器内部的信号映射到TRGO引脚,触发别的外设

从模式:接收其他外设或者自身外设的一些信号,控制自身定时器的运行(被别的信号控制)

触发源选择:选择从模式的触发信号源(可认为从模式的一部分),选择指定的一个信号,得到TRGI,去触发从模式。

若想完成TI1FP1信号自动触发CNT清零,触发源选择就可以选中TI1FP1,从模式执行操作Reset。

1.主模式选择:

若想完成定时器的级联,可选择定时器主模式,输出更新信号到TRGO,另一个定时器选择上一个定时器触发从模式,从模式选择执行外部时钟模式1的操作,可实现定时器级联。

主模式还可以选择复位、使能、比较脉冲和四个OCREF信号作为TRGO的输出。

2.从模式触发源可选择信号

3.触发从模式后执行的操作

4.补充外部时钟模式知识点:

一、 外部时钟模式1 (External Clock Mode 1)
  1. 原理:

    • 模式1主要利用定时器的输入捕获通道1 (TI1) 或 输入捕获通道2 (TI2) 来获取外部时钟信号。

    • 外部信号连接到配置为输入的 TIMx_CH1 或 TIMx_CH2 引脚。

    • 信号首先经过输入滤波器边沿检测器

    • 然后,信号被送到一个触发控制器(Trigger Controller)

    • 触发控制器的输出 (TRGI) 被用作从模式控制器 (Slave Mode Controller) 的触发输入。

    • 在模式1中,从模式控制器被配置为 “外部时钟模式1” (External Clock Mode 1)

    • 最终,这个处理后的信号就成为了定时器计数器 (CNT) 的时钟源 (CK_CNT)。计数器会在选定边沿(上升沿、下降沿或双边沿)到来时递增或递减。

  2. 信号路径:

    外部信号 -> TIMx_CH1/TIMx_CH2 引脚 -> 输入滤波器 -> 边沿检测器 -> 触发控制器 (TRGI) -> 从模式控制器 (配置为 ECE=1, SMS=111) -> CK_PSC -> CK_CNT (计数器时钟)
  3. 特征:

    • 信号源: 只能来自 TIMx_CH1 或 TIMx_CH2 引脚。

    • 边沿选择: 可以配置为上升沿、下降沿或双边沿计数。这通过捕获/比较模式寄存器 TIMx_CCMR1 中对应通道的 CCxS (选择输入源) 和 ICxP/ICxNP (选择极性) 位,以及从模式控制寄存器 TIMx_SMCR 中的 ETF (滤波器) 和 ETP (极性) 位间接影响。

    • 滤波: 可以配置输入滤波器 (TIMx_CCMR1 中的 ICxF 位) 来消除信号抖动。

    • 分频: 外部时钟信号在进入计数器之前,仍然会经过定时器的预分频器 (PSC)。预分频器设置 (TIMx_PSC) 决定了多少个外部时钟边沿才使计数器增加1。

    • 应用: 非常适合用于频率测量、脉冲计数等场景,因为它直接利用捕获通道,便于后续的捕获功能配合使用。

二、 外部时钟模式2 (External Clock Mode 2)
  1. 原理:

    • 模式2使用一个专门的输入引脚:外部触发输入 (ETR)

    • 外部信号连接到 TIMx_ETR 引脚。

    • 信号首先经过一个可配置的外部触发极性控制器 (ETP) 和 外部触发预分频器 (ETPS) 以及 外部触发滤波器 (ETF)

    • 经过这些处理后的信号 (ETRP) 直接作为定时器计数器 (CNT) 的时钟源 (CK_CNT)。它不经过从模式控制器

    • 同时,模式2需要使能外部时钟模式2功能。这通过设置 TIMx_SMCR 寄存器中的 ECE (External Clock Enable) 位为 1 来实现。

  2. 信号路径:

    外部信号 -> TIMx_ETR 引脚 -> 极性控制器 (ETP) -> 预分频器 (ETPS) -> 滤波器 (ETF) -> ETRP -> CK_PSC -> CK_CNT (计数器时钟)
    ↑
    (需要 TIMx_SMCR.ECE = 1)
  3. 特征:

    • 专用引脚: 必须使用 TIMx_ETR 引脚。每个定时器通常只有一个ETR引脚。

    • 独立路径: 时钟信号处理路径独立于输入捕获通道和从模式控制器。

    • 内置预分频器: 模式2有一个专属于ETR信号的预分频器 (ETPS[1:0] in TIMx_SMCR),可以在信号进入定时器核心之前进行分频 (1, 2, 4, 8 分频)。然后信号还会经过主预分频器 (PSC)。

    • 极性控制: 可以直接反转输入信号的极性 (ETP bit in TIMx_SMCR)。

    • 滤波: 有专用的滤波器 (ETF[3:0] in TIMx_SMCR)。

    • 简单直接: 配置相对模式1更简单直接,因为它不涉及触发输入的选择和从模式控制器的复杂配置(除了使能ECE位)。

    • 应用: 非常适合需要独立、专用外部时钟输入的场景,特别是当信号频率较高或需要ETR引脚独有的预分频/滤波时。也常用于精确的外部时钟同步

三、 核心区别总结
特性 外部时钟模式 1 外部时钟模式 2
信号源引脚 TIMx_CH1 或 TIMx_CH2 专用 TIMx_ETR
配置核心 通过从模式控制器 (Slave Mode Controller),选择 SMS=111 (外部时钟模式1) 和触发源 TS=TI1FP1/TI2FP2 独立路径,只需启用外部时钟模式2 (ECE=1) 并配置ETR参数
信号路径 经过输入通道滤波器/边沿 -> 触发控制器 -> 从模式控制器 -> CK_CNT 经过ETR极性/预分频/滤波 -> 直接 -> CK_CNT
专用预分频 。信号仅受主预分频器 (PSC) 影响。 。ETR有自己独立的预分频器 (ETPS: 1,2,4,8分频) 之后再经过主PSC。
极性控制 主要通过捕获通道配置 (ICxP/ICxNP) 和从模式触发极性 (TriggerPolarity) 有直接的ETR极性控制位 (ETP)
滤波 使用对应输入捕获通道的滤波器 (ICxF) 使用ETR专用滤波器 (ETF)
是否依赖捕获通道 ,必须配置对应的TI1/TI2通道输入 ,完全独立于输入捕获通道
配置复杂度 相对复杂,需要配置捕获通道(可选但推荐)和从模式控制器 相对简单直接,主要配置ETR参数和使能ECE
典型应用 脉冲计数、频率测量 (常结合捕获功能) 专用外部时钟输入、高频信号计数、需要独立ETR预分频/滤波的场景

输入捕获基本结构

结构图只使用一个通道,目前只能测量频率

输入捕获过程:

配置时基单元,启动定时器,CNT会在预分频之后的时钟驱动(驱动CNT的标准频率fc=72M/预分频系数)下,不断自增(CNT为测周法用来计数计时)

输入捕获通道1的GPIO口,输入一个方波信号,经过滤波器和边沿检测,选择TI1FP1为上升沿触发,之后输入选择直连的通道,分频器选择不分频。当TI1FP1出现上升沿之后,CNT的当前计数值转运到CCR1。

同时,触发源选择,选中TI1FP1为触发信号,从模式选择复位操作。这样TI1FP1的上升沿也会触发CNT清零。

TI1FP1的执行顺序:先转运CNT的值到CCR,再触发从模式给CNT清零。或者是非阻塞的同时转移,CNT的值转移到CCR,同时0转移到CNT里面去。

当信号出现一个上升沿,CCR1=CNT(把CNT的值转运到CCR1)这是输入捕获自动执行的。然后CNT=0,清零计数器,这是从模式自动执行的。

之后在一个周期之内,CNT在标准时钟的驱动下不断自增。由于已经将CNT清零,所以CNT就是从上升沿开始,从0开始计数一直加直到下一次上升沿来临,后执行相同操作(CCR=CNT,CNT=0)。

此过程中,CCR1始终保持最新一个周期的计数值N,后fc/N=信号频率

注意:

①CNT值有上限,ARR一般设置为最大65535,CNT最大计数65535,若信号频率太低,CNT值可能溢出

②从模式触发源选择,只有TI1FP1和TI2FP2,因此,使用从模式自动清零CNT只能选择通道1或者2

PWMI基本结构

使用俩个通道同时捕获一个引脚,可以同时测量周期和占空比。

增加一个过程:TI1FP1配置上升沿触发,触发捕获和清零CNT,正常捕获周期。

再加上一个TI1FP2,配置下降沿触发,通过交叉通道,触发通道2捕获单元。

当信号出现一个上升沿,CCR1捕获CNT值,同时清零CNT,后CNT++,在下降沿时触发CCR2捕获CNT值,即CNT为一个周期内高电平的计数值,CCR2不触发CNT清零,CNT++,下一次上升沿,CCR1捕获CNT,CNT清零……

CCR1为一整个周期的计数值,CCR2为高电平期间的计数值

占空比=CCR2/CCR1

输入捕获模式测频率

(库函数引用STM32_stm32 tim16s-CSDN博客

1.输入捕获初始化

步骤:
①RCC开启时钟,把GPIO和TIM时钟打开
②GPIO初始化,把GPIO配置成输入模式(上拉输入/浮空输入)
③配置时基单元,CNT计数器在内部时钟驱动下自增运行
④配置输入捕获单元,包括滤波器,极性,直连通道还是价差通道,分频器参数
⑤选择从模式触发源TI1FP1
⑥选择从触发模式的操作
⑦开启定时器

2.初始化输入捕获单元

1.用结构体配置输入捕获单元函数
单一配置一个通道
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

2.输入捕获初始化的函数
快速配置俩个通道,把外设电路结构配置成PWMI模式
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

3.给输入捕获结构体赋一个初始值
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);

4.选择输入触发源TRGI(从模式触发源)
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

5.选择输出触发源TRGO(主模式输出的触发源)
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);

6.选择从模式
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);

7.单独配置通道1234分频器
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);

8.读取4个通道的CCR
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

输出比较模式:CCR只写,用SetCompare写入
输入捕获模式,CCR只读,用GetCapture读出

1.IC.c

明确指出:

STM32的定时器可以同时进行输入捕获和输出比较,因为定时器的不同通道是独立的。每个通道可以独立配置为输入捕获或输出比较模式;但是,同一个通道不能同时用于输入捕获和输出比较,因为每个通道只有一个捕获/比较寄存器(CCRx)和相应的模式配置位.

  1. 通道独立性

    • 每个定时器有4个独立通道(TIM1/TIM8有更多)

    • 每个通道可单独配置为:

      • 输入捕获(测量外部信号)

      • 输出比较(生成PWM/波形)

    • ✅ 关键:不同通道可同时使用不同功能

  2. 资源分配

    • 共享资源:计数器(CNT)、预分频器(PSC)、自动重载寄存器(ARR)

    • 独立资源:各通道的捕获/比较寄存器(CCRx)、捕获/比较模式寄存器

  3. 通道冲突避免

    TIM3:
      CH1(PA6) -> 输入捕获
      CH2(PA7) -> 输出比较
    • 同一通道不能同时用于输入和输出

    • 解决方案:使用不同物理通道

  4. 中断优先级管理

    // 设置捕获中断优先级
    HAL_NVIC_SetPriority(TIM3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
  5. 计数器模式选择

    • 推荐使用TIM_COUNTERMODE_UP(向上计数)

    • 避免使用中心对齐模式(可能引起捕获时间计算错误)

  6. 时钟频率考虑

    • 输入信号频率 < 定时器时钟频率/(2×滤波器)

    • 输出PWM频率 = 定时器时钟/((PSC+1)×(ARR+1))

  7. 注意事项:

1. 定时器的工作模式(如向上计数、向下计数等)是全局的,所以输入捕获和输出比较共享同一个计数器(CNT)。

2. 输入捕获和输出比较的功能是独立的,不会互相干扰,只要使用不同的通道。

3. 需要正确配置每个通道的相应寄存器。

     8. 举例说明(以TIM2为例,因为TIM2有4个通道):

- 通道1(PA0):输入捕获,用于捕获外部信号的上升沿。

- 通道2(PA1):输出比较,用于产生PWM信号。

- 通道3(PA2):输出比较,用于产生另一个PWM信号。

- 通道4(PA3):输出比较,用于产生第三个PWM信号。

void IC_init(void)
{
	//①开启时钟RCC,将TIM外设和GPIO外设时钟打开
	//APB1开启时钟
	//由于TIM2输出PWM,换TIM3输入捕获
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启TIM3时钟(APB1)
  
	//②GPIO初始化,把GPIO配置成输入模式(上拉输入/浮空输入)
	//TIM3的通道1和通道2对应PA6和PA7
	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);
	
  //③配置时基单元,CNT计数器在内部时钟驱动下自增运行
	//选择内部时钟
	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;//ARR自动重装器的值,设计最大,以防CNT溢出
	TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//PSC预分频器的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的重复计数器的值,初级没有
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  
	//④配置输入捕获单元,包括滤波器,极性,直连通道还是交叉通道,分频器参数
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//输入捕获通道1
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器,若有噪声,可增加滤波器参数,有效避免干扰
	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);
	
	//⑤选择从模式触发源TI1FP1
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//选择哪一个触发源
	
	//⑥选择从触发模式的操作
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//⑦开启定时器
	TIM_Cmd(TIM3,ENABLE);
	
}

//返回最新一个周期的频率值 Hz
uint32_t IC_GetFreqent(void)
{
	return 1000000/TIM_GetCapture1(TIM3);//Fre=72M/(PSC+1)/(ARR+1) ARR+1=100
	}//此刻PSC=72-1  N为CCR的值
2.IC.h
#ifndef __IC_H_
#define __IC_H_

uint32_t IC_GetFreqent(void);
void IC_init(void);


#endif
3.pwm.c(修改)
#include "stm32f10x.h"                  // Device header

void PWM_init(void)
{
	/*
	①开启时钟RCC,将TIM外设和GPIO外设时钟打开
	②配置时基单元和时钟源选择
	③配置输出比较单元,包括CCR值,输出比较模式,极性选择,输出使能参数
	④配置GPIO口,初始化为复用推挽输出配置
	⑤运行控制,启动计数器,输出PWM
	*/
	//①开启时钟RCC,将TIM外设和GPIO外设时钟打开
	//APB1开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启TIM2时钟(APB1)
	
	//使用TIM2的OC1/CH1通道,输出PWM
	//②配置时基单元和时钟源选择
	//选择内部时钟
	TIM_InternalClockConfig(TIM2);

	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up ;//向上计数
	TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR自动重装器的值
	TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSC预分频器的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的重复计数器的值,初级没有
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

	//③配置输出比较单元,包括CCR值,输出比较模式,极性选择,输出使能参数
	//选择PA0口→第一个输出通道
	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;//设置CCR
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);

	//通过引脚图,是PA0输出,重映射列表中查找PA15引脚也可以
	//④配置GPIO口,初始化为复用推挽输出配置
	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);

	//⑤运行控制,启动计数器,输出PWM
	TIM_Cmd(TIM2,ENABLE);

}
/*
调节PWM频率
f=72M(PSC+1)/(ARR+1)
占空比=1/(ARR+1)
俩个公式可知,单独控制PWM频率可以调节PSC
ARR固定100-1
*/
void PWM_set_PSC(uint16_t psc)
{
	//单独写入PSC函数
	TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Update);//重装模式(更新事件重装/立即重装)
}

4.main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "buzzer.h"
#include "pwm.h"
#include "IC.h"

void display(void)
{
	PWM_set_PSC(720-1);//Fre=72M/(PSC+1)/(ARR+1) ARR+1=100
	TIM_SetCompare1(TIM2,50);//Duty=CCR/(ARR+1) ARR+1=100
	
	//PWM模块已经将待测信号输出到PA0
	//PA0通过导线,输入到PA6(TIM3通道1)
	//通道1通过输入捕获模块测量得到频率
	
	
	
	OLED_ShowNum(1,6,IC_GetFreqent(),6);
	


}
int main(void)
{	
	
  OLED_Init();
	PWM_init();
	IC_init();
    OLED_ShowString(1,1,"Freq:000000Hz");
	while(1)
	{
		display();
	}
}

PWMI测量频率和占空比

1.IC.c代码改编

	//④配置输入捕获单元,包括滤波器,极性,直连通道还是价差通道,分频器参数
	//俩个通道同时捕获一个引脚模式PWMI模式
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//输入捕获通道
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器,若有噪声,可增加滤波器参数,有效避免干扰
	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);
	
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//输入捕获通道
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器,若有噪声,可增加滤波器参数,有效避免干扰
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;//边沿检测极性选择,下降沿触发
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//触发信号分频器,不分频就是每次触发都有效
	TIM_ICInitStructure.TIM_ICSelection= TIM_ICSelection_IndirectTI ;//配置输入选择器(直连通道/交叉通道)选择触发信号从哪一个引脚输入
  TIM_ICInit(TIM3,&TIM_ICInitStructure);

将输入捕获单元复制,配置IC2通道2(有点麻烦)

使用一个库函数:

TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);

自动将剩下的通道初始化成相反的配置
函数仅支持通道1和通道2配置

//返回最新一个周期的频率值 Hz
uint32_t IC_GetFreqent(void)
{
	return 1000000/TIM_GetCapture1(TIM3);//Fre=72M/(PSC+1)/(ARR+1) ARR+1=100
}//此刻PSC=72-1  N为CCR的值

//获取占空比的函数
uint32_t IC_GetGuty(void)
{
	return TIM_GetCapture2(TIM3)*100/TIM_GetCapture1(TIM3);
}

2.main.c

void display(void)
{
	PWM_set_PSC(720-1);//Fre=72M/(PSC+1)/(ARR+1) ARR+1=100
	TIM_SetCompare1(TIM2,50);//Duty=CCR/(ARR+1) ARR+1=100
	
	//PWM模块已经将待测信号输出到PA0
	//PA0通过导线,输入到PA6(TIM3通道1)
	//通道1通过输入捕获模块测量得到频率
	
	
	
	OLED_ShowNum(1,6,IC_GetFreqent(),6);
	
	
	OLED_ShowNum(2,6,IC_GetGuty(),3);
	

}
int main(void)
{	
	
  OLED_Init();
	PWM_init();
	IC_init();
    OLED_ShowString(1,1,"Freq:000000Hz");
    OLED_ShowString(2,1,"Duty:000%");
	while(1)
	{
		display();
	}
}

测评率的性能:

①测频率的范围:

测量频率下限:

标准频率1MHz,计数器最大只能计数65535,最低频率1M/65535≈15Hz

若想标准频率更低,加大预分频系数

测量频率上限:1MHz,根据误差承受范围决定

提高频率上限,降低PSC,提高标准频率,上限提高

误差分析:

①正负1误差

②晶振误差

输入捕获预输出比较区别

特性 输入捕获 输出比较
方向 输入 (监测外部信号) 输出 (驱动引脚动作)
主要目的 测量外部事件发生的时间点 预设时间点 控制引脚电平
触发源 外部信号边沿 (引脚) 内部计数器达到预设值 (比较匹配)
核心动作 捕获/锁存当前计数器值 (记录时刻) 改变引脚状态 (驱动动作)
寄存器操作 硬件自动读取计数器值存入捕获寄存器 用户写入目标值到比较寄存器
典型应用 脉冲宽度测量、频率测量、周期测量、编码器 PWM 生成、方波生成、精确时间触发、单脉冲

简单类比:

  • 输入捕获 像一个秒表:当外部事件(比如运动员冲过终点线)发生时,你按下按钮(硬件自动完成),秒表记录下那一刻的时间。

  • 输出比较 像一个闹钟:你预先设定好一个时间(写入比较寄存器),当钟表走到那个时间(计数器匹配),闹钟就会响(引脚电平改变/动作发生)。


网站公告

今日签到

点亮在社区的每一天
去签到