赞
踩
先放我们需要的辅助电路的电路图
假设我们要测量的是X信号和Y信号的初相位差,我们可以将两组信号分别表示为和。
很明显两组信号过零点的时间差乘以一个2就是相位差了。
为了方便测量我们先用一个过零比较器把信号变为方波
也就是我们只要测出红圈圈出的脉冲宽度即可得到时间差从而得到相位差。
我们可以先将红色的X信号取反再和蓝色的Y信号相与,得到如下信号:
现在我们只需要用单片机测量出红圈圈出的蓝色信号脉冲宽度即可得到时间差从而得到相位差。如下图所示,我们只需要找到这个超长低电平之前的高电平长度并输出即可。黑色箭头宽度为两个信号中低频信号的周期的一半,也就是说蓝色信号的两个上升沿之间的距离是大于低频信号的一个半周期的。
先按照下图配置好一个定时器。
这个定时器的作用是检测到上升沿的时候开始计数,计到第一个下降沿的时候将采样次数记作TIM4->CCR2,到下一个上升沿的时候将采样次数记作TIM4->CCR1。如果TIM4->CCR1的数值除以你的采样率后大于低频信号的半周期,就说明你找到需要的那个脉冲了,此时的TIM4->CCR2对应的就是这个脉冲的宽度。在代码中的表现如下图所示:
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
- {
- if (htim->Instance == TIM4)
- {
- if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
- {
- if(TIM4->CCR1>36000)//此处的数字取决于定时器采样频率和信号周期,36000为我这个信号半个周期对应的采样点数,用于判定我所需要的脉冲
- {
- capduty2 = (float)(TIM4->CCR2);//高电平时的采样点数,用点数除以采样率得到时间
- k++;
- if(k==1000)
- {
- printf("相位差=%d", (int)(capduty1*360*f/72000000)); //f为信号频率,72000000为我的采样率
- k=0;//防止刷新过快导致卡死,测满1000组输出一次
- }
- }
- }
- }
- }
当然别忘了先开启定时器
- /* USER CODE BEGIN 2 */
- HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1);
- HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2);
如果相位差是都是正的,那这篇文章写到这里差不多就可以结束了,但我们还要处理负的相位差。这次我们将蓝色的Y信号取反再和红色的X信号相与(可以参考文章最开始的那张图)。被圈出的蓝色脉冲的宽度就为负的相位差对应的时间(两者乘除频率可以互相转换)。好消息是黑色箭头的长低电平依然存在,我们只需要找到间隔相差超过一个低频信号半周期的两个下降沿就能找到我们需要测量的脉冲。
先配置另一个定时器,只有Channel1和Channel2对应的上升沿下降沿互换位置其他同上:
然后还是在begin2里开启输入捕获中断,但是在begin4里的代码需要略微改动
- if (htim->Instance == TIM4)
- {
- if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
- {
-
- if(TIM1->CCR1>36000)
- {
- capduty1 = (float)(TIM1->CCR1-TIM1->CCR2);
- j++;
- if(j==1000)
- {
- printf("相位差=-%d", (int)(capduty2*360*f/72000000));
- j=0;
- }
- }
-
-
-
- }
最后补充一点,如果我们不能提前知道相位差是正的还是负的怎么办呢?我们可以加一个功能,
if(capduty1*360*f/72000000>179)
printf("相位差=-%d", (int)(capduty2*360*f/72000000));
else
printf("相位差=%d", (int)(capduty1*360*f/72000000));
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。