89c51仿真时出现问题,请教各位大侠!

来源:百度文库 编辑:神马文学网 时间:2024/04/19 01:32:12

89c51仿真时出现问题,请教各位大侠!

相关搜索: 大侠, 仿真, 请教

本帖最后由 ANSI_gao 于 2010-8-1 10:51 编辑

 

我用了两片89c51,一片用来产生两个负边缘信号(前后时间相差0.3秒,输出到另一块89c51的INT0,INT1用来触发外部中断。)同时不断发出38.5kHZ的频率信号。另一块89c51接到第一个外部中断后Timer0开始计时,Timer1计数clock发出的脉冲信号,在接到0.3秒后的第二个外部中断INT1停止计时计数。把测得的时间和脉冲显示在lcd上。但是用protued 仿真时没成功。我弄不懂,好郁闷啊。特来请教各位大侠。

/*********************************************

程序功能:按键按下P1.0产生一个负边缘输出信号

定时0.3秒之后P1.1产生另外一个负边缘输出信号

**********************************************/

#include

#define uchar unsigned char

#define uint  unsigned int

#define ulong unsigned long

#define TH_M1 (65536-50000)/256     //timer0定时0.05sX6次=0.3s

#define TL_M1 (65536-50000)%256

extern void cs_t(void);    //超声波发生函数

sbit flag_P=P0^0;         

sbit P1_0=P1^0;            //P1^0 P1^1用来产生两个下降沿信号

sbit P1_1=P1^1;

uint cou_t=0;             //每0.05s cou_t加1

void main()

{

  IE=0x82;                    /*允许T0中断*/

  TMOD=0x01;            //timer0选择mode1

  P1_0=1; P1_1=1;       //初始设置两个输出口为高电平

  if(flag_P=1)

    while(flag_P)

      cs_t();       //P0^0的按键没有按下前发射超声波

  if(flag_P==0){   

  P1_0=0;

  TR0=1;

  TH0=TH_M1;

  TL0=TL_M1;       //P0^0的按键按下后启动Timer0定时

  for(;cou_t<7;)

    cs_t();       //定时6次=0.3s

  P1_1=0;

  for(;;)

    cs_t();        //发射超声波

  }

  return ;

}

 

void timer0(void) interrupt 1       //timer0定时中断

{

    TH0=TH_M1;

    TL0=TL_M1;

    cou_t++;

}

/*****************************************************

在INT0~INT1两个外部中断的时间间隔内计时timer1传来的外部脉冲

同时timer0对这段时间间隔进行计时,把时间,脉冲数在液晶上显示

*****************************************************/

 

#include

#include

#define uchar unsigned char

#define uint  unsigned int

#define ulong unsigned long

#define TH_M2 (256-100)       // 定时100us                               

#define TL_M2 (256-100)

uchar msg1[]="Pulse:";         //液晶第一行显示的信息

uchar msg2[]="Time:0.";        //液晶第二行显示的信息

uchar num1[5]={0,0,0,0,0};     //存放测得脉冲个数

uchar num2[4]={0,0,0,0};       //0.————秒

ulong cou_t=0;                 //记录时间,每100us cou_t加1

ulong pulses=0;                //记录测得的脉冲个数

sbit RS=P2^0;    //寄存器选择位,将RS位定义为P2.0引脚

sbit RW=P2^1;    //读写选择位,将RW位定义为P2.1引脚

sbit E=P2^2;     //使能信号位,将E位定义为P2.2引脚

sbit BF=P0^7;    //忙碌标志位,,将BF位定义为P0.7引脚

bit end_flag=0;

/*****************************************************

函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒

***************************************************/

void delay1ms()

{

   unsigned char i,j;  

     for(i=0;i<10;i++)

      for(j=0;j<33;j++)

       ;        

}

/*****************************************************

函数功能:延时若干毫秒

入口参数:n

***************************************************/

void delay(unsigned char n)

{

   unsigned char i;

    for(i=0;i

       delay1ms();

}

 

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:result。result=1,忙碌;result=0,不忙

***************************************************/

unsigned char BusyTest(void)

  {

    bit result;

    RS=0;       //根据规定,RS为低电平,RW为高电平时,可以读状态

    RW=1;

    E=1;        //E=1,才允许读写

    _nop_();   //空操作

    _nop_();

    _nop_();

    _nop_();   //空操作四个机器周期,给硬件反应时间

    result=BF;  //将忙碌标志电平赋给result

   E=0;         //将E恢复低电平

   return result;

  }

/*****************************************************

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数:dictate

***************************************************/

void WriteInstruction (unsigned char dictate)

{  

    while(BusyTest()==1); //如果忙就等待

     RS=0;                  //根据规定,RS和R/W同时为低电平时,可以写入指令

     RW=0;  

     E=0;                   //E置低电平(根据表8-6,写指令时,E为高脉冲,

                          // 就是让E从0到1发生正跳变,所以应先置"0"

     _nop_();

     _nop_();             //空操作两个机器周期,给硬件反应时间

     P0=dictate;            //将数据送入P0口,即写入指令或地址

     _nop_();

     _nop_();

     _nop_();

     _nop_();               //空操作四个机器周期,给硬件反应时间

     E=1;                   //E置高电平

     _nop_();

     _nop_();

     _nop_();

     _nop_();               //空操作四个机器周期,给硬件反应时间

      E=0;                  //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:指定字符显示的实际地址

入口参数:x

***************************************************/

void WriteAddress(unsigned char x)

{

     WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"

}

/*****************************************************

函数功能:将数据(字符的标准ASCII码)写入液晶模块

入口参数:y(为字符常量)

***************************************************/

void WriteData(unsigned char y)

{

    while(BusyTest()==1); 

      RS=1;           //RS为高电平,RW为低电平时,可以写入数据

      RW=0;

      E=0;            //E置低电平(根据表8-6,写指令时,E为高脉冲,

                       // 就是让E从0到1发生正跳变,所以应先置"0"

      P0=y;           //将数据送入P0口,即将数据写入液晶模块

      _nop_();

      _nop_();

      _nop_();

     _nop_();       //空操作四个机器周期,给硬件反应时间

      E=1;          //E置高电平

      _nop_();

      _nop_();

      _nop_();

     _nop_();        //空操作四个机器周期,给硬件反应时间

     E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:对LCD的显示模式进行初始化设置

***************************************************/

void LcdInitiate(void)

{

   delay(15);             //延时15ms,首次写指令时应给LCD一段较长的反应时间

   WriteInstruction(0x38);  //显示模式设置:16×2显示,5×7点阵,8位数据接口

    delay(5);               //延时5ms ,给硬件一点反应时间

   WriteInstruction(0x38);

    delay(5);

    WriteInstruction(0x38); //连续三次,确保初始化成功

    delay(5);

    WriteInstruction(0x0c);  //显示模式设置:显示开,无光标,光标不闪烁

    delay(5);

    WriteInstruction(0x06);  //显示模式设置:光标右移,字符不移

    delay(5);

    WriteInstruction(0x01);  //清屏幕指令,将以前的显示内容清除

    delay(5);

 

}

void int0(void) interrupt 0  //int0外部中断

{

  TH0=TH_M2;TL0=TL_M2;TR0=1; //启动timer0定时中断 mode2

  TH1=0;TL1=0;TR1=1;         //启动timer1计数

  }

 

void int1(void) interrupt 1  //t0定时中断

{

  cou_t++;}

 

void int2(void) interrupt 2    //int1外部中断

{

  pulses=TH1*256+TL1;          //脉冲数

  TR0=0;TR1=0;                 //停止timer0 timer1

  end_flag=1;                  //结束标志

  }

 

void translate()               //转换函数

{

  if(pulses>10000&&pulses<40000&&cou_t>1000&&cou_t<9000)

  {

  num1[0]=(uchar)pulses/10000;pulses=pulses%10000;

  num1[1]=(uchar)pulses/1000; pulses=pulses%1000;

  num1[2]=(uchar)pulses/100;  pulses=pulses%100;

  num1[3]=(uchar)pulses/10;   pulses=pulses%10;

  num1[4]=(uchar)pulses;

  num2[0]=(uchar)cou_t/1000;cou_t=cou_t%1000;

  num2[1]=(uchar)cou_t/100; cou_t=cou_t%100;

  num2[2]=(uchar)cou_t/10;  cou_t=cou_t%10;

  num2[3]=(uchar)cou_t;

  }

 

  }

 

void main()

{

  uint i,j;

  IE=0x8f;    //允许所有的中断

  IP=0x05;    //INT0 INT1 优先级为1

  TMOD=0x25;        //T0为Timer选择MODE2,T1为counter选择Mode1

  IT0=1;IT1=1;        //INT0,INT1选择下降沿触发

  LcdInitiate();      //lcd初始化                   

  WriteAddress(0x00);

  for(i=0;i<6;i++)

    WriteData(msg1);

  WriteAddress(0x40);

  for(j=0;j<7;j++)

    WriteData(msg2[j]);

  while(end_flag==0);   //等待结束

  if(end_flag==1)

  {

     _nop_();

     _nop_();

     translate();       //转换函数

     }

  WriteAddress(0x00+6);  

  for(i=0;i<4;i++)

    WriteData(num1);

  WriteAddress(0x40+7);

  for(j=0;j<5;j++)

    WriteData(num1);

  } 

protues仿真图.png (15.27 KB)

 

下载次数:0

 

2010-8-1 10:51

 

 

 

 

 c文件和电路图.rar (16.29 KB)

下载次数:4

 

2010-8-1 10:43

 

 

 

 

本文来自:proteus仿真论坛(http://proteus.5d6d.com),详细出处参考:http://proteus.5d6d.com/thread-12738-1-1.html