STM32 基于外部时钟源的 PWM 测量

时钟配置(72MHz 系统时钟)、TIM2 PWM 输出(PA0,10Hz)保持不变;

TIM3 引脚仍为 PA6(CH1),但功能从「输入捕获」改为「外部时钟源输入」。

  1. TIM3 外部时钟源配置

打开 CubeMX → 进入 TIM3 的「Configuration」界面;

第一步:配置从模式(Slave Mode)

点击「Slave Mode Configuration」标签;

Trigger Selection(触发源):选择 TI1FP1(TIM3_CH1 引脚的滤波后信号,即 PWM 输入);

Slave Mode(从模式):选择 External Clock Mode 2(外部时钟模式 2,由触发源驱动计数器);

Trigger Polarity(触发极性):选择 Rising(上升沿触发计数,对应 PWM 的上升沿);

Filter(滤波):设为 0(无滤波,若 PWM 有噪声可设 1~15);

Prescaler(分频):设为 0(不分频,每个上升沿都计数);

第二步:计数器基础配置

Counter Settings:

Counter Mode:Up(向上计数);

Prescaler (PSC):0(外部时钟源模式下,内部 PSC 失效,仅外部分频生效);

Counter Period (ARR):65535(16 位最大值,避免快速溢出);

Auto-reload preload:Enabled;

第三步:启用 TIM3 更新中断(用于检测溢出 / 计数完成)

进入「NVIC Settings」→ 勾选 TIM3 global interrupt,优先级默认即可;

点击「OK」保存配置,重新生成代码。

复制代码
#include "tim.h"
#include "stdio.h"

// TIM3 外部时钟源相关变量
uint32_t tim3_counter = 0;       // TIM3计数器值
uint32_t pwm_period_ticks = 0;   // PWM周期对应的计数值
float pwm_frequency_ext = 0.0f;   // 外部时钟模式下的PWM频率
uint8_t tim3_overflow_flag = 0;  // TIM3溢出标志
uint32_t overflow_count_ext = 0; // 溢出次数


// TIM3全局中断处理函数
void TIM3_IRQHandler(void)
{
  // 处理HAL库默认中断
  HAL_TIM_IRQHandler(&htim3);
  
  // 检测更新中断(溢出/计数器归零)
  if (__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_UPDATE) != RESET)
  {
    __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE);
    overflow_count_ext++; // 溢出次数+1
    
    // 计算PWM周期(外部时钟源下,1个tick=1个PWM上升沿)
    // 若ARR=65535,溢出一次表示计数了65536个PWM周期
    pwm_period_ticks = 65536 * overflow_count_ext;
    // 10Hz PWM的理论计数值:1秒内计数10次 → 频率=计数次数/时间
    pwm_frequency_ext = (float)pwm_period_ticks / (overflow_count_ext * (65536.0f / 10.0f));
    
    // 重置标志(按需)
    tim3_overflow_flag = 1;
    overflow_count_ext = 0;
  }
}



int main(void)
{
  // 1. 基础初始化
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  
  // 2. 启动TIM2 PWM输出(10Hz,PA0)
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 499); // 50%占空比
  
  // 3. 启动TIM3计数器(外部时钟源模式)
  HAL_TIM_Base_Start_IT(&htim3); // 启动TIM3基础定时器+中断
  
  // 4. 主循环
  while (1)
  {
    // 读取TIM3当前计数值(即已捕获的PWM上升沿次数)
    tim3_counter = __HAL_TIM_GET_COUNTER(&htim3);
    
    // 溢出后打印结果
    if (tim3_overflow_flag)
    {
      printf("TIM3计数值:%lu,PWM频率:%.2f Hz\r\n", tim3_counter, pwm_frequency_ext);
      tim3_overflow_flag = 0;
    }
    
    // 实时打印计数值(每500ms)
    HAL_Delay(500);
    printf("当前计数值:%lu(溢出次数:%lu)\r\n", tim3_counter, overflow_count_ext);
  }
}

四、简化版:直接通过计数值计算频率
若只需测量 10Hz PWM(周期 100ms),可不用等溢出,直接在主循环计算:
c
运行
while (1)
{
  // 记录初始计数值和时间
  uint32_t start_cnt = __HAL_TIM_GET_COUNTER(&htim3);
  uint32_t start_tick = HAL_GetTick();
  
  // 延时1秒(10Hz PWM应计数10次)
  HAL_Delay(1000);
  
  // 记录结束计数值和时间
  uint32_t end_cnt = __HAL_TIM_GET_COUNTER(&htim3);
  uint32_t end_tick = HAL_GetTick();
  
  // 计算实际计数次数(考虑溢出)
  uint32_t cnt_diff = end_cnt - start_cnt + (overflow_count_ext * 65536);
  // 计算频率 = 计数次数 / 实际时间(秒)
  pwm_frequency_ext = (float)cnt_diff / ((end_tick - start_tick) / 1000.0f);
  
  printf("1秒内计数:%lu次,PWM频率:%.2f Hz\r\n", cnt_diff, pwm_frequency_ext);
  
  // 重置溢出计数
  overflow_count_ext = 0;
}

硬件接线:必须将 TIM2_CH1(PA0)与 TIM3_CH1(PA6)短接,PWM 信号才能输入到 TIM3 作为外部时钟;

触发极性选择:若选Rising则按上升沿计数,选Falling则按下降沿计数,需与 PWM 的有效边沿匹配;

外部时钟模式区别:

外部时钟模式 1:由 TRGI 触发计数器启动 / 停止;

外部时钟模式 2:由 TRGI 直接驱动计数器计数(推荐用于 PWM 时钟源);

计数精度:外部时钟模式下,TIM3 的计数精度完全由 PWM 信号的边沿决定,无内部时钟分频误差。

总结

CubeMX 核心配置:TIM3 选择「External Clock Mode 2」,触发源设为 TI1FP1(TIM3_CH1),触发极性为上升沿,启用更新中断;

代码逻辑:启动 TIM3 基础定时器 + 中断,通过计数器值 / 溢出次数计算 PWM 频率(10Hz PWM 每秒应计数 10 次);

优势:相比输入捕获,外部时钟源模式无需逐边沿捕获,直接通过计数次数反映 PWM 频率,更简洁且抗干扰性更强。

相关推荐
HQB20268 小时前
EG1198|屹晶微电子 120V 内置 MOS 异步降压 DC‑DC(高性价比)
嵌入式硬件·硬件工程
果壳science10 小时前
张祥前实验如何获取正电荷
笔记·科技·嵌入式硬件·硬件工程·制造
南山电子nscn10 小时前
中科芯CETC汽车电池管理系统BMS进口芯片国产型号替代指南
单片机·汽车·bms
沉淀的.晴天10 小时前
can总线
stm32
桀人10 小时前
认识AT24C02
stm32·单片机·嵌入式硬件
国科安芯12 小时前
星间激光通信终端CANFD控制网络的时延确定性与辐射可靠性
网络·嵌入式硬件·信息与通信·canfd·低轨卫星·商业航天·抗辐射
一直C12 小时前
嵌入式 Linux 驱动开发学习笔记:内核定时器、platform 总线与 I²C 驱动
linux·驱动开发·嵌入式硬件·学习·imx6ull
传感器与混合集成电路12 小时前
150MHz主频、8路DAC与6路PWM:JLH221360伺服控制SIP解析
嵌入式硬件
comyccccc12 小时前
STM32PID控制板设计全解析学习笔记
单片机·嵌入式硬件
碧海银沙音频科技研究院13 小时前
实现炬芯ATS308X的usb cdc 串口IAP 固件升级功能实现
人工智能·嵌入式硬件·深度学习·算法