基于STM32的相位差测量方法详解

         两路方波输入到stm32的两路定时器通道,通过检测高电平到来的时间差从而算出相位差,

公式  相位差=360*频率*(时间差)

        如果要测正弦波,可以通过电压比较电路转为方波

        

ddb1f5fd884b4a10b96a95a73d7f9ab1.png

定时器初始化及定时器中断代码:

void TIM5_Cap_Init(uint16_t arr,uint16_t psc)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStructure;
    TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period=arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
    TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

    
    TIM_ICInitTypeDef  TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel=TIM_Channel_4;
    TIM_ICInitStructure.TIM_ICFilter=0x00;
    TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM5,&TIM_ICInitStructure);
    
    TIM_ICInitStructure.TIM_Channel=TIM_Channel_3;
    TIM_ICInitStructure.TIM_ICFilter=0x00;
    TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM5,&TIM_ICInitStructure);
    
    NVIC_InitTypeDef  NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC4|TIM_IT_CC3,ENABLE);
    
    TIM_Cmd(TIM5,ENABLE);
}

u8  TIM5CH4_Cap_State; //第一路信号捕获标志
u16 TIM5CH4_Cap_Value; //第一路信号捕获值
u8  TIM5CH3_Cap_State; //第二路信号捕获标志
u16 TIM5CH3_Cap_Value; //第二路信号捕获值

void TIM5_IRQHandler()
{
    if((TIM5CH4_Cap_State&0x80)==0) //第一路信号未捕获到下降沿
    {
        if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET)
        {
            if(TIM5CH4_Cap_State&0x40) //第一路信号已捕获到上升沿
            {
                if((TIM5CH4_Cap_State&0x3f)==0x3f) //第一路信号上升沿到下降沿时间过长,捕获失败
                {
                    TIM5CH4_Cap_State|=0x80;       
                    TIM5CH4_Cap_Value=0xffff;
                }
                else TIM5CH4_Cap_State++;
            }
        }
        
        if(TIM_GetITStatus(TIM5,TIM_IT_CC4)==SET) //捕获中断
        {
            if(TIM5CH4_Cap_State&0x40) 		//第一路信号已经捕获到上升沿,则此次为下降沿被捕获
            {
                TIM5CH4_Cap_State|=0x80; 	//标志一次检测完成
                TIM5CH4_Cap_Value=TIM_GetCapture4(TIM5); //取出定时器的值
                TIM_OC4PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获
            }
            else //第一路未捕获到上升沿,则此次为上升沿被捕获
            {
                TIM5CH4_Cap_State=0;
                TIM5CH4_Cap_Value=0;
			    TIM_SetCounter(TIM5,0);
                TIM5CH4_Cap_State|=0X40; //标记捕获到上升沿
                TIM_OC4PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获
            }
        }
    }
    
    if((TIM5CH3_Cap_State&0x80)==0) 
    {
        if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET)
        {
            if(TIM5CH3_Cap_State&0x40) 
            {
                if((TIM5CH3_Cap_State&0x3f)==0x3f) 
                {
                    TIM5CH3_Cap_State|=0x80;       
                    TIM5CH3_Cap_Value=0xffff;
                }
                else TIM5CH3_Cap_State++;
            }
        }
        
        if(TIM_GetITStatus(TIM5,TIM_IT_CC3)==SET) 
        {
            if(TIM5CH3_Cap_State&0x40) 
            {
                TIM5CH3_Cap_State|=0x80; 
                TIM5CH3_Cap_Value=TIM_GetCapture3(TIM5); 
                TIM_OC3PolarityConfig(TIM5,TIM_ICPolarity_Rising); 
            }
            else 
            {
                TIM5CH3_Cap_State=0;
                TIM5CH3_Cap_Value=0;
			    TIM_SetCounter(TIM5,0);
                TIM5CH3_Cap_State|=0X40; 
                TIM_OC3PolarityConfig(TIM5,TIM_ICPolarity_Falling); 
            }
        }
    }
    
    TIM_ClearITPendingBit(TIM5,TIM_IT_Update|TIM_IT_CC4|TIM_IT_CC3);  
}

在主程序中求其中一路信号的频率,再使用开头给出的公式可求得相位差

下面给出关于求相位差部分的主程序代码:

		if((TIM5CH4_Cap_State&0x80) && (TIM5CH3_Cap_State&0x80))
		{
			timer4_temp=TIM5CH4_Cap_State&0x3f;
			timer4_temp*=65536;
			timer4_temp+=TIM5CH4_Cap_Value;
			
			timer3_temp=TIM5CH3_Cap_State&0x3f;
			timer3_temp*=65536;
			timer3_temp+=TIM5CH3_Cap_Value;
			
			if(timer4_temp > timer3_temp)
				time_diff = timer4_temp - timer3_temp;
			else
				time_diff = timer3_temp - timer4_temp;
			
			phase_diff = 360*F*time_diff/1000000;
			LCD_ShowNum(410,5+24*1,phase_diff,4,24);
			LCD_ShowString(410+4*12,5+24*1,12,24,24,".");
			LCD_ShowNum(410+5*12,5+24*1,(u16)(phase_diff*10)%10,1,24);
			
			TIM5CH4_Cap_State = 0;
			TIM5CH3_Cap_State = 0;
		}

物联沃分享整理
物联沃-IOTWORD物联网 » 基于STM32的相位差测量方法详解

发表评论