ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32 13 测周法测输入模式的频率

STM32 13 测周法测输入模式的频率 一、学习背景和目标学习背景本人在学习 STM32F103 单片机开发的过程中已经掌握了 GPIO 输出、定时器中断、OLED 显示等基础外设的使用方法。在进一步学习定时器的高级功能时希望通过一个完整的实战项目把 PWM 输出和输入捕获IC两个知识点串联起来加深对定时器工作原理的理解。学习目标掌握 STM32 定时器输出 PWM 波形的方法理解 ARR、PSC、CCR 三个寄存器的含义与配合关系掌握定时器输入捕获IC测量外部信号频率的原理与编程方法将 PWM 输出与输入捕获结合实现自己发波、自己测频的闭环验证通过 OLED 实时显示测量到的频率值完成一个可直观观察结果的完整小项目。二、连接图三、代码块main.c#includestm32f10x.h// Device header#includedelay.h#includeOLED.h#includepwm.h#includeIC.hintmain(){OLED_Init();pwm_init();IC_init();pwm_setpsc(720-1);//频率72M/(PSC1)(ARR1)pwm_setcompare(50);OLED_ShowString(1,1,Freq:);OLED_ShowString(1,12, HZ);while(1){OLED_ShowNum(1,6,get_fre(),6);}}pwm.c#includestm32f10x.h// Device headervoidpwm_init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivisionTIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterModeTIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period100-1;//ARRTIM_TimeBaseInitStructure.TIM_Prescaler720-1;//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter0;TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCModeTIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarityTIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputStateTIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse50;//CCRTIM_OC1Init(TIM2,TIM_OCInitStructure);TIM_Cmd(TIM2,ENABLE);}voidpwm_setcompare(uint16_tnum){TIM_SetCompare1(TIM2,num);}voidpwm_setpsc(uint16_tpsc){TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate);}IC.c#includestm32f10x.h// Device headervoidpwm_init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivisionTIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterModeTIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period100-1;//ARRTIM_TimeBaseInitStructure.TIM_Prescaler720-1;//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter0;TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCModeTIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarityTIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputStateTIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse50;//CCRTIM_OC1Init(TIM2,TIM_OCInitStructure);TIM_Cmd(TIM2,ENABLE);}voidpwm_setcompare(uint16_tnum){TIM_SetCompare1(TIM2,num);}voidpwm_setpsc(uint16_tpsc){TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate);}四、知识点1. PWM 输出原理PWMPulse Width Modulation脉冲宽度调制通过控制高低电平的占空比来模拟输出不同大小的电压。STM32 定时器输出 PWM 时计数器从 0 向上计数到 ARR当计数值小于 CCR 时输出高电平大于 CCR 时输出低电平从而形成周期性的方波。ARR自动重装载值决定 PWM 的周期即频率。频率 72M / ((PSC1) × (ARR1))。PSC预分频器对定时器时钟进行分频用于降低计数频率配合 ARR 共同决定 PWM 频率。CCR捕获/比较寄存器决定占空比。占空比 CCR / (ARR1) × 100%。本项目中PSC 719ARR 99CCR 50因此 PWM 频率 72M / (720 × 100) 1000Hz占空比 50 / 100 50%。2. 输入捕获IC原理输入捕获用于测量外部信号的频率或脉宽。当检测到引脚上的边沿上升沿或下降沿时定时器会记录当前计数器的值。通过两次相邻边沿捕获的计数值之差即可算出信号的周期进而得到频率。捕获到上升沿时记录计数值 CNT1下一次上升沿记录 CNT2信号周期 (CNT2 - CNT1) × 单个计数周期频率 1 / 周期。3. 定时器时钟配置STM32F103 的 TIM2 挂载在 APB1 总线上时钟频率为 72MHz。使用RCC_APB1PeriphClockCmd使能 TIM2 时钟使用RCC_APB2PeriphClockCmd使能 GPIOA 时钟。PWM 输出引脚 PA0 需配置为复用推挽输出GPIO_Mode_AF_PP。4. 频率计算公式本项目通过 PWM 输出 1000Hz 的方波再由输入捕获测量该频率实现自己发波、自己测频的闭环验证。频率计算公式为频率72M/((PSC1)×(ARR1))其中 PSC 和 ARR 均可通过pwm_setpsc和pwm_setcompare动态调整实现频率和占空比的实时修改。五、不足与改进1. 代码结构冗余当前IC.c中重复定义了pwm_init、pwm_setcompare、pwm_setpsc等 PWM 相关函数与pwm.c完全重复。这会导致编译时出现重复定义错误或在使用时产生混淆。改进建议将 PWM 相关函数统一放在pwm.c中IC.c只保留输入捕获相关的初始化与测量函数并在IC.c中通过#include pwm.h引用 PWM 功能。2. 输入捕获实现缺失当前代码只完成了 PWM 输出部分输入捕获IC的初始化函数IC_init和频率测量函数get_fre并未在IC.c中给出具体实现导致项目无法真正实现自己发波、自己测频的闭环验证。改进建议补充完整的输入捕获实现包括配置 TIM2 的通道 2PA1为输入捕获模式使能捕获中断在中断服务函数中记录相邻两次上升沿的计数值根据两次捕获的差值计算信号周期与频率将计算得到的频率值通过get_fre返回给主函数显示。3. 频率测量精度有限使用输入捕获测量频率时若被测信号频率较高单个计数周期对应的频率分辨率会下降若频率较低则测量周期变长实时性变差。当前设计在 1000Hz 附近表现尚可但扩展到更宽频率范围时精度不足。改进建议根据被测频率范围动态切换预分频系数保证计数分辨率采用多次测量取平均的方式降低随机误差对高频信号可改用测周法对低频信号可改用测频法结合两种策略提高精度。4. 缺少异常保护与边界处理代码中未对pwm_setpsc和pwm_setcompare的输入参数做范围校验。若传入过大的 PSC 或 CCR 值可能导致频率或占空比超出预期范围甚至产生异常波形。改进建议在函数入口处增加参数合法性检查例如限制 PSC 不超过 65535、CCR 不超过 ARR 值并对非法输入做默认值兜底处理。5. 显示刷新效率较低主循环中OLED_ShowNum每轮都刷新整个数字区域即使频率值未变化也会重复写入既占用 CPU 时间也可能造成 OLED 显示闪烁。改进建议在显示前先判断频率值是否发生变化只有变化时才刷新显示或使用局部刷新方式仅更新变化的数字位。
返回列表