官方的例程
/**
\brief configure the GPIO ports
\param[in] none
\param[out] none
\retval none
*/
void gpio_configuration(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
/*configure PA6 (TIMER2 CH0) as alternate function*/
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
}
/**
\brief configure the nested vectored interrupt controller
\param[in] none
\param[out] none
\retval none
*/
void nvic_configuration(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(TIMER2_IRQn, 1, 1);
}
/**
\brief configure the TIMER peripheral
\param[in] none
\param[out] none
\retval none
*/
void timer_configuration(void)
{
/* TIMER2 configuration: input capture mode -------------------
the external signal is connected to TIMER2 CH0 pin (PA6)
the rising edge is used as active edge
the TIMER2 CH0CV is used to compute the frequency value
------------------------------------------------------------ */
timer_ic_parameter_struct timer_icinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
timer_deinit(TIMER2);
/* TIMER2 configuration */
timer_initpara.prescaler = 107;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 65535;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
/* TIMER2 configuration */
/* TIMER2 CH0 input capture configuration */
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; //上升沿触发
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0x0;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER2);
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
/* channel 0 interrupt enable */
timer_interrupt_enable(TIMER2,TIMER_INT_CH0);
/* TIMER2 counter enable */
timer_enable(TIMER2);
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
gpio_configuration();
gd_eval_com_init(EVAL_COM1);
nvic_configuration();
timer_configuration();
while (1);
}
/**
* @brief This function handles TIMER2 interrupt request.
* @param None
* @retval None
*/
void TIMER2_IRQHandler(void)
{
if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH0)){
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
if(0 == ccnumber){
/* read channel 0 capture value */
readvalue1 = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0);
ccnumber = 1;
}else if(1 == ccnumber){
/* read channel 0 capture value */
readvalue2 = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0);
if(readvalue2 > readvalue1){
count = (readvalue2 - readvalue1);
}else{
count = ((0xFFFF - readvalue1) + readvalue2);
}
fre = (float)1000000 / count;
printf("the value1 is %d,the value2 is %d\n",readvalue1,readvalue2);
printf("the count is %d\n",count);
printf("the frequence is %f\n",fre);
ccnumber = 0;
}
}
}
自己修改使用的
void ACSig_In_Capture_Init(void) //TIM2_CH0 AC_SIG-PB4
{
timer_ic_parameter_struct timer_icinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_AF);
//重映射
gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE);
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(TIMER2_IRQn, 1, 1);
/* TIMER2 configuration: input capture mode -------------------
the external signal is connected to TIMER2 CH0 pin (PB4)
the rising edge is used as active edge
the TIMER2 CH0CV is used to compute the frequency value
------------------------------------------------------------ */
timer_deinit(TIMER2);
/* TIMER2 configuration */
timer_initpara.prescaler = 215;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 65535;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
/* TIMER2 configuration */
/* TIMER2 CH0 input capture configuration */
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING; //下降沿
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0x4; //使能滤波功能
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER2);
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
/* channel 0 interrupt enable */
timer_interrupt_enable(TIMER2,TIMER_INT_CH0);
/* TIMER2 counter enable */
timer_enable(TIMER2);
}
可以看到上面的例程使能了滤波功能,下面对滤波功能做一下介绍,并说明为什么要用。
输入捕获1滤波器CH0CAPFLT[3:0], 这个用来设置输入采样频率和数字滤波器长度。 其中,fPCLK是定时器的输入频率(TIMxCLK) ,一般为 108Mhz,而 fDTS则是根据 TIMERx_CTL0 的 CKDIV[1:0]的设置来确定的,如果 CKD[1:0]设置为 00,那么fDTS=fTIMER_CK=fPCLK。
N 值就是滤波长度,举个简单的例子:假设 CH0CAPFLT[3:0]=0011,并设置 IC1 映射到通道 1 上,且为上升沿触发,那么在捕获到上升沿的时候,再以fPCLK的频率,连续采样到 8 次通道 1 的电平,如果都是高电平,则说明确实是一个有效的触发,就会触发输入捕获中断(如果开启了的话) 。这样可以滤除那些高电平脉宽低于 8 个采样周期的脉冲信号,从而达到滤波的效果。
此处我是用来采集下降沿信号,但是信号下降的比较慢。当我把滤波关掉,情况如下图,蓝色是采集信号,黄色是测试信号,进一次触发中断就翻转一次黄色信号的电平。可以看到因为蓝色信号下降太慢,在临界处触发了多次中断。
当我把滤波打开后,定时器就会采集多次才会触发,这样就可以解决信号边沿慢的问题了。