PIC极限应用

2020-02-09 09:30发布

在一个小项目里面,用PIC16F913来主控,用来记录N个脉冲的时间,时间精确到10us,看了下资料,晶振可以最高20M     20M/4分频可以到5M。但是看了下第定时器的中断,软件模拟了下,进中断和出中断就要3.XX个US,如果加上脉冲捕获进中断的时间,一起的误差会不会超出10US的范畴???(思路是:一边捕获脉冲。一边开个5US的定时器片,一直累加。当脉冲捕获到N值时,关定时器。看定时了多少个5US)  刚接错PIC,不知道这样可行不?高手路过,喵喵。。。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
25条回答
adszmc
1楼-- · 2020-02-11 11:10
回复【12楼】su_mj000
如果脉冲频率很慢,可以借助软件定时,即开启定时器溢出中断,中断时软件计数加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)
这样的方案是否可行? 感觉这样操作容易点,也容易控制精度。
adszmc
2楼-- · 2020-02-11 14:30
自己顶下。。。。。 等待高手路过
jack_yu
3楼-- · 2020-02-11 16:14
 精彩回答 2  元偷偷看……
millwood0
4楼-- · 2020-02-11 20:48
"自己顶下。。。。。 等待高手路过"

did you see TMR1GE in that chart?

read about it in the datasheet.
millwood0
5楼-- · 2020-02-11 22:19
here is an example of how you would execute it.

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.
millwood0
6楼-- · 2020-02-12 01:34
here is (roughly) the same code running on a C51 counting a 10Khz pulse train.

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
        }
}

一周热门 更多>