protues仿真之数码管消影问题

最近因为课程需要,需要做一个基于PCF8591 A/D转换的数字直流电压表,精确到小数点后三位。本来一个很简单的题目,三下五下写完代码烧到开发板运行没多大问题。接下来需要画出相应的protues仿真电路图,画好电路图加载程序却出现数码管显示不出来的结果。
于是改代码,检查电路都没效果。最终发现是消影语句出的问题。 在开发板上演示时消影语句是:P0=0xff ; 而在protues 上仿真时消影要写成:P0=0x00 ; 只有这样程序才能运行正常。下面把整个题目分享出来,有兴趣的可以试一下,希望不要有人再掉入这个坑!!

源代码:

 /**********************四位直流数字电压表************************
描述:通过调节可调电阻来模拟现实的电压输入量,采用PCF8091 A/D 转换芯片将电压采样, 量化后数码管显示出电压值
日期: 2016.10.27
******************************************************************/
/*-----------------------------------------------
  名称:IIC协议 PCF8591ADDA转换          显示有4个,注意只有2个可以调节电压的
  内容:此程序通过IIC协议对DAAD芯片操作,读取电位器的电压通过液晶显示,并输出模拟量,用LED亮度渐变指示
------------------------------------------------*/
 #include    //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
 #include  //包含NOP空指令函数_nop_();

 #define AddWr 0x90   //写数据地址 
 #define AddRd 0x91   //读数据地址
#define uchar unsigned char
#define uint unsigned int

 sbit RST=P2^4;   //时钟 加上后可以关掉DS1302芯片输出
 sbit Sda=P2^0;       //定义总线连接端口
 sbit Scl=P2^1;
sbit DU=P2^6;
sbit WE=P2^7;
 bit ADFlag;          //定义AD采样标志位
 uchar code table[17]={0x3f , 0x06 , 0x5b ,0x4f , 0x66 , 0x6d ,0x7d ,
                   0x07 , 0x7f , 0x6f ,0x77 , 0x7c , 0x39 , 
                   0x5e , 0x79 , 0x71 , 0x80 };  //0-9&A-F&“不显示”  字型码?

void  stopwatch(uchar ge, uchar z1,uchar z2, uchar z3)   ;



/*------------------------------------------------
                    延时程序
------------------------------------------------*/
 void mDelay(unsigned char j)
 {
  unsigned int i;
  for(;j>0;j--)
     {
      for(i=0;i<125;i++)
         {;}
      }
  }
/*------------------------------------------------
                    初始化定时器1
------------------------------------------------*/
void Init_Timer1(void)
{
 TMOD |= 0x10;               
 TH1=0xff;                  /* Init value */
 TL1=0x00;
 //PT1=1;                   /* 优先级    */
 EA=1;                      /* interupt enable */
 ET1=1;                     /* enable timer1 interrupt */
 TR1=1;  
}
/*------------------------------------------------
                    启动IIC总线
------------------------------------------------*/
  void Start(void)
  {
   Sda=1;
   _nop_();
   Scl=1;
   _nop_();
   Sda=0;
   _nop_();
   Scl=0;
  }


/*------------------------------------------------
                    停止IIC总线
------------------------------------------------*/
  void Stop(void)
  {
   Sda=0;
   _nop_();
   Scl=1;
   _nop_();
   Sda=1;
   _nop_();
   Scl=0;
   }


/*------------------------------------------------
                   应答IIC总线
------------------------------------------------*/
   void Ack(void)
   {
    Sda=0;
    _nop_();
    Scl=1;
    _nop_();
    Scl=0;
    _nop_();
    }


/*------------------------------------------------
                 非应答IIC总线
------------------------------------------------*/
    void NoAck(void)
    {
     Sda=1;
     _nop_();
     Scl=1;
     _nop_();
     Scl=0;
     _nop_();
     }


/*------------------------------------------------
              发送一个字节
------------------------------------------------*/
     void Send(unsigned char Data)
     { 
      unsigned char BitCounter=8;
      unsigned char temp;

      do
        {
         temp=Data;
         Scl=0;
         _nop_();
         if((temp&0x80)==0x80)
            Sda=1;
         else
            Sda=0;

            Scl=1;
            temp=Data<<1;
            Data=temp;
            BitCounter--;
          }
      while(BitCounter);
          Scl=0;
      }


/*------------------------------------------------
               读入一个字节并返回
------------------------------------------------*/
      unsigned char Read(void)
      {
       unsigned char temp=0;
       unsigned char temp1=0;
       unsigned char BitCounter=8;

       Sda=1;
       do
         {
          Scl=0;
          _nop_();
          Scl=1;
          _nop_();
          if(Sda)
             temp=temp|0x01;
          else
             temp=temp&0xfe;

          if(BitCounter-1)
             {
              temp1=temp<<1;
              temp=temp1;
              }
              BitCounter--;
             }
        while(BitCounter);
        return(temp);
      }

/*------------------------------------------------
                    写入DA数模转换值
------------------------------------------------*/
      void DAC(unsigned char Data)
      {
           Start();
           Send(AddWr); //写入芯片地址
           Ack();
           Send(0x40);  //写入控制位,使能DAC输出
           Ack();
           Send(Data);  //写数据
           Ack();
           Stop();

       }

/*------------------------------------------------
                 读取AD模数转换的值,有返回值
------------------------------------------------*/
      unsigned char ReadADC(unsigned char Chl)
      {
       unsigned char Data;
           Start();        //写入芯片地址
           Send(AddWr);
           Ack();
           Send(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
                          //Chl的值分别为0、1、2、3,分别代表1-4通道
           Ack();
           Start();
           Send(AddRd);    //读入地址
           Ack();
           Data=Read();    //读数据
           Scl=0;
           NoAck();
           Stop();
           return Data;   //返回值
      }


/*------------------------------------------------
                   主程序
------------------------------------------------*/
    void main()
    {
        int  ge , z1, z2, z3 ;                   //DA数模输出变量
    int ADtemp;                //定义中间变量
    mDelay(20);
   Init_Timer1();
        RST=0;      //      关时钟DS1302
         while(1)
          { 
           if(ADFlag)      //定时采集输入模拟量
           {
             ADFlag=0;       //  清除标志位
          ADtemp=(int)(ReadADC(3)*0.01961*1000);  // 将八位量化值转化成十进制数
           ge =ADtemp/1000;
                z1 =ADtemp%1000/100;         
       z2 =ADtemp%1000%100/10;
             z3=ADtemp%10;
        stopwatch( ge, z1, z2,  z3) ; 

           }

       }
    }

    void  stopwatch(uchar ge, uchar z1,uchar z2, uchar z3)     // 数码管显示函数
{          
                   DU=1;
             P0=table[ ge];   //  各位数
              DU=0;
                  WE=1;
            P0=0xef;
               WE=0;
                  mDelay(3) ;       
            P0=0x00;
          //P0=0xff;    
                DU=1;
            P0=table[ 16];  //   小数点
              DU=0;
              WE=1;
             P0=0xef;
              WE=0;
                  mDelay( 1) ; 
             P0=0x00;
             //  P0=0xff;
           DU=1;
            P0=table[ z1];  //  小数点后一位
              DU=0;
              WE=1;
             P0=0xdf;
              WE=0;
                  mDelay( 8) ; 
                     P0=0x00;
                //   P0=0xff;
                     DU=1;
            P0=table[ z2];  //   小数点后两位
              DU=0;
              WE=1;
             P0=0xbf;
              WE=0;
                  mDelay( 5) ; 
                     P0=0x00;
                    //  P0=0xff;
                     DU=1;
            P0=table[ z3];  //  小数点后三位
              DU=0;
              WE=1;
             P0=0x7f;
              WE=0;
                  mDelay( 5) ;
            P0=0x00;
           // P0=0xff;                      // 使用开发板时用
}




/*------------------------------------------------
                   定时器中断程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 
{
 static unsigned int j;
 TH1=0xfb;      //重新赋值
 TL1=0x00;
 j++;
 if(j==10) 
    {j=0;ADFlag=1;} //定时置位AD采样标志位
}   

仿真图:
protues仿真之数码管消影问题_第1张图片

你可能感兴趣的:(单片机)