今天我们来学习timer1的输入捕获应用——方波信号的频率和占空比测量
测量的原理也不复杂,但是要理解清除还是要花点时间。
基本原理就是从TI1输入方波信号,经过边沿选择器后分别送入IC1和IC2通道进行捕获。
IC1通道上升沿有效,在进行捕获的同时还触发timer的计数器复位。
IC2则是在下降沿时捕获。
如下图所示
IC1只捕获上升沿,并且捕获后就将计数器清零,两个上升沿之间的长度就是周期T。
IC2只捕获下降沿,IC1捕获后清零,计数器开始重新计数,到发生下降沿时IC2捕获。
IC2捕获的长度就是方波高电平的时间。
因此,IC1捕获周期,IC2捕获高电平。
周期和高电平都得到了,占空比和频率自然出来了。
原理很简单,但是实现方法还得看timer的结构
概括图可以看到,计数器的复位信号是由时钟、触发控制单元发出的。
看TI1的输入结构
TI1FP1有到时钟触发控制器的连接
下图显示了各输入通道的结构
TI1经过滤波分频和边沿选择后的信号可以有两个。
一个是TI1FP1,送入IC1通道,
一个是TI1FP2,送入IC2通道。
如果还不懂怎么配置,可以按照官方手册进行配置
按照步骤配置下来就好了。
由于我的输入信号比较高,125K。
主时钟8M,如果进入中断处理的话,每64个时钟必须进入一次中断。
显然64个时钟是不够用的。
因此我就想对输入信号进行分频。
但其实是没作用的。用于输入捕获的时钟是可以分频的,但是用于触发的时钟却不支持分频。
手册写有,输入捕获分频器不用于触发,不需要配置分频器。。。
没办法,只好用查询法处理了,进中断花费时间太多。
测试的时候发现波形的周期居然少了两个CPU周期。
64分频的方波信号,只记到62个脉冲。这不科学啊。
翻看手册的触发复位模式介绍。
这图就很清楚了。
TI1产生上升沿后经过1个时钟周期产生触发事件UG,
再过一个时钟周期后计数器复位为0.
这里就耽误了两个时钟周期。
再看看输入捕获
这里显示产生有效边沿后计数器的值马上被捕获锁存到比较捕获寄存器了。
基本没延时,这就造成了开始计数晚了两个周期,结束时能立即捕获,最终结果就是少了两个周期。
这儿也好办,直接加上2个时钟就完成了。
下面是测试
125K时钟信号,50%占空比
在线仿真监控
125K,50,没问题
使用USBee的PWM输出功能
这回没法看波形了,直接看结果吧
频率1464,接近1.5K。我也不知道输出信号是多少频率,没办法抓取,应该是准确的吧。
从结果看,起码占空比还是比较准确的。
贴上测试代码
- #include<iostm8s105k4.h>
- unsigned int T,D;
- unsigned long duty,freq;
- void init()
- {
- PC_DDR_DDR1=0; //PC timer1 TI1输入配置
- PC_CR1_C11=1;
- PC_CR2_C21=0;
-
- PD_DDR_DDR0=1; //PD0配置 时钟输出
- PD_CR1_C10=1;
- PD_CR2_C20=1;
-
- CLK_SWCR=0x02; //时钟切换
- CLK_SWR=0xb4;
- CLK_CKDIVR=0x00;
- CLK_CCOR=0x15; //时钟输出Fcpu/64 125Khz
-
- TIM1_CCMR1=0x01; //TI1FP1接到IC1
- TIM1_CCMR2=0x02; //TI1FP2接到IC2
- TIM1_SMCR=0x54; //从模式配置 上升沿复位
- TIM1_CR1=0x01; //开始计数
- TIM1_CCER1=0x31; //开捕获 IC1上升沿捕获,IC2下降沿捕获
-
- }
- int main( void )
- {
- init();
- while(1)
- {
- while(!(TIM1_SR1&0x02)); //等待IC1捕获
- TIM1_SR1=0x00; //清标志
- while(!(TIM1_SR1&0x02)); //再次捕获IC1,完成一个周期
- TIM1_CCER1=0x00; //关捕获
- T=TIM1_CCR1H<<8;
- T|=TIM1_CCR1L+2; //取值+2时钟周期补偿
- D=TIM1_CCR2H<<8;
- D|=TIM1_CCR2L+2;
- if(T>D) //计算周期、频率
- {
- duty=((unsigned long)D*10000)/T;
- freq=8000000/T;
- }
- TIM1_CCER1=0x31; //重开捕获
- }
- }
THE END!