脉冲计数实现
将定时器 2 通道 2 输入的低电平脉冲作为定时器 2 的时钟,并通过串口打印脉冲数 PSC=0,ARR=65535 外部时钟模式1、触发选择、上升沿触发、不分频、不滤波。
“外部时钟模式 1(ECM1)用 TIM2_CH2 计脉冲
main.c:
#include "sys.h" // 项目通用头(通常会包含芯片HAL头文件及时钟配置)
#include "delay.h" // 延时相关
#include "led.h" // LED 驱动(用于简单指示)
#include "uart1.h" // 串口1 打印
#include "counter.h" // 本实验的计数器对外接口(见下方)int main(void)
{HAL_Init(); /* 初始化HAL库:复位外设、初始化Flash接口、Systick等 */stm32_clock_init(RCC_PLL_MUL9); /* 配置系统时钟到72MHz(HSE*9),为后续外设/内核提供时钟 */led_init(); /* LED初始化(可选,用于指示运行状态) */uart1_init(115200); /* 串口1初始化为115200-8-N-1,用于打印结果 */printf("hello world!\r\n");/* * 计数器初始化:* - arr = 65536 - 1 => 自动重装载寄存器ARR=0xFFFF(16位满量程)* - psc = 0 => 预分频=0(即不分频,计数器每来一个外部脉冲就+1)** 说明:TIM2本身是32位定时器,但你把ARR设成了16位最大值,这样更直观地做“0~65535”循环计数。* 如果你要更大计数范围,可把ARR设更大(比如0xFFFFFFFF,需要按32位读改)。*/counter_init(65536 - 1, 0);while(1){/* 方式1:读取当前CNT并在变化时打印(示例与原逻辑一致) */count_get();/* 方式2(推荐做实时计数):得到“自上次调用以来的增量脉冲数”,更高效,避免频繁printf阻塞uint32_t incr = count_get_delta();if (incr) { printf("inc: %lu\r\n", incr); }*/// 适当小延时,避免打印过快造成串口阻塞(根据实际脉冲频率调整)delay_ms(1);}
}
counter.h:
#ifndef __COUNTER_H__
#define __COUNTER_H__#include "stm32f1xx_hal.h" // 确保包含到F1的HAL头;若你的sys.h已包含,可按需修改#ifdef __cplusplus
extern "C" {
#endif/* 对外接口函数声明 *//*** @brief 外部时钟模式1:用 TIM2_CH2 计数外部脉冲* @param arr 自动重装载值(周期 - 1),例如 65536 - 1 表示16位满量程* @param psc 预分频(0 表示不分频)*/
void counter_init(uint32_t arr, uint16_t psc);/*** @brief 读取当前CNT值,若变化则通过printf打印(和你的原函数一致)*/
void count_get(void);/*** @brief 返回“自上次调用以来的增量脉冲数”,自动处理ARR回卷(推荐统计增量用)* @return 增量(0 表示无新增脉冲)*/
uint32_t count_get_delta(void);#ifdef __cplusplus
}
#endif#endif /* __COUNTER_H__ */
counter.c:
#include "counter.h"
#include "stdio.h"/* 全局句柄:TIM2 用于计外部脉冲 */
TIM_HandleTypeDef counter_handle = {0};/* 保存上/下两次读取的计数值,用于变化打印与增量计算 */
static volatile uint32_t g_old_cnt = 0; // 上一次读取的CNT
static volatile uint32_t g_arr = 0xFFFF; // 记录配置的ARR,便于做回卷运算/*** @brief 初始化 TIM2 为“外部时钟模式1”,在 CH2(PA1) 上计数外部脉冲* @param arr 自动重装载值(周期-1),例:65536-1* @param psc 预分频系数(0=不分频)*/
void counter_init(uint32_t arr, uint16_t psc)
{/* ------------ 1. 基本定时器参数配置(只负责计数器本体) ------------ */counter_handle.Instance = TIM2; // 选择 TIM2counter_handle.Init.Prescaler = psc; // 计数器预分频:0=不分频counter_handle.Init.Period = arr; // 自动重装载值 ARR,计数达到ARR后回到0counter_handle.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数counter_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 内部分频不再分(DIV1)HAL_TIM_Base_Init(&counter_handle); // 初始化基本定时器(装载上述配置)g_arr = arr; // 保存ARR,供回卷计算/* ------------ 2. 配置输入捕获通道(把CH2当作触发源TI2FP2) ------------ */TIM_IC_InitTypeDef ic_cfg = {0};ic_cfg.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; // 触发沿:上升沿(与你的“上升沿触发”一致)// 若要“低电平脉冲起始”为有效,可改成 FALLING(下降沿):// ic_cfg.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;ic_cfg.ICSelection = TIM_ICSELECTION_DIRECTTI; // 选择直连TI(CH2直接接到IC)ic_cfg.ICPrescaler = TIM_ICPSC_DIV1; // 输入捕获不分频(不跳边)ic_cfg.ICFilter = 0; // 不滤波(0~15 可选,>0 可做数字滤波,抗抖/毛刺)HAL_TIM_IC_ConfigChannel(&counter_handle, &ic_cfg, TIM_CHANNEL_2);/* ------------ 3. 配置从模式为“外部时钟模式1”(ECM1) ------------ */TIM_SlaveConfigTypeDef slave_cfg = {0};slave_cfg.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; // 外部时钟模式1:由触发输入驱动计数器时钟slave_cfg.InputTrigger = TIM_TS_TI2FP2; // 触发选择:TI2 的滤波后信号(来自CH2)slave_cfg.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING; // 触发极性:上升沿// 若改下降沿,对应改为 TIM_TRIGGERPOLARITY_FALLINGslave_cfg.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; // 触发预分频(对触发边沿再做1/2/4/8分频)slave_cfg.TriggerFilter = 0; // 触发滤波(通常对ETR有效;TIx滤波主看ICFilter)HAL_TIM_SlaveConfigSynchro(&counter_handle, &slave_cfg);/* ------------ 4. 使能通道与启动计数 ------------ */HAL_TIM_IC_Start(&counter_handle, TIM_CHANNEL_2); // 使能CH2输入捕获(允许触发链路工作)HAL_TIM_Base_Start(&counter_handle); // 打开计数器(CEN=1)。此后,每个外部有效边沿 => CNT+1
}/*** @brief 由HAL库自动回调:定时器输入捕获 MSP(底层)初始化* @note 在这里打开GPIO/TIM时钟,并把PA1配置成输入*/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM2){GPIO_InitTypeDef gpio = {0};__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能 GPIOA 时钟(PA1 在 A 口)__HAL_RCC_TIM2_CLK_ENABLE(); // 使能 TIM2 时钟/* TIM2_CH2 => PA1,配置为“输入”* F1系列定时器通道的复用是固定映射,无需设置AF功能号。* 建议上拉(PULLUP),让空闲时为高电平,这样外部“低脉冲”更清晰地产生一个“下降+上升”的边沿对。*/gpio.Pin = GPIO_PIN_1; // PA1gpio.Mode = GPIO_MODE_INPUT; // 输入模式(F1用这个即可;若是F4/07等系列可用GPIO_MODE_AF_PP/OD并上拉)gpio.Pull = GPIO_PULLUP; // 上拉:空闲=高,抗干扰gpio.Speed = GPIO_SPEED_FREQ_HIGH; // 对输入影响不大,可保持高速HAL_GPIO_Init(GPIOA, &gpio);}
}/*** @brief 读取当前CNT,若变化则打印(与你原始逻辑保持一致)* @note printf 可能阻塞,脉冲频率高时建议换成 count_get_delta() 方案做累计*/
void count_get(void)
{uint32_t new_cnt = __HAL_TIM_GET_COUNTER(&counter_handle); // 读取TIM2->CNT(0..ARR循环)if (new_cnt != g_old_cnt) // 仅在变化时打印,减少串口负担{g_old_cnt = new_cnt; // 更新历史值printf("CNT: %lu\r\n", (unsigned long)new_cnt); // 打印当前计数}
}/*** @brief 返回“自上次调用以来”的增量脉冲数,自动处理ARR回卷* @return 增量(0 表示期间无新脉冲)*/
uint32_t count_get_delta(void)
{uint32_t cur = __HAL_TIM_GET_COUNTER(&counter_handle); // 当前CNTuint32_t inc;if (cur >= g_old_cnt) {inc = cur - g_old_cnt; // 常规情况:直接相减} else {inc = (g_arr + 1u - g_old_cnt) + cur; // 回卷情况:先从old到ARR,再从0到cur}g_old_cnt = cur; // 更新历史值return inc;
}
二、参数/函数逐点解释
1) ARR = 65536 - 1
为什么常这么写?
计数范围是
0 … ARR
,所以把ARR=65536-1
等价于0…65535
(16位满量程)。你当然可以改成别的数(比如 9999),那就是 0…9999 后回卷。
若想极大范围,TIM2 是 32 位定时器,可以把
ARR
设得更大(如0xFFFFFFFF
),但相应地:CNT
用uint32_t
读取与存储;增量/回卷逻辑也按 32 位来处理。
2) PSC = 0
预分频器对“计数时钟”再做一次分频,
PSC=0
表示不分频。在外部时钟模式 1 下,“有效触发边沿”就是计数器时钟源;通常我们希望每个脉冲计一次,所以
PSC=0
。
3) TIM_SLAVEMODE_EXTERNAL1 + TIM_TS_TI2FP2
外部时钟模式1(ECM1):把“触发输入(TRGI)”当作计数器时钟。
TIM_TS_TI2FP2
:把 CH2 的滤波后输入(TI2FP2)选作“触发输入”。效果:PA1 上每来一次选定极性的有效边沿 => CNT + 1。
4) 极性与滤波
ICPolarity=RISING
/TriggerPolarity=RISING
:上升沿触发(你现在的需求)。若你的外部脉冲是“低电平脉冲”(空闲高,短时拉低),一般脉冲开始是一个下降沿,脉冲结束是一个上升沿。
你希望“每个低脉冲只记一次”,通常选其中一个边沿(比如上升沿或下降沿),二选一即可。
想在“低脉冲开始就计数”,把极性改成
FALLING
。
滤波:
ICFilter
(0~15)对 TIx 输入做数字滤波(多个采样一致才认为有效),可抑制毛刺/抖动。频率高且信号干净时设 0;有噪声/机械抖动时适当增大(但会降低最高可计频率)。
5) HAL_TIM_IC_Start
与 HAL_TIM_Base_Start
HAL_TIM_IC_Start
:打开通道的输入捕获功能(允许 TI2FP2 形成触发)。HAL_TIM_Base_Start
:真正使能计数器(CEN=1)。两者都要开。
三、脉冲计数原理(外部时钟模式1)
可以用一个简化方框图理解:
外部信号(到PA1=TIM2_CH2)│▼输入滤波(ICFilter) ──> 形成 TI2FP2(带滤波的CH2信号)│▼触发选择(TS=TI2FP2) ──> 触发极性(上升/下降沿) ──> “触发事件”│└─────────────> 设从模式为 External1:把“触发事件”当作计数器时钟│▼计数器 CK_CNT│▼CNT = CNT + 1 (每个有效边沿+1)
核心思想:不是用内部APB时钟去“滴答”,而是把外部边沿当作“时钟脉冲”。
因此 CNT 的步进频率 = 外部有效边沿频率(再考虑触发/IC分频)。
你要的是“低电平脉冲的次数”,那就选定某个边沿(比如脉冲结束的上升沿),每次出现就
CNT+1
。
1. TIM_HandleTypeDef.Init
的参数
这是定时器的基本配置部分。
counter_handle.Init.Prescaler = psc;
counter_handle.Init.Period = arr;
counter_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
counter_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
Prescaler:预分频器 (PSC)
0
~0xFFFF
实际计数频率 = 计数时钟 / (PSC+1)
Period:自动重装载寄存器 (ARR)
定时器计数的上限,CNT 计到 ARR 后溢出回 0。
CounterMode:计数模式
TIM_COUNTERMODE_UP
(向上计数)TIM_COUNTERMODE_DOWN
(向下计数)TIM_COUNTERMODE_CENTERALIGNED1/2/3
(中心对齐模式,常用于PWM)
ClockDivision:时钟分频(对内部时钟的进一步分频)
TIM_CLOCKDIVISION_DIV1
TIM_CLOCKDIVISION_DIV2
TIM_CLOCKDIVISION_DIV4
通常用于滤波/死区计数。
2. TIM_IC_InitTypeDef
的参数
输入捕获通道配置。
ic_cfg.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
ic_cfg.ICSelection = TIM_ICSELECTION_DIRECTTI;
ic_cfg.ICPrescaler = TIM_ICPSC_DIV1;
ic_cfg.ICFilter = 0;
ICPolarity(极性)
TIM_INPUTCHANNELPOLARITY_RISING
(上升沿)TIM_INPUTCHANNELPOLARITY_FALLING
(下降沿)TIM_INPUTCHANNELPOLARITY_BOTHEDGE
(双边沿)
ICSelection(选择)
TIM_ICSELECTION_DIRECTTI
(直连输入 TIx → 通道)TIM_ICSELECTION_INDIRECTTI
(间接输入,另一通道)TIM_ICSELECTION_TRC
(触发控制器输入)
ICPrescaler(输入分频)
TIM_ICPSC_DIV1
(每个有效边沿都计)TIM_ICPSC_DIV2
(每 2 个有效边沿计 1)TIM_ICPSC_DIV4
(每 4 个)TIM_ICPSC_DIV8
(每 8 个)
ICFilter(滤波)
0
~15
,越大抗干扰能力越强,但能识别的最高频率下降。常用于抖动/毛刺信号。
3. TIM_SlaveConfigTypeDef
的参数
从模式配置,用于外部时钟/触发同步。
slave_cfg.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
slave_cfg.InputTrigger = TIM_TS_TI2FP2;
slave_cfg.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
slave_cfg.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
slave_cfg.TriggerFilter = 0;
SlaveMode(从模式)
TIM_SLAVEMODE_DISABLE
(关闭从模式)TIM_SLAVEMODE_RESET
(触发信号使 CNT 复位)TIM_SLAVEMODE_GATED
(触发信号作为门控)TIM_SLAVEMODE_TRIGGER
(触发信号启动定时器)TIM_SLAVEMODE_EXTERNAL1
(外部时钟模式1,脉冲作为时钟源)← 你用的
InputTrigger(触发输入源)
TIM_TS_TI1FP1
(通道1的滤波输入)TIM_TS_TI2FP2
(通道2的滤波输入)← 你用的TIM_TS_ETRF
(外部触发输入 ETR)TIM_TS_ITR0~3
(内部触发,用于定时器之间联动)
TriggerPolarity(触发极性)
TIM_TRIGGERPOLARITY_RISING
TIM_TRIGGERPOLARITY_FALLING
TIM_TRIGGERPOLARITY_BOTHEDGE
TriggerPrescaler(触发预分频)
TIM_TRIGGERPRESCALER_DIV1
TIM_TRIGGERPRESCALER_DIV2
TIM_TRIGGERPRESCALER_DIV4
TIM_TRIGGERPRESCALER_DIV8
TriggerFilter(触发滤波)
0
~15
,抗干扰。
4. GPIO_InitTypeDef
的参数
IO 口配置(初始化 PA1)。
gpio.Pin = GPIO_PIN_1;
gpio.Mode = GPIO_MODE_INPUT;
gpio.Pull = GPIO_PULLUP;
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
Pin:选择引脚,如
GPIO_PIN_0 | GPIO_PIN_1
。Mode:模式
GPIO_MODE_INPUT
(输入)GPIO_MODE_OUTPUT_PP
(推挽输出)GPIO_MODE_OUTPUT_OD
(开漏输出)GPIO_MODE_AF_PP
(复用推挽)GPIO_MODE_AF_OD
(复用开漏)GPIO_MODE_ANALOG
(模拟输入)
Pull:上下拉
GPIO_NOPULL
GPIO_PULLUP
GPIO_PULLDOWN
Speed:输出速度(对输入无关)
GPIO_SPEED_FREQ_LOW
GPIO_SPEED_FREQ_MEDIUM
GPIO_SPEED_FREQ_HIGH
不同结构体对应不同的参数选择:
计数器基本配置:
Prescaler
、Period
、CounterMode
、ClockDivision
输入捕获配置:
ICPolarity
、ICSelection
、ICPrescaler
、ICFilter
从模式配置:
SlaveMode
、InputTrigger
、TriggerPolarity
、TriggerPrescaler
、TriggerFilter
GPIO 配置:
Pin
、Mode
、Pull
、Speed
STM32 HAL 定时器常见配置参数速查表:每张表都包含:字段、可选宏/取值、含义/作用、常用场景示例(含你本l例“外部时钟模式1计数”的推荐值)。
TIM_Base 初始化(TIM_HandleTypeDef.Init
)
字段 | 可选值/范围 | 作用 | 常用场景示例 |
---|---|---|---|
Prescaler | 0 ~ 0xFFFF (F1) | 计数器预分频:计数时钟 = 输入时钟 / (PSC+1) | 外部时钟计数:0 (每个外部边沿+1);定时中断:按期望溢出频率计算 |
Period | 0 ~ 0xFFFF (F1,16位TIM);0~0xFFFFFFFF (32位TIM,如 TIM2/5) | 自动重装载(ARR),CNT 到 ARR 后回卷 | 计数器满量程:65535 (写 65536-1 );定时中断:按周期计算 |
CounterMode | TIM_COUNTERMODE_UP / DOWN / CENTERALIGNED1/2/3 | 计数模式 | 计数/定时:UP ;PWM中心对齐:CENTERALIGNEDx |
ClockDivision | TIM_CLOCKDIVISION_DIV1/2/4 | 内部分频,影响数字滤波/死区采样 | 一般 DIV1 |
RepetitionCounter * | 仅高级定时器(TIM1/TIM8) | N 次更新后再触发一次更新事件 | 高级PWM特殊应用 |
* F1 的 HAL 里 RepetitionCounter
通过 TIMx->RCR
访问,不总在 Init
中暴露。
输入捕获配置(TIM_IC_InitTypeDef
)
字段 | 可选值/范围 | 作用 | 外部脉冲计数(ECM1)推荐 | 频率/周期测量常用 |
---|---|---|---|---|
ICPolarity | TIM_INPUTCHANNELPOLARITY_RISING / FALLING / BOTHEDGE | 识别哪种边沿为有效 | 视脉冲定义:每个脉冲只记一次 → 选 RISING 或 FALLING 之一 | 测周期多用 RISING |
ICSelection | TIM_ICSELECTION_DIRECTTI / INDIRECTTI / TRC | 通道输入选择 | DIRECTTI (TIx直连) | DIRECTTI (两通道互联时另一路可用 INDIRECTTI ) |
ICPrescaler | TIM_ICPSC_DIV1/2/4/8 | 边沿抽取分频 | DIV1 (每个边沿都记) | 噪声多时可降采样 |
ICFilter | 0 ~ 15 | 数字滤波(越大越抗抖,但最高可测频率下降) | 0 或小值;有毛刺时增大 | 依输入噪声设定 |
从模式/触发配置(TIM_SlaveConfigTypeDef
)
字段 | 可选值/范围 | 作用 | 外部脉冲计数(ECM1)推荐 | 其他常见用途 |
---|---|---|---|---|
SlaveMode | DISABLE / RESET / GATED / TRIGGER / EXTERNAL1 | 从模式选择 | TIM_SLAVEMODE_EXTERNAL1 (外部时钟模式1) | 主从同步:TRIGGER /RESET ,门控:GATED |
InputTrigger | TIM_TS_TI1FP1 / TI2FP2 / ETRF / ITR0~3 | 触发源选择(TRGI) | TIM_TS_TI2FP2 (CH2 触发) | 定时器联动:ITR0~3 ;外部脚:ETRF |
TriggerPolarity | RISING / FALLING / BOTHEDGE | 触发极性 | 与 ICPolarity 对应选一个边沿即可 | 同步/门控时按边沿需求 |
TriggerPrescaler | DIV1/2/4/8 | 触发预分频 | DIV1 | 降低触发频率 |
TriggerFilter | 0 ~ 15 | 触发滤波 | 0 或小值 | 抗干扰 |
备注:ECM1 实际计数由 TRGI 驱动,TRGI 又来自
InputTrigger
选定的源(如 TI2FP2),因此 IC 配置 + 从模式配置 两部分要匹配。
主模式(触发输出)配置(TIM_MasterConfigTypeDef
)
字段 | 可选值/范围 | 作用 | 常用场景 |
---|---|---|---|
MasterOutputTrigger | TIM_TRGO_RESET / ENABLE / UPDATE / OC1 / OC1REF / OC2REF / OC3REF / OC4REF | 决定 TRGO 输出的事件 | 多定时器同步:用 UPDATE 让别的TIM以此为触发 |
MasterSlaveMode | TIM_MASTERSLAVEMODE_ENABLE/DISABLE | 使能主从模式(便于同步) | 级联/同步启动等 |
通道级(输出比较/PWM)配置(TIM_OC_InitTypeDef
)—(若你做PWM会用到)
字段 | 可选值/范围 | 作用 | 常用场景 |
---|---|---|---|
OCMode | TIM_OCMODE_TIMING / ACTIVE / INACTIVE / TOGGLE / PWM1 / PWM2 / FORCED_ACTIVE / FORCED_INACTIVE | 通道输出模式 | PWM1/PWM2 生成PWM |
Pulse | 0 ~ ARR | CCRx,占空比 | 占空比 = CCR / (ARR+1) |
OCPolarity | TIM_OCPOLARITY_HIGH/LOW | 有效电平极性 | 反相输出时选 LOW |
OCFastMode | ENABLE/DISABLE | 快速比较 | 特殊应用 |
外部触发输入(ETR)/ 外部时钟模式2(了解即可)
项 | 可选值/范围 | 说明 |
---|---|---|
外部时钟模式2 | HAL_TIM_ConfigClockSource(..., TIM_CLOCKSOURCE_ETRMODE2) | 通过 ETR 脚作为时钟源(与 ECM1 不同路径) |
ETR 极性/滤波/预分频 | TIM_ETRPOLARITY_NONINVERTED/INVERTED 、TIM_ETR_PRESCALER_DIV1/2/4/8 、TIM_ETR_FILTER 0~15 | 当使用 ETR 时可单独配置 |
GPIO 初始化(GPIO_InitTypeDef
,与定时器通道配合)
字段 | 可选值/范围 | 作用 | 外部脉冲计数建议 |
---|---|---|---|
Pin | GPIO_PIN_x | 选择引脚 | 例:GPIO_PIN_1 (TIM2_CH2=PA1) |
Mode | INPUT / AF_PP / AF_OD / OUTPUT_PP / OUTPUT_OD / ANALOG | 引脚模式 | F1 用输入模式(GPIO_MODE_INPUT )接外部信号 |
Pull | PULLUP / PULLDOWN / NOPULL | 上下拉 | 建议 PULLUP ,空闲为高,低脉冲清晰 |
Speed | LOW/MEDIUM/HIGH | 输出速率 | 对输入影响不大,可 HIGH |
常见“目标任务”推荐配置(速查)
目标 | 关键配置 | 备注 |
---|---|---|
外部脉冲计数(ECM1) | IC: Polarity=RISING(或FALLING), Selection=DIRECTTI, Prescaler=DIV1, Filter=0~N ;Slave: Mode=EXTERNAL1, Trigger=TIxFPx(与你用的通道对应), TriggerPolarity=同上, TriggerPrescaler=DIV1, TriggerFilter=0~N ;PSC=0, ARR=期望满量程 | 你这题:TIM2_CH2→TI2FP2 ,上升沿记一次脉冲 |
定时中断(TimeBase) | SlaveMode=DISABLE ;根据目标周期设置 PSC/ARR ;HAL_TIM_Base_Start_IT | 常用来做固定周期任务 |
PWM 输出 | OC: Mode=PWM1/2, Pulse=CCR, Polarity=HIGH ;PSC/ARR 设置PWM频率;HAL_TIM_PWM_Start | 频率 = TimerClk / (PSC+1) / (ARR+1) ;占空比 = CCR/(ARR+1) |
频率/占空比测量(PWM输入模式) | HAL_TIM_PWM_ConfigChannel / HAL_TIM_IC_ConfigChannel(成对配置) + HAL_TIM_...PWM 输入模式(或两通道互联) | 用一通道测周期,另一通道测高电平宽度 |
计算方法:
内部时钟定时模式
计数频率
f_cnt = f_tim / (PSC+1)
溢出频率
f_ov = f_cnt / (ARR+1)
→ 周期T = (PSC+1)*(ARR+1)/f_tim
外部时钟模式1(ECM1)
计数步进由触发有效边沿决定:
f_cnt ≈ f_edge / (ICPrescaler * TriggerPrescaler)
(忽略滤波饱和)
PWM
PWM 频率
f_pwm = f_tim / (PSC+1) / (ARR+1)
占空比
D = CCR / (ARR+1)