打印

CCP1中断读取CCPR1H:CCPR1L,但是读出的总是随机数

[复制链接]
4660|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hahahaluo|  楼主 | 2007-12-25 10:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
CCP1引脚输入1KHZ的方波,我用示波器看过,已经进入CCP1中断,但是中断中读取CCPR1H:CCPR1L,但是读出的总是随机数,给位帮我看看是什么问题,

1.上电,运行,几分钟都是CCPR1H=0xF0,CCPR1L=0xC0,

2.断电,电容放电,上电,运行,几分钟都是CCPR1H=0xCA,CCPR1L=0x56,

3.PIC程序清除,断电,电容放电,上电,运行,几分钟都是CCPR1H=0xDF,CCPR1L=0xFF,

4......

#include <p18f2480.h> 


unsigned char cap_high;
unsigned char cap_low;


void VectorHigh (void);
void HandlerHigh (void);

#pragma code VectorHigh = 0x08
void VectorHigh (void)
{
  _asm
    goto HandlerHigh //jump to interrupt routine
  _endasm
}
#pragma code

#pragma interrupt HandlerHigh
void HandlerHigh ()
{
//CCP1中断----------------------------------

 if(PIR1bits.CCP1IF)  
 {  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
 cap_low=CCPR1L;
 cap_high=CCPR1H;

 CCPR1H=0;
 CCPR1L=0;
 }

}
#pragma code

void main() 

TRISCbits.TRISC2= 1; //设定RC2为输入

CCP1CON = 0x04;//CCP1下降沿捕捉模式

T3CON = 0;

CCPR1H=0;
CCPR1L=0;

PIE1bits.CCP1IE=1;//CCP1中断打开
PIR1bits.CCP1IF=0;//CCP1溢出标志
IPR1bits.CCP1IP = 1;//CCP1溢出中断优先级为高中断

T1CON = 0x00;//关闭定时器1

PIE1bits.TMR1IE=1;//定时器1中断打开
PIR1bits.TMR1IF=0;//定时器1溢出标志
IPR1bits.TMR1IP = 1;//定时器1溢出中断优先级为高中断

INTCONbits.GIE = 1;//全局中断打开
INTCONbits.PEIE=1;//外围设备中断打开

for(;;);



帮帮我吧,崩溃了
沙发
systemchip| | 2007-12-25 15:41 | 只看该作者

定时器都没开,怎么工作?

使用特权

评论回复
板凳
hahahaluo|  楼主 | 2007-12-25 16:34 | 只看该作者

我又试了下,好像不是这个原因

#include <p18f2480.h> 

unsigned char cap_high;
unsigned char cap_low;

void VectorHigh (void);
void HandlerHigh (void);

#pragma code VectorHigh = 0x08
void VectorHigh (void)
{
  _asm
    goto HandlerHigh //jump to interrupt routine
  _endasm
}
#pragma code

#pragma interrupt HandlerHigh
void HandlerHigh ()
{
//CCP1中断----------------------------------

 if(PIR1bits.CCP1IF)  
    {  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
    cap_low=CCPR1L;
    cap_high=CCPR1H;

    CCPR1H=0;
    CCPR1L=0;
    LATBbits.LATB1 = !LATBbits.LATB1;//后加的,判断是否进入中断
    }

}
#pragma code

void main() 

TRISCbits.TRISC2= 1; //设定RC2为输入

TRISB = 0;//后加的,定义PB.0-.7口作输出

CCP1CON = 0x04;//CCP1下降沿捕捉模式

T3CON = 0x01;//无论T3CON=0x00还是0x01,都进入中断,结果一样

CCPR1H=0;
CCPR1L=0;

PIE1bits.CCP1IE=1;//CCP1中断打开
PIR1bits.CCP1IF=0;//CCP1溢出标志
IPR1bits.CCP1IP = 1;//CCP1溢出中断优先级为高中断

T1CON = 0x01;//无论T1CON=0x00还是0x01,都进入中断,结果一样

PIE1bits.TMR1IE=0;//定时器1中断打开
PIR1bits.TMR1IF=0;//定时器1溢出标志
IPR1bits.TMR1IP = 1;//定时器1溢出中断优先级为高中断

INTCONbits.GIE = 1;//全局中断打开
INTCONbits.PEIE=1;//外围设备中断打开

for(;;);


看到楼上回复,我又用示波器测了下,结果还是一样

使用特权

评论回复
地板
systemchip| | 2007-12-25 23:16 | 只看该作者

:

捕捉时间发生后,其并不会复位计数器,所以从相邻两个计数结果差异就可以得到两次捕捉时间的间隔。。。。。

使用特权

评论回复
5
兰天白云| | 2007-12-26 08:25 | 只看该作者

LS正解

使用特权

评论回复
6
hahahaluo|  楼主 | 2007-12-26 09:33 | 只看该作者

得到的结果是CCPR1= 0x4e44

void HandlerHigh ()
{
//CCP1中断----------------------------------

if(PIR1bits.CCP1IF)  
{  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
cap_low=CCPR1L-cap_low;          //差值
cap_high=CCPR1H-cap_high;        //差值

}

}

修改了下中断,如果不发生溢出,cap_high、cap_low的值应该接近,

icd2不能实时跟踪CCPR1,所以我在main()中加入串口发送4次/秒,
不占用中断波特率115200,看cap_high、cap_low的值,每次都是4e 44

再问下下,被捕捉信号1KHZ(PIC晶振4M),差值应该是03e8,对不对??

使用特权

评论回复
7
hahahaluo|  楼主 | 2007-12-26 09:50 | 只看该作者

感觉自己找问题的方向不对,版主有没有好的建议

1.上电,运行,几分钟都是CCPR1H=0x4e,CCPR1L=0x44,

2.断电,换新的芯片,上电,运行,几分钟都是CCPR1H=0x84,CCPR1L=0x2c,

3.PIC程序清除,断电,电容放电,上电,运行,几分钟都是CCPR1H=0x84,CCPR1L=0x2c,

4......

感觉自己找问题的方向不对,版主有没有好的建议

谁有CCP1捕捉的例程,参考下,我手上只有16F87X的一个例子,希望有多点作参考

使用特权

评论回复
8
兰天白云| | 2007-12-26 11:20 | 只看该作者

考虑一下,打开/关闭CCP(在程序中)

使用特权

评论回复
9
hahahaluo|  楼主 | 2007-12-26 13:16 | 只看该作者

我找到原因了

正如systemchip所说,定时器开关有问题,不知道为什么

过程:

1.像上面程序配置好CCP1相关的寄存器,一定要打开两个中断使能和一个定时器开关
      PIE1bits.CCP1IE=1;//CCP1中断打开
      PIE1bits.TMR1IE=0;//定时器1中断打开
      T1CONbits.TMR1ON = 1;//打开定时器1
否则,CCPR1读出值是随机的,或者根本就进不了中断

2.中断程序
void HandlerHigh ()
{
//CCP1中断----------------------------------
TMR1H=0;                //定时器1一定要在中断里面清0
TMR1L=0;                //进入中断先清0,保证计时精度

if(PIR1bits.CCP1IF)  
{  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
    cap_low=CCPR1L;          
    cap_high=CCPR1H-;        

}

}

这两句一定要加:
TMR1H=0;
TMR1L=0;
否则读的是差值,而且程序跳不出中断(不知道为什么?)    

3.使用定时器3,寄存器T3CON的T3ECCP1和T3CCP1一定要配置,资料上对18F2480说的不完整:只说2480没有这两个寄存器。
T3CONbits.T3ECCP1 = 1;//定时器3是CCP1的时钟源
T3CONbits.T3CCP1 = 0;//定时器3是CCP1的时钟源
如果不配置,CCP1中断能进入,但是CCPR1读出值是随机的

终于搞出来,感觉自己还是细节上出错,否则不会这么久

使用特权

评论回复
10
systemchip| | 2007-12-26 15:15 | 只看该作者

:

2.中断程序
void HandlerHigh ()
{
//CCP1中断----------------------------------
TMR1H=0;                //定时器1一定要在中断里面清0
TMR1L=0;                //进入中断先清0,保证计时精度

if(PIR1bits.CCP1IF)  
{  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
    cap_low=CCPR1L;          
    cap_high=CCPR1H-;        

}

}

这两句一定要加:
TMR1H=0;
TMR1L=0;
否则读的是差值,而且程序跳不出中断(不知道为什么?)  


---建议不要这样操作,因为这样会丢失计数器在中断延迟/现场保护期间的计数数据,因为你无法得知这段期间记数的数据(尤其是当你使用C语言编程时候,中断程序中将加入部分中断现场保护代码),这样会导致捕捉结果的误差,当然你可以人为的进行数据补偿。
   另外如果这样操作的话,该Timer就不能做其他的记数/记时控制,造成资源的浪费。
   所以还是建议你使用从相邻两个计数结果差异得到两次捕捉时间的间隔。

使用特权

评论回复
11
systemchip| | 2007-12-26 15:38 | 只看该作者

void main() 

TRISCbits.TRISC2= 1; //设定RC2为输入
CCP1CON=0x00;
TMR1H=0x00;
TMR1L=0x00;     // clear Timer1 Counter

CCPR1H=0;
CCPR1L=0;

T3CON = 0x00;//Timer1 for CCP

CCP1CON = 0x04;//CCP1下降沿捕捉模式


PIE1bits.CCP1IE=1;//CCP1中断打开
PIR1bits.CCP1IF=0;//CCP1溢出标志
IPR1bits.CCP1IP = 1;//CCP1溢出中断优先级为高中断

RCONbits.IPEN=1;
INTCONbits.GIE = 1;//全局中断打开
INTCONbits.PEIE=1;//外围设备中断打开


T1CONbits.TMR1ON =1;//open Timer1

while(1);

使用特权

评论回复
12
hahahaluo|  楼主 | 2007-12-26 17:23 | 只看该作者

systemchip果然老道,知道我下步在想什么,这方法真好

void HandlerHigh ()
{
//CCP1中断----------------------------------

if(PIR1bits.CCP1IF)  
{  
    PIR1bits.CCP1IF = 0;            //一定要在中断里面赋值
    if(ccpnumber==0)cap=CCPR1;
    if(ccpnumber==1)
    {
    cap=CCPR1-cap;
    cap_high=cap/0x0100;
    cap_low=cap;
    }
    ccpnumber++;
}

}

1KHZ捕捉,
第一种方法直接读,捕捉值03 dd (左右),偏差大
第二种方法差值读,捕捉值03 e8(偶尔有03 e9)
估计把PIR1bits.CCP1IF = 0;  放到最后,出现03 e9的次数会更少

使用特权

评论回复
13
strangestar| | 2012-9-6 11:44 | 只看该作者
小弟也在写类似的应用程序,但是一开始是进不了中断,挣扎可很久,后来进去了却没法读取数据,不懂为什么,希望楼主帮帮忙。谢谢啦

//功能:实现捕捉完成频率测量功能
//具体设置:ccp1con=00000101上升沿捕捉;


#include<pic.h>
#include<math.h>
#define uchar unsigned char;
#define uint unsigned int;
void init();
void interrupt int_ccp();//中断
unsigned int hz;//频率
unsigned char n1,n2,n3,n4,n5;
void disp();//显示
void delay(int n);
unsigned int p,q,tm,count,flag=0;
const int table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

void main()
{
  init();
  while(1)
  {
    disp();//delay(1);
  }
}
void init()//初始化
{  
  TRISC=0;PORTC=0;
  TRISC2=1;TRISB=0;TRISD=0;
  TMR1L=0X00;
  TMR1H=0X00;
  CCPR1L=0;
  CCPR1H=0;
  CCP1CON=0B00000111;//16个采样一次
  PIR1=0;//标志位清零
  PIE1=0X05;//使能
  INTCON=0XC0;//总中断打开
  T1CON=0X01;
  //PORTC=0X01;

}
void interrupt int_ccp()
{
   GIE=0;
   if(TMR1IF==1)
     {
       TMR1IF=0;
       TMR1L=0;
       TMR1H=0;
       count++;
     }
   if(CCP1IF==1);
     {
       CCP1IF=0;
       flag=!flag;
       if(flag==1)
          {
            TMR1L=0;
            TMR1H=0;
            count=0;
            
          }
       else
          {
            PORTC=0X01;
            tm=CCPR1H<<8|CCPR1L;
            hz=(count*65534+tm)/4000000;
            hz=15/hz;
            
          }
     }
   TMR1ON=1;   
   GIE=1;  
}
void disp()
{
   n1=hz/10000;
    n2=hz%10000/1000;
    n3=hz%1000/100;
    n4=hz%100/10;
    n5=hz%10;
  PORTB=0xff;
  PORTD=table[n1];
  RB1=0;
  delay(5);
  PORTD=table[n2];
  RB1=1;
  RB2=0;
  delay(5);
  PORTD=table[n3];
  RB2=1;
  RB3=0;
  delay(5);
  PORTD=table[n4];
  RB3=1;
  RB4=0;
  delay(5);
  PORTD=table[n5];
  RB4=1;
  RB5=0;
  delay(5);
}
void delay(int n)
{
  uint p,q;
  for(p=n;p>0;p--)
  for(q=110;q>0;q--);
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

41

帖子

0

粉丝