使用中断标志的脉冲宽度

pulse width using interruption flag

我想在捕获模式下使用 pic 18f4550 CCP 测量脉冲宽度。 这个想法是: 当CCP模型接收到上升沿时,timer1启动,Timer1每次中断后,初始值为0的常数x加1,当CCP模型接收到下降沿时,timer1停止并增加x 也必须停止,以便其值可用于计算脉冲。 我发现的问题是 x 的增加不会停止并且代码像计数器一样工作 由于我是图片编程的新手,所以我找不到错误。 如果有人可以提供帮助,我将不胜感激。 我正在使用的代码如下。 谢谢!

#include <stdio.h>
#include <stdlib.h>

#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>

int x=0;

void main()
{
    unsigned long comtage;
    unsigned long DEPHASAGE[20];
    float Deph_tempo;
    
    TRISCbits.TRISC2=1;
    
    IRCF0=1;     
    IRCF1=1;
    IRCF2=1;  
    
    LCD_Init();
    
    LCD_String_xy(0,0,"pulse"); 
 
    PIE1bits.CCP1IE=1;
    PIR1bits.CCP1IF=0; 
    
    CCP1CON=0b00000101; 
    CCPR1=0;        
    
    T1CONbits.RD16=0;
    T1CKPS0=0;
    T1CKPS1=0;
    TMR1CS=0;
    
    while(1)        
    {    
        CCP1CON         = 0b00000101;
        PIR1bits.CCP1IF = 0;
        TMR1ON          = 0; 
        TMR1            = 0;

        while (!PIR1bits.CCP1IF)
            ;

        TMR1ON          = 1; 
        CCP1CON         = 0b00000100;
        PIR1bits.CCP1IF = 0;
    
        if (TMR1IF==1)
        {
            x++;
            TMR1IF=0;
        }
    
        while (!PIR1bits.CCP1IF)
            ; 

        comtage = x; 
    
        Deph_tempo = ((float)comtage /7843.13 ); 
        sprintf(DEPHASAGE,"%.5f  ",Deph_tempo); 

        LCD_String_xy(2,0,DEPHASAGE);
    }
    x = 0;
}                              

``

有一种方法可以实现您想要做的事情...这有点棘手,因为您需要一个宽度超过 16 位的计时器。可以同时使用 TMR1 和 TMR3 与 CCPCON 一起工作,并得到一个 19 位宽的定时器,在 Fosc = 8MHz 时,您输入到定时器的时钟是 2MHz,这意味着这个 19 位定时器将在 2^19 * 后翻转.5 us = 264 us 秒左右...我们可以使用 TMR3IF 检测翻转并将其设为 20 位,但这仍然有点短。

也可以使用具有 1:256 预分频器的 TMR0,但您需要为 TMR0 提供外部时钟。您可以使用 TMR3 和 PWM 发生器在 CCP2/RC1 上生成 500kHz 时钟信号,并将其路由到 TK0CKI/RA4。这将有效地创建一个 26 位计数器,分辨率为 4/Fosc = .5 us,范围为 33.55 秒。您可以通过使用 PLL 来增加振荡器频率来增加分辨率。这还有一个好处,那就是它会非常精确。可重复性取决于循环。使用 ISR 捕获中断会大大提高可重复性。

#include <stdio.h>
#include <stdlib.h>

#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>

void main()
{
    unsigned long count = 0;

    // Setting up TMR0 for extarnal clock on T0CKI/RA4

    LATAbits.LATA4    = 0;
    TRISAbits.TRISA0  = 1;     // RC0 as input
    T0CON             = 0x27   // Prescaler 1:256, 0->1 transition, T0CKI input 
    TMR0IE            = 0;     // mask interrupts.

    // Setting up TMR1/CCP1CON for capture on RC2/CCP1

    TRISCbits.TRISC2  = 1;     // CCP2/RC2 as input
    LATCbits.LATC2    = 0;
    T1CON             = 0x80   // internal clock oscillator off, 1:1 pre, 16 bits reads
    TMR1              = 0;
    CCP1CON           = 0x05   // set capture mode on rising edge
    CCP2IE            = 0;     // mask interrupts
    TMR1IE            = 0;

    // Setting up TMR2/CCP2CON for generating the clock on CCP2/RC1

    LATCbits.LATC1    = 0;     // clear RC1 latch
    TRISCbits.TRICSC1 = 0;     // RC1 as output
    T2CON             = 0;     // timer2 off, prescaler 1:1, post scaler 1:1
    PR2               = 3;     // PWM frequency = (Fosc / 4) / 4
    TMR2              = 0;
    CCPR2             = 0;
    CCP2CON           = 0x1C;  // CCP2M = PWM mode, DCB2<0> = 1 (LSB for duty cycle compare) 
    CCP2IE            = 0;     // mask interrupts
    TMR2IE            = 0;

    while (1)
    {
        // get ready to capture.
        TMR2ON          = 0;      // stop our timing clock.
        TMR0ON          = 0;      // this reset TMR0 prescaler
        TMR0            = 0;      // clear timers.
        TMR1            = 0;
        TMR2            = 0;
        TMR0ON          = 1;      // Timer 0 is ready to count.
        CCP1CON         = 0x05;   // set capture mode on rising edge
        PIR1bits.CCP1IF = 0;

        while (!PIR1bits.CCP1IF)  // wait for event
            ;

        PIR1bits.CCP1IF = 0;
        CCP1CON         = 0x04;   // set capture mode on falling edge

        TMR1ON          = 1;
        TMR2ON          = 1;

        while (!PIR1bits.CCP1IF)  // wait for event
            ;
        
        // here we have to make sure to keep the same latency as after 
        // rising edge, so we are precise. 
        PIR1bits.CCP1IF = 0;
        CCP1CON         = 0x04;   // set capture mode on rising edge

        TMR1ON          = 0;
        TMR2ON          = 0;      // also stops TMR0 

        // TMR0's clock is is divided by 2²2 * 2^8 = 2^10
        // its lower 6 bits should be equal to the upper 6 bits
        // of TMR1.   
        count = ((TMR0 & 0xFFC0 << 10) + TMR1;

        // convert to us
        count >>= 1;

        // display...
    }
}

在我面前没有实际设备和示波器的情况下,这是我所能达到的最接近水平。如果您有任何疑问或遇到任何问题,请告诉我。