完整的初始化代码
[cpp] view plain copyvoid signal_capture_Init(void)
{
TIM1_CNTRH = 0x00;//清零计数器高8位
TIM1_CNTRL = 0x00;//清零计数器低8位
TIM1_PSCRH = 0x00;//计数器时钟分频高8位
TIM1_PSCRL = 0x10;//计数器时钟分频低8位16分频
TIM1_CCER1 &= (unsigned char)~0x01;//清零TIM1_CCER1中的CC1E位,之后才可配置TIM1_CCMR1
TIM1_CCMR1 = 0x01;//配置TIM1_CCMR1中的CC1S位为1,CC1通道配置为输入,IC1映射到TI1FP1上
//无滤波器、无预分频器(捕获输入口上检测到的每一个边沿都触发一次捕获)
TIM1_CCER1 &= (unsigned char)~0x02;//上升沿或者高电平触发
TIM1_IER |= 0x02;//CC1IE=1,使能捕获/比较1中断
TIM1_CCER1 |= 0x01;//捕获使能
TIM1_CR1 |= 0x01;//使能定时/计数器
}
当发生一个输入捕获时,计数器的值被传送到TIM1_CCR1寄存器中,计时器的时钟源在程序中我们设置为16分频
分频过后计数器的频率为1MHz,这里采用分频主要是避免计数器溢出,这样同时也降低了精度,同时设置计数器的初值为0,计数器默认计数方式是向上计数,计到最大值后又从0开始计数,
中断处理代码如下
[cpp] view plain copy@far @interrupt void signal_capture_irq (void)
{
if(TIM1_SR1&0x02)
{
TIM1_SR1 &= (unsigned char)~0x02;//清除CC1IF标志
if(vsync_cap_data_old == 0x00)
{//第一次捕获中断来临
vsync_cap_data_old = TIM1_CCR1H;//先读取高8位数据
vsync_cap_data_old = (unsigned int)(vsync_cap_data_old《《8) + TIM1_CCR1L;//再读取低8位数据
}
else
{
//第二次捕获中断来临
vsync_cap_data_new = TIM1_CCR1H;//先读取高8位数据
vsync_cap_data_new = (unsigned int)(vsync_cap_data_new《《8) + TIM1_CCR1L;//再读取低8位数据
TIM1_IER &= (unsigned char)~0x02;//禁止通道1捕获/比较中断
TIM1_CR1 &= (unsigned char)~0x01;//停止计数器
if(vsync_cap_data_new 》 vsync_cap_data_old)
vsync_period = (vsync_cap_data_new - vsync_cap_data_old);
else
vsync_period = 0xFFFF + vsync_cap_data_new - vsync_cap_data_old;
vsync_cap_data_old = 0x00;
isCaptureOver = 1;
}
}
}
我们捕获两次中断计算时间差,
[cpp] view plain copyif(isCaptureOver)
{
//如果捕获完成则对数据进行处理
cmd_puts(“period:”);
cmd_hex((unsigned char)(vsync_period》》8));
cmd_hex((unsigned char)vsync_period);
TIM1_CNTRH = 0x00;//清零计数器高8位
TIM1_CNTRL = 0x00;//清零计数器低8位
TIM1_IER |= 0x02;//CC1IE=1,使能捕获/比较1中断
TIM1_CR1 |= 0x01;//使能定时/计数器
isCaptureOver = 0;
}
这里只从串口输出了周期,结果如下
可以看到周期在一个范围内波动我们取一个值0x79ED来计算,它所对应的频率f=1000000/0x79ED=32.0379Hz还是比较接近我们的实际输入频率30Hz,误差是大了些,可以通过代码继续改进
评论
查看更多