在一个小项目里面,用PIC16F913来主控,用来记录N个脉冲的时间,时间精确到10us,看了下资料,晶振可以最高20M 20M/4分频可以到5M。但是看了下第定时器的中断,软件模拟了下,进中断和出中断就要3.XX个US,如果加上脉冲捕获进中断的时间,一起的误差会不会超出10US的范畴???(思路是:一边捕获脉冲。一边开个5US的定时器片,一直累加。当脉冲捕获到N值时,关定时器。看定时了多少个5US) 刚接错PIC,不知道这样可行不?高手路过,喵喵。。。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
如果脉冲频率很慢,可以借助软件定时,即开启定时器溢出中断,中断时软件计数加1.
定时器应该设置成循环方式。
这样一来,中断源增加到2个。pic16只有一个中断入口,所以中断时应先查计数,后查
定时。中断延时误差是个常数,可以用软件修正。
-----------------------------------------------------------------------
谢谢su_mj000 的关注,
看了下pic16f914的技术手册:
设计方案为: 将timer1的设置为外部计数模式。将脉冲信号从TICKI引脚输入,TMR1寄存器记录。使用PIC内部资源的捕捉 / 比较 /PWM (CCP)模块中的比较模式, 用16位CCPRx寄存器值与TMR1寄存器的值进行比较。 当发生匹配时,CCPx模块可产生软件中断。比如说我需要设置1000个脉冲计时,置CCPRx为1000的值,同时清TMR1寄存器值。当来一个脉冲的话。TMR1寄存器值+1,一旦与CCPRx发生匹配时,产生软件中断,中断里面设置为关定时器。
(原文件名:2.JPG)
定时器使用Timer0 模块的8位定时器 :每定时一个周期(00~FF)加一,(加一在定时中断里面做)当捕获模块发生匹配中断时,关定时器,同时读TTimer0模块寄存器值,通过系统时钟可以换算出时间为: (256*N+ TTimer0模块寄存器值)*FOSC/4 其中N为加一次数。如果需要更高精度,可以补偿进定时器进中断处理的时间【(N*进中断到出中断的时间)+捕获匹配进中断和出中断时间】。
(原文件名:3.JPG)
这样的方案是否可行? 感觉这样操作容易点,也容易控制精度。
did you see TMR1GE in that chart?
read about it in the datasheet.
the mcu in question is running on 4Mhz internal RC (1us timer clicks). it is measuring the pulse width of a 100Khz pulse train (5us pulse width) and storing the number of internal clock ticks during the time T1G has gone low into count.
in this case, count = 5 is the right answer.
because of phase differences between the incoming pulse and the clock, you may have 1 or up to 2 ticks' errors. so to be very accurate, you have to increase the internal clock speed.
the limitation here is the length of the pulse. as tmr1 is a 16-bit timer, the max pulse length is 64K clock ticks. you can solve that by having an interrupt on tmr1 overflow and use a software counter to make the timer a 48-bit timer (16-bit hardware timer + 32-bit software timer).
(原文件名:12F675 Gated TMR1.PNG)
the same concept can also be easily implemented on any mcu with a gated timer, like the 8051.
the output is on P2 and as you can see, it is 0x32 = 50 ticks -> 50us for the pulse width - the correct answer.
the only difference here is that the gate on a 12F675 is active low and the gate on the 8051 is active high.
(原文件名:C51 Gated TMR0.PNG)
========code==============
#include <regx51.h>
#include "gpio.h"
//__CONFIG(MCLRDIS & BORDIS & WDTDIS & PWRTEN & INTIO);
#define IN_PORT P3
#define IN_DDR P3
#define IN_GATE (1<<2) //pulse gate on int0=p3.2
#define OUT_PORT P2
#define OUT_DDR P2
#define OUT_PINs 0xff //all pins on p2 are output
void mcu_init(void) { //initiate the mcu
//ANSEL=0x00; //all pins digital
//CMCON=0x07; //analog comparators off
IO_IN(IN_DDR, IN_GATE); //in_gate as input
IO_OUT(OUT_DDR, OUT_PINs); //out_pins as output
}
void tmr0_init(void) { //initiate the tmr1
//TMR1GE=1; //enable tmr1 gate control - tmr1 starts counting if t1g is low
//T1CKPS1=0, T1CKPS1=0; //tmr1 prescaler 1:1
//TMR1CS=0; //tmr1 source is internal clock
TMOD &=0xf0; //reset tmod0..3
TMOD |=0x09; //tmr0 =gated timer, and in mode 1 (16-bit timer)
//TMR1ON=0; //tmr0 off
TR0=0;
}
void
main(void)
{
unsigned short count=0;
mcu_init(); //initiate the mcu
tmr0_init(); //initiate the tmr1
while (1){
//TODO Auto-generated main function
while (IO_GET(IN_PORT, IN_GATE)); //wait for in_gate to go low
//now in_gate is low
TH0=0, TL0=0; //reset tmr0 counters
//TMR1ON=1; //turn on tmr1
TR0=1;
while (!IO_GET(IN_PORT, IN_GATE)); //wait for IN_gate to go high
//in_gate is high -> counting starts high
while (IO_GET(IN_PORT, IN_GATE)); //wait for in_gate to go low
//TMR1ON=0; //turn off tmr1
TR0=0;
count=(TH0<<8) | TL0; //count contains tmr1h:tmr1l
IO_CLR(OUT_PORT, OUT_PINs); //clear output pins
IO_SET(OUT_PORT, count); //output
}
}
一周热门 更多>