摘要今天完成了 TIM2 输出 PWM、TIM3 输入捕获测量频率与占空比这一整套实验链路的梳理。重点不是死记库函数而是理解TIM2 负责产生 PWMTIM3 通过 PWM 输入模式同时记录完整周期和高电平时间。同时排查了函数声明、函数定义和调用名称不一致造成的隐式声明与 Undefined symbol 链接错误。当前代码逻辑已整理最终 OLED 实测频率和占空比结果标记为“待确认”。开发环境项目配置MCUSTM32F103C8T6IDEKeil μVision 5编译器ARMCC V5.06 update 7固件库STM32F10x 标准外设库PWM输出TIM2_CH1 / PA0输入捕获TIM3_CH1 / PA6实验接线PA0 接 PA6显示OLED一、实验整体链路TIM2 从 PA0 输出 PWM↓ PA0 接 PA6TIM3 从 PA6 测量 PWM↓CCR1 记录完整周期CCR2 记录高电平时间↓计算频率和占空比并显示到 OLEDTIM2 是“信号发生器”TIM3 是“测量仪”。二、PWM 输出参数怎么得到 100 Hz、80% 占空比现象主程序使用 PWM_SetPrescaler(7200-1) 和 PWM_SetCompare(80)PWM 初始化中的 ARR 为 100-1需要确认最终输出参数。原因TIM2 时钟按 72 MHz 计算经过 7200 分频后为 10 kHzARR1 为 100因此输出频率为 100 Hz。CCR 为 80因此占空比为 80%。72 MHz ÷ 7200 10 kHz10 kHz ÷ 100 100 Hz80 ÷ 100 80%周期 10 ms高电平时间 8 ms图1 PWM频率、占空比与PSC/ARR/CCR的关系解决方法保持 PSC 控制计数速度、ARR 控制周期、CCR 控制高电平时间。当前参数保持 ARR99、PSC7199、CCR80。验证结果根据参数计算理论输出为 100 Hz、80% 占空比。实际测量结果待确认。三、调用 PWM 函数时出现隐式声明和 Undefined symbol现象Keil 提示 PWM_SetPrescaler declared implicitly并在链接阶段提示 Undefined symbol PWM_SetCompare。原因PWM.h、PWM.c 和 main.c 中的接口名称没有统一例如 PWM_SetCompare 与 PWM_SetCompare1、PWM_SetPrescaler 与 PWM_Prescaler。解决方法声明、定义、调用统一使用 PWM_SetCompare() 和 PWM_SetPrescaler()。修改头文件后执行 Rebuild all target files。void PWM_SetCompare(uint16_t Compare){TIM_SetCompare1(TIM2, Compare);}void PWM_SetPrescaler(uint16_t Prescaler){TIM_PrescalerConfig(TIM2, Prescaler,TIM_PSCReloadMode_Immediate);}验证结果错误原因已确认。最终重新编译结果待确认。四、TIM3 输入捕获却误初始化了 TIM2现象输入捕获模块开启的是 TIM3但时基初始化曾写为 TIM_TimeBaseInit(TIM2, ...)。原因复制定时器代码后外设实例没有全部替换。这样 TIM2 被再次修改TIM3 没有获得预期的 PSC 和 ARR。解决方法改为 TIM_TimeBaseInit(TIM3, TIM_TimeBaseInitStructure)并逐项检查 IC.c 中所有定时器参数是否均为 TIM3。验证结果代码中的时基对象已修正为 TIM3。实际测频结果待确认。五、输入捕获模块里不需要配置 PWM 输出比较现象IC.c 中同时配置 TIM_OC1Init() 和 TIM_PWMIConfig()。原因TIM_OC1Init() 用于输出比较而 TIM3 在本实验中只负责输入捕获。解决方法删除 TIM_OCInitTypeDef 和整段 TIM_OC1Init() 输出配置PWM 输入模式只保留 TIM_PWMIConfig()。验证结果输入捕获模块职责已整理为“只测量、不输出”。最终运行结果待确认。六、CCR1 和 CCR2 到底记录什么现象PWM 输入模式同时使用 CCR1 和 CCR2容易混淆两者的含义。原因TI1 上升沿作为复位触发源。CH1 直接捕获相邻上升沿之间的完整周期CH2 间接捕获上升沿到下降沿之间的高电平时间。上升沿CNT 清零并开始计时下降沿CCR2 保存高电平时间下一个上升沿CCR1 保存完整周期CNT 再次清零100 Hz、80% 理论值CCR1 ≈ 10000CCR2 ≈ 8000解决方法记住“频率看 CCR1占空比看 CCR2/CCR1”。验证结果CCR1 和 CCR2 的物理含义已经明确。实际捕获值待确认。七、频率和占空比公式现象需要把 TIM3 捕获值换算为可显示的频率和占空比。原因TIM3 按 72 MHz 时钟和 PSC71 配置后计数频率为 1 MHz每个计数约为 1 μs。频率 1000000 ÷ (CCR1 1)占空比 (CCR2 1) × 100 ÷ (CCR1 1)解决方法读取 CCR1、CCR2 后进行计算并对 Period0 做保护避免没有有效输入时产生异常结果。uint32_t IC_GetFreq(void){uint16_t Period TIM_GetCapture1(TIM3);if (Period 0) return 0;return 1000000 / (Period 1);}uint32_t IC_GetDuty(void){uint16_t Period TIM_GetCapture1(TIM3);uint16_t HighTime TIM_GetCapture2(TIM3);if (Period 0) return 0;return (HighTime 1) * 100 / (Period 1);}验证结果理论输入为 100 Hz、80% 时OLED 应接近显示 Freq:00100Hz、Duty:80%。实际显示待确认。八、固定排查清单出现 declared implicitly先检查头文件中的函数声明。出现 Undefined symbol检查源文件中是否存在完全同名的函数定义。声明、定义、调用三处的函数名和参数必须完全一致。配置 TIM3 时检查所有库函数的第一个参数是否误写为 TIM2。输入捕获模块不要混入 TIM_OCxInit() 输出比较配置。使用 TIM_PWMIConfig() 后明确 CCR1 记录周期、CCR2 记录高电平时间。检查 PA0 是否真正连接 PA6。确认输出为 TIM2_CH1输入为 TIM3_CH1。计算频率前确认 TIM3 实际计数频率。没有输入信号时对捕获值为 0 的情况做保护。修改头文件或接口后执行 Rebuild all target files。编译通过后仍要用 OLED 或示波器验证实际结果。