ARTICLE DETAIL

资讯详情

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

用STM32测量PWM频率:输入捕获、PWM输入、外部时钟三种方案详解

用STM32测量PWM频率:输入捕获、PWM输入、外部时钟三种方案详解 简介面向STM32F407开发者的PWM波频率测量工程实例基于标准外设库实现定时器输入捕获、中断计数与频率换算适合嵌入式入门及电机转速、信号检测类项目参考。压缩包共160个文件以C语言与头文件源码为主46个h、45个c另含Keil工程配置、编译输出axf/hex、PDF说明及调试辅助文件整体体积仅5.19MB。已有1825人学习/下载。工程可直接导入Keil编译烧写覆盖定时器输入捕获、外部事件计数、滤波与溢出处理等核心环节同时附带LCD显示、ADC采集、Flash读写等外设驱动便于在现有框架上二次开发。通过对照源码和说明文档读者可快速掌握STM32F407测量PWM频率的配置流程并迁移至其他定时器或更高频率信号场景。1. 测PWM频率这个需求到底卡在哪很多人在拿到一个未知PWM信号时第一反应是用示波器看波形。但在产线自检、设备维护和传感器读取场景里示波器出场并不方便你手里往往只有一块STM32开发板。这个标题的需求非常直白给一路PWM信号用STM32量出它的频率精度要能判断一个电机是转在30Hz还是60Hz或者一块舵机的控制信号是不是标准的50Hz。难点从来不是读寄存器而是把定时器的输入捕获用对、把溢出和毛刺处理干净、把中断优先级排好否则测出来的频率要么跳得没法看要么干脆在某个量程上完全错误。本文以STM32F4为主线把三种测频方案的取舍、最小可跑配置和参数调优一次讲透。2. 三种测频方案怎么选输入捕获、PWM输入模式还是外部时钟2.1 测频法、测周法的本质差别先从误差模型说起PWM频率测量从数学上只有两条路闸门计数和周期计时。闸门计数M法在固定时间窗口内数脉冲个数频率等于计数除以闸门时间周期计时T法测量相邻两个上升沿的时间间隔频率等于1除以时间差。两者的误差模型完全不同。M法误差是±1个脉冲低频信号在短闸门内会非常不准100Hz信号用100ms闸门只能数到10个脉冲误差±10%。T法误差是±1个计数节拍只要定时器时钟足够高低频反而测得更准因为周期越长、计数值越大、相对误差越小。PWM信号测量绝大多数场景走的是T法变体捕获上升沿并记录定时器计数两次捕获值的差就是周期。工程上的分歧点在于“周期”是只测一个脉冲还是测多个脉冲再做平均这正是下面三种硬件方案的分水岭。2.2 输入捕获、PWM输入模式、外部时钟模式的横向对比方案一输入捕获。定时器任选一个通道配置边沿捕获边沿到达时硬件把当前计数写入CCR寄存器。两次捕获值相减得到周期。优点是灵活、顺手能测占空比、代码直观缺点是每次边沿都产生中断信号频率很高时CPU开销大。方案二PWM输入模式。这是STM32从模式与主模式联动的一种经典组合把两个通道配置成一个测周期、一个测占空比由硬件自动完成同步。优点是占空比和周期同时得到、不需要软件协调两个通道缺点是配置绕、占住了两个相邻通道中途换通道会让你调试时怀疑人生。方案三外部时钟模式1。把PWM信号直接接到定时器的外部时钟引脚如TIM2的ETR引脚信号边沿直接驱动计数器加一另用一个高频时基去定时读取计数器做差分。优点是中断少、CPU占用极低适合几百kHz以上的高频信号缺点是测的是“累计脉冲数”要瞬时频率就得频繁读占空比完全测不了。三个方案整理成一张选型表维度输入捕获PWM输入模式外部时钟模式1硬件开销1个捕获通道2个相邻通道1个ETR引脚频率占空比需双通道分两次配置硬件自动同步获取只能测频率中断压力每个边沿触发每个完整周期触发按读取间隔触发最小可测频率受定时器位数和溢出处理限制同左且要求信号占空比可用计数器溢出前不丢代码调试难度低中低典型场景100Hz~100kHz通用测频舵机/电机调速同时要占空比MHz级高频计数2.3 为什么通用场合我优先选输入捕获选型逻辑可以分三步。第一步看频率量程几十Hz到几十kHz的PWM用T法输入捕获最合适定时器分频后到1MHz甚至更高测量分辨率完全够用。第二步看CPU余量如果信号是几百kHz甚至MHz级每个边沿都进中断实际会拖垮主线逻辑这时改成外部时钟模式加定时轮询更合理。第三步看是否要同时拿占空比电机调速和舵机控制经常两个都要直接上PWM输入模式。多数入门项目、毕业设计和产线自检工具面对的PWM信号来自另一个MCU、信号发生器或传感器频率范围基本落在100Hz到100kHz之间输入捕获是最不容易出错的方案。后面的配置和代码都按输入捕获展开第5章会补另外两种方案的配置要点。3. 在STM32F4上把输入捕获配到能跑时钟树、初始化、中断回调3.1 先核对定时器时钟这步错了后面全错STM32F407的TIM2和TIM5挂在APB1上APB1最大42MHz但定时器时钟会再乘2所以TIM2/TIM5的输入时钟是84MHz。F429、F405同属F4系列也是这个关系。很多例程把预分频写成84-1默认计数频率是1MHz前提就是定时器时钟确实是84MHz——如果SystemClock_Config里改了AHB预分频APB1分频结果可能不是42MHz定时器时钟跟着变这时同样代码测出的频率会有系统性偏差。我一般会在初始化里打印或单步看一眼HAL_RCC_GetPCLK1Freq()返回的实际值再反推定时器时钟避免换了一块板子就翻车。3.2 HAL库最小配置TIM2_CH1捕获PA0上的PWM下面的代码在STM32F407VET6开发板、HAL库环境下跑通也适配F429等F4系列只需按开发板原理图改引脚。/* 输入捕获初始化TIM2_CH1PA0计数频率 1MHz */ static void PWM_Freq_Init(void) { GPIO_InitTypeDef gpio {0}; __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /* PA0 复用为 TIM2_CH1输入引脚不需要上下拉 */ gpio.Pin GPIO_PIN_0; gpio.Mode GPIO_MODE_AF_PP; gpio.Pull GPIO_NOPULL; gpio.Speed GPIO_SPEED_FREQ_HIGH; gpio.Alternate GPIO_AF1_TIM2; HAL_GPIO_Init(GPIOA, gpio); /* 基地址84MHz 分频到 1MHz计数器每 1us 跳一次 */ htim2.Instance TIM2; htim2.Init.Prescaler 84 - 1; /* 计数频率 84MHz / 84 1MHz */ htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 0xFFFFFFFF; /* 32位计数器最大值不主动溢出 */ htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_IC_Init(htim2); /* 捕获配置上升沿触发直接捕获通道无分频开滤波 */ TIM_IC_InitTypeDef ic {0}; ic.ICPolarity TIM_INPUTCHANNELPOLARITY_RISING; ic.ICSelection TIM_ICSELECTION_DIRECTTI; ic.ICPrescaler TIM_ICPSC_DIV1; ic.ICFilter 0x0F; HAL_TIM_IC_ConfigChannel(htim2, ic, TIM_CHANNEL_1); /* 开启捕获中断并启动定时器 */ HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1); }这段代码里三个参数需要重点说明。Prescaler 84 - 1让计数器每1微秒加1这样CCR寄存器两次捕获值的差就直接代表微秒数从本文还有配套的精品资源点击获取
返回列表