频率测量可以用测周法和测频法:
1.测周法:通过一个方波的两个上升沿或下降沿触发中断,然后定时器计数,计数的总个数乘以计数单位时间即该方波的周期。实际程序如下:
void TIM3_Encoder_IN_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//时钟配置
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler=psc; 100kHz,10us//56M//24M
//TIM时钟频率
//TIM_TimeBaseStructure.TIM_Period //ENCODER_TIM_PERIOD=(u16)(65000)
= ENCODER_TIM_PERIOD-1;
TIM_TimeBaseStructure.TIM_Period=arr; //测频范围在1.6Hz到100kHz
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式向上
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//定时器初始化
//通道1
TIM_ICInitStructure.TIM_Channel =TIM_Channel_1; //通道选择
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿触发
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //管脚与寄存器对应关系
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入预分频。意思是控制在多少个输入周期做一次捕获,如果
//输入的信号频率没有变,测得的周期也不会变。比如选择4分频,则每四个输入周期才做一次捕获,这样在输入信号变化不频繁的情况下,
//可以减少软件被不断中断的次数。
TIM_ICInitStructure.TIM_ICFilter = 0x0; 置,经历几个周期跳变认定波形稳定0x0~0xF
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//通道2
TIM_ICInitStructure.TIM_Channel =TIM_Channel_2; 选择
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; 发
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 存器对应关系
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; 频。意思是控制在多少个输入周期做一次捕获,如果
//滤波设 //通道//上升沿触//管脚与寄//输入预分
//输入的信号频率没有变,测得的周期也不会变。比如选择4分频,则每四个输入周期才做一次捕获,这样在输入信号变化不频繁的情况下,
//可以减少软件被不断中断的次数。
TIM_ICInitStructure.TIM_ICFilter = 0x0; //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF
TIM_ICInit(TIM3, &TIM_ICInitStructure);
NVIC_InitStructure.NVIC_IRQChannel = //NVIC配置
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //打开中断
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE); //打开中断
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
TIM3_IRQn;
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
TIM_Cmd(TIM3, ENABLE); //定时器使能
}
void TIM3_IRQHandler(void)
{//PWM_IN2通道采集
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
count1++;
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)//TIM3CH2
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);//清除中断标志
if(capture1_loop==0)
{TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);
Ic1readvalue1=TIM_GetCapture1(TIM3);//得到第一次计数值
capture1_loop=1;}
else{
if(capture1_loop==1)
{Ic1readvalue2=TIM_GetCapture1(TIM3);
TIM_ITConfig(TIM3, TIM_IT_Update,DISABLE);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
ch1freq=100000/(65536*count1+Ic1readvalue2-Ic1readvalue1);
capture1_loop=0;
count1=0;
}
usRegInputBuf[17]=ch1freq;//PWM_IN2通道采集
}
}
实际测试结果是频率在600-1000HZ时,有其他的非频率数据,不准确。这里采用了定时器溢出中断来计算65535溢出的次数。
另外,还可以不采用溢出中断,直接比较计数值的大小来实现,程序如下:
void TIM3_IRQHandler(void)
{//PWM_IN2通道采集
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)//TIM3CH2
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);//清除中断标志
if(capture1_loop==0)
{Ic1readvalue1=TIM_GetCapture1(TIM3);//得到第一次计数值
capture1_loop=1;}
else{
if(capture1_loop==1)
{Ic1readvalue2=TIM_GetCapture1(TIM3);
if(Ic1readvalue2>Ic1readvalue1)
{Capture1=(Ic1readvalue2-Ic1readvalue1);}
else{Capture1=((0XFFFF-Ic1readvalue1)+Ic1readvalue2);}
ch1freq=1000000/Capture1;//861HZ-21000HZ
capture1_loop=0;
}
usRegInputBuf[17]=ch1freq;//PWM_IN2通道采集
}
}
测试结果是频率在频率100-800HZ,有其他的非频率数据,不准确。
2.测频法:通过定时器定时1S,计算方波上升沿或者下降沿的个数,频率数据较准确,特别是高频信号测量准确,程序代码简单,程序如下:
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) //定时器1S溢出
{TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除溢出标志位
usRegInputBuf[17]=count1; //PWM_IN2通道采集
usRegInputBuf[16]=count2; //PWM_IN1通道采集
count1=0;
count2=0;
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)//TIM3CH2
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);//清除中断标志
count1++;
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)//TIM3CH1
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);//清除中断标志
count2++;
}
}