利用stm32测量两路正弦波相位差,有四种主要思路:
1. 两路直接捕获信号直接得到时间差
即将正弦波过比较器变成方波(stm32直接测量正弦波也可以的,频率较大时误差基本上在忍受范围的),开启两路捕获得到上升沿的时间差,即可得到其相位差,但如果系统中信号噪声较大,此方法就很难测准。
辅助比较器威廉希尔官方网站
:
(input0为比较值,这里是过零比较,接地就好了)
stm32代码:
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=0XFFFFFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}//这是溢出处理,要是采集的信号频率较高,则可以不用这一段代码。
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}else
{
TIM2CH1_CAPTURE_STA=0;
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA|=0X40;
TIM_Cmd(TIM2,DISABLE );
TIM_SetCounter(TIM2,0);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
TIM_Cmd(TIM2,ENABLE );
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update);
}
2. 两路信号过或非门转换成占空比测量
即将正弦波过比较器变成方波,过或非门得到占空比,使得测量相位差变成测量占空比,这里选用的或非门为SN74HC7002,由于这个或非门具有施密特触发器,使得系统抗噪性得到提高。
威廉希尔官方网站
图:
威廉希尔官方网站
图做了信号的隔直处理,去处理信号的直流分量。
STM32代码如下:
TIM_ICInitTypeDef TIM2_ICInitStructure;
void TIM2_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0口为信号接入口
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM2_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM2, &TIM2_ICInitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM2,ENABLE );
}
u8 TIM2CH1_CAPTURE_STA=0;
u16 TIM2CH1_CAPTURE_VAL1;
u16 TIM2CH1_CAPTURE_VAL2;
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
if((TIM2CH1_CAPTURE_STA&0X40))
{
TIM2CH1_CAPTURE_STA|=0X80; //捕捉到下降沿,停止计时,即一个周期的时间
TIM2CH1_CAPTURE_VAL2=TIM_GetCapture1(TIM2);
}
else if((TIM2CH1_CAPTURE_STA&0X20))
{
TIM2CH1_CAPTURE_STA|=0X40; //捕捉到第二个上升沿,记录时间,即高电平时间
TIM2CH1_CAPTURE_VAL1=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
}
else
{
TIM2CH1_CAPTURE_STA=0;
TIM2CH1_CAPTURE_VAL1=0;
TIM2CH1_CAPTURE_VAL2=0;
TIM_SetCounter(TIM2,0);
TIM2CH1_CAPTURE_STA|=0X20;
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update);
}
占空比即为 (TIM2CH1_CAPTURE_VAL1 / TIM2CH1_CAPTURE_VAL2)
相位差就是占空比乘以180,即为(TIM2CH1_CAPTURE_VAL1 / TIM2CH1_CAPTURE_VAL2)*180
主程序代码:
extern u8 TIM2CH1_CAPTURE_STA;
extern u16 TIM2CH1_CAPTURE_VAL1;
extern u16 TIM2CH1_CAPTURE_VAL2;
int main(void)
{
u16 temp1,temp2,phase_difference;
if(TIM2CH1_CAPTURE_STA&0X80)
{
{
temp1=TIM2CH1_CAPTURE_VAL1;
temp2=TIM2CH1_CAPTURE_VAL2;
phase_difference = temp1/temp2*180;
TIM2CH1_CAPTURE_STA=0;
}
}
}
3. 利用求相关来测量相位差
求相关测相位差在噪声严重的情况下误差还是蛮大的,这里就简单的讲一下,这是利用了互相关函数的两同频正弦信号的互相关函数零时刻值与其相位差的余弦值成正比的原理获得相位差。
具体公式:
matlab仿真代码(由仿真即可看出噪声影响对结果影响较大)
SNR = 10 ^( 0.1 * k); %信噪比的公式:10*lg(PS/PN)
N0 = 1/SNR; %N0为噪声
Sigma = sqrt(N0/2);
t=0:0.00002:0.01; %采样信号50kHz,持续时间10ms
f=0.002; %被采样信号500Hz
num=1/f; %num是周期
w=pi/4;
x1=sin(2*pi*num*t); %产生信号x1
y1=sin(2*pi*num*t+w); %产生信号x2
n1=Sigma.*randn(1,num+1); %n1是噪声
y2=y1+n1; %给y1信号加噪
Ix=sum(x1.^2)/num;
Iy=sum(y2.^2)/num;
Ixy=sum(x1.*y2)/num;
c=180*acos(2*Ixy/sqrt(4*Ix*Iy))/pi;
利用stm32测量两路正弦波相位差,有四种主要思路:
1. 两路直接捕获信号直接得到时间差
即将正弦波过比较器变成方波(stm32直接测量正弦波也可以的,频率较大时误差基本上在忍受范围的),开启两路捕获得到上升沿的时间差,即可得到其相位差,但如果系统中信号噪声较大,此方法就很难测准。
辅助比较器威廉希尔官方网站
:
(input0为比较值,这里是过零比较,接地就好了)
stm32代码:
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=0XFFFFFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}//这是溢出处理,要是采集的信号频率较高,则可以不用这一段代码。
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}else
{
TIM2CH1_CAPTURE_STA=0;
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA|=0X40;
TIM_Cmd(TIM2,DISABLE );
TIM_SetCounter(TIM2,0);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
TIM_Cmd(TIM2,ENABLE );
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update);
}
2. 两路信号过或非门转换成占空比测量
即将正弦波过比较器变成方波,过或非门得到占空比,使得测量相位差变成测量占空比,这里选用的或非门为SN74HC7002,由于这个或非门具有施密特触发器,使得系统抗噪性得到提高。
威廉希尔官方网站
图:
威廉希尔官方网站
图做了信号的隔直处理,去处理信号的直流分量。
STM32代码如下:
TIM_ICInitTypeDef TIM2_ICInitStructure;
void TIM2_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0口为信号接入口
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM2_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM2, &TIM2_ICInitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM2,ENABLE );
}
u8 TIM2CH1_CAPTURE_STA=0;
u16 TIM2CH1_CAPTURE_VAL1;
u16 TIM2CH1_CAPTURE_VAL2;
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
if((TIM2CH1_CAPTURE_STA&0X40))
{
TIM2CH1_CAPTURE_STA|=0X80; //捕捉到下降沿,停止计时,即一个周期的时间
TIM2CH1_CAPTURE_VAL2=TIM_GetCapture1(TIM2);
}
else if((TIM2CH1_CAPTURE_STA&0X20))
{
TIM2CH1_CAPTURE_STA|=0X40; //捕捉到第二个上升沿,记录时间,即高电平时间
TIM2CH1_CAPTURE_VAL1=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
}
else
{
TIM2CH1_CAPTURE_STA=0;
TIM2CH1_CAPTURE_VAL1=0;
TIM2CH1_CAPTURE_VAL2=0;
TIM_SetCounter(TIM2,0);
TIM2CH1_CAPTURE_STA|=0X20;
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update);
}
占空比即为 (TIM2CH1_CAPTURE_VAL1 / TIM2CH1_CAPTURE_VAL2)
相位差就是占空比乘以180,即为(TIM2CH1_CAPTURE_VAL1 / TIM2CH1_CAPTURE_VAL2)*180
主程序代码:
extern u8 TIM2CH1_CAPTURE_STA;
extern u16 TIM2CH1_CAPTURE_VAL1;
extern u16 TIM2CH1_CAPTURE_VAL2;
int main(void)
{
u16 temp1,temp2,phase_difference;
if(TIM2CH1_CAPTURE_STA&0X80)
{
{
temp1=TIM2CH1_CAPTURE_VAL1;
temp2=TIM2CH1_CAPTURE_VAL2;
phase_difference = temp1/temp2*180;
TIM2CH1_CAPTURE_STA=0;
}
}
}
3. 利用求相关来测量相位差
求相关测相位差在噪声严重的情况下误差还是蛮大的,这里就简单的讲一下,这是利用了互相关函数的两同频正弦信号的互相关函数零时刻值与其相位差的余弦值成正比的原理获得相位差。
具体公式:
matlab仿真代码(由仿真即可看出噪声影响对结果影响较大)
SNR = 10 ^( 0.1 * k); %信噪比的公式:10*lg(PS/PN)
N0 = 1/SNR; %N0为噪声
Sigma = sqrt(N0/2);
t=0:0.00002:0.01; %采样信号50kHz,持续时间10ms
f=0.002; %被采样信号500Hz
num=1/f; %num是周期
w=pi/4;
x1=sin(2*pi*num*t); %产生信号x1
y1=sin(2*pi*num*t+w); %产生信号x2
n1=Sigma.*randn(1,num+1); %n1是噪声
y2=y1+n1; %给y1信号加噪
Ix=sum(x1.^2)/num;
Iy=sum(y2.^2)/num;
Ixy=sum(x1.*y2)/num;
c=180*acos(2*Ixy/sqrt(4*Ix*Iy))/pi;
举报