打印

仿真成功,硬件总是有问题,CCP的频率计经常漂移

[复制链接]
2461|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
毅如靳往|  楼主 | 2011-8-3 21:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ccp1.rar (179.89 KB)
使用proteus软件仿真基于PIC16F877A的数字频率计

仿真的时候没有问题   正确的显示频率信号

但是烧写到硬件的时候  

出现了  
无法计算频率的问题

数码管显示的数字不断的在改变  

本人用的  函数信号发生器    产生 的    50.27HZ的    VPP为2V的  方波信号


请各位不吝赐教


//220v的交流电源直接用电阻限流,经光耦隔离,形成脉冲送到ccp2捕捉、动态显示
//A口做位选,D口做段选
#include<PIC.H>
__CONFIG(0x3F71);
# define T0_2MS 6    //TMR0的2ms延时常数,8分频
# define LED_QW RA0
# define LED_BW RA1
# define LED_SW RA2
# define LED_GW RA3
//全局变量定义
char WW,QW,BW,SW,GW;
char FUN,D1,A;
unsigned int TTZ,TON;
//函数声明
void CSH(void);
void BCD(unsigned int);
void interrupt INT_ISR(void);
void DELAY(unsigned int);
void DELAY_I(unsigned int);
const char LED_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
      0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
//const char LED_CODE[17]={0b11000000,0b11111001,0b10100100,0b10110000,
//                       0b10011001,0b10010010,0b10000010,0b11111000,
//       0b10000000,0b10010000,0b10001000,0b10000011,
//       0b11000110,0b10100001,0b10000110,0b10001110,0b11111111};

void main(void)
{   
  DELAY(10);
     CSH();
     while(1);
}

void interrupt INT_ISR(void)
{
long X;
unsigned int Y;
if(CCP2IF==1 && CCP2IE==1)
{
  CCP2IF=0;
  if(FUN<2)FUN++;  //只在FUN<3时才加1
  if(FUN==1)   //第一次ccp2中断,开始tmr0计数
  {
   TMR1L=0;TMR1H=0;
   CCP2CON=0;
   CCP2CON=0b00000111;   //每16个上升沿中断
   CCP2IF=0;
   PORTA=0xf0&PORTA; //关闭显示
   PORTD=0x00;
  }
  else if(FUN==2)               //弟二次ccp2中断,计算周期
  {
   TTZ=(CCPR2H<<8) | CCPR2L;    //将双字节数变成整数型,ttz为频率计算用
   CCP2CON=0;
   CCP2IE=0;
   PEIE=0;
   X=200000000;     //频率的100倍,显示2位小数
   X=X/TTZ;
   Y=X;
   BCD(Y);      //作bcd转换
   D1=TON=0;    //准备显示频率
   T0IE=1;
   FUN=3;
  }
}
if(T0IF==1&&T0IE==1)
{
T0IF=0;
if(FUN==3)
{
  TMR0=T0_2MS;
  PORTA=0xf0&PORTA; //关闭显示
  PORTD=0x00;
  switch(D1)
  {
   case 0:    //显示千位
    PORTD=LED_CODE[GW];
    LED_GW=1;
    break;
   case 1:   //显示百位
    PORTD=LED_CODE[SW];
    PORTD=PORTD|0x80;    //最高位为0,显示小数点
    LED_SW=1;
    break;
   case 2:   //显示十位
    PORTD=LED_CODE[BW];
    LED_BW=1;
    break;
   case 3:   //显示个位
    PORTD=LED_CODE[QW];
    LED_QW=1;
    break;
  }
D1=D1+1;   //D1=1~4分别显示千位、百位、十位、个位
  if(D1>3)D1=0;
TON=TON+1;
if(TON>=200)
{
  TON=D1=FUN=0;   //显示次数到
  PORTA=0xf0&PORTA; //关闭显示
  PORTD=0x00;
  DELAY_I(100);  //灭100ms,以造成闪动效果
  PIR2=0;
  PEIE=1;
  CCP2IE=1;
  CCP1IE=1;
  CCP2CON=0;
  CCP1CON=0;
  CCP2CON=0b00000101;     //每1个上升沿中断
  CCP1CON=0b00000101;     //每1个上升沿中断
  CCP2IF=0;
  CCP1IF=0;
  INTCON=0b11000000;      //允许外围中断
}
}
}
}

void CSH(void)   //初始化程序
{ OPTION=0b10000010; //TMR0分频系数为1:8
TRISB=0b00000001; //RB0为CIS选择
TRISA=0b00000000; //RA0,RA3为输入,RA4必须为输出才有脉冲
TRISC=0b00000010; //RC口除RC1/CCP2外全为输出
TRISD=0b00000000; //RD口全为输出

PORTA=0x00;
PORTD=0x00;
TON=D1=FUN=0;
PIR2=0;
PEIE=1;
CCP2IE=1;  //允许捕捉中断
CCPR2H=CCPR2L=0;
CCP2CON=0;
CCP2CON=0b00000101; //每一个上升沿中断
TMR1H=TMR1L=0;
T1CON=0b00110001; //RMR1分频比为1:8
INTCON=0b11000000; //允许外围中断
}

void DELAY(unsigned int n)
{
unsigned int j;
char k;
for(j=0;j<n;j++)
  for(k=246;k>0;k--)NOP();
}

void DELAY_I(unsigned int n)  //延时函数,中断专用
{
unsigned int j;
char k;
for(j=0;j<n;j++)
  for(k=246;k>0;k--)NOP();
}
void BCD(unsigned int R1)
{
WW=0;QW=0;BW=0;SW=0;GW=0;
while(R1>=10000)
  {R1-=10000;WW++;}
while(R1>=1000)
  {R1-=1000;QW++;}
while(R1>=100)
  {R1-=100;BW++;}
while(R1>=10)
  {R1-=10;SW++;}
GW=R1;
}
沙发
NE5532| | 2011-8-3 22:25 | 只看该作者
求流程图

使用特权

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

本版积分规则

2

主题

176

帖子

1

粉丝