一、需求
使用STM32F407 测量外部输入方波信号的周期,信号变化范围:45HZ~55HZ,测量分辨率0.001HZ。
二、配置
- stm32Cubemx:version 6.1.1
- HAL库:1.25.2
- MDK:5.34
- C Compiler:ARMCC 6.16
三、分析
采用定时器的PWM输入捕获模式,读取定时器在两个信号脉冲上升沿之间计数值,即可。
50Hz测量分辨率为0.001Hz,即测量频率精确到小数点后三位,测量精度非常高,因此必须尽可能提高定时器的运行频率。此外,还要考虑定时器的位数,防止计数超过定时器的最大计数值。
参考STM32F407的技术手册,定时器TIM2~TIM5、TIM12~TIM14受限于APB1总线的最大时钟(42MHz),定时器TIM1、TIM8~TIM11受限于APB2总线的最大时钟(84MHz)。
送到Timer的时钟还会被系统二倍频,因此,TIM2~TIM5、TIM12~TIM14的最大时钟为84MHz,TIM1、TIM8~TIM11的最大时钟为168MHz。
还需要考虑计数值的最大计数范围,例如在最大时钟168MHz运行时,到50HZ的计数值应该为168M/50 = 3360000,这远超过16位计数器的65535。因此,需要折中考虑。
经过分析,32位定时器TIM5,运行在84MHZ时,是比较满足要求的,50HZ此时的计数值为84M/50 = 1680000, 32位计数器能hold住。
四、cubeMx配置
4.1 时钟设置
TIM5挂在APB1上,保证APB1最大速度42MHz,可得到APB1的Timer时钟84MHz。
4.2 TIM设置
选择TIM5,使用PWM 的通道1输入:
定时器的预分频系数PSC设置为0,即不分频。PWM设置为TI1FP1上升沿触发,SlaveModeController设置ResetMode,即捕获到上升沿就重置计数。InputFilter用于设置输入滤波,当识别到多少个电平信息后认为是稳定的边沿到达。
然后开启全局中断
设置CH1的GPIO为下拉,以保证稳定外部触发。
其他配置包括串口UART之类的,正常配置即可。保存,生成工程代码。
五、计算频率
- 在MDK工程中,使用 HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1),启用定时器的PWM捕获功能。
- 在void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) 中断函数中获取定时器的计数值,并计算出频率。
- 使用HAL_TIM_ReadCapturedValue读取计数值。
main.c代码如下:
中断处理函数如下:
主函数main.c中每500ms打印一次频率测量值。
信号发生器输出频率50Hz,实际测得的值为49.99672699HZ,一直很稳定,小数点后4位不变化,说明精度可以保证到0.0001Hz,固定误差是0.004Hz,在输出结果时进行误差补偿即可,这部分误差有可能是信号发生器本身或者连接线的问题,是可以满足测量任务的。