51单片机p0口需要数码管和lcd1602同时显示

我使用protues仿真时可以同时显示数码管数值和lcd数值,实物不可以

使用的74hc573驱动数码管

程序没有报错,实物只显示数码管
我尝试把lcd的数据输从p0口换到74hc573的输出口,仍然是可以仿真,实物板子没有到所以用了之前接在p0口的板子,发现数码管也没有了显示。
我想要数码管和lcd可以同时显示

仿真图片:

img

整个程序的代码:

#include <reg52.h>
#include "stdio.h"//标准输入输出
#include "intrins.h"//函数,使用空指令用到,字符循环移位
#include <math.h>//数学运算
#define uchar unsigned char 
#define uint unsigned int
#define DB P0//液晶并行数据接口
#define  normal_mode  0x10//显示模式
#define  set_mode  0x20//设置模式
sbit  hw_dx=P3^5;    //使用此引脚接红外探头检测"东西"方向通过的车辆,该引脚会呈现低电平
sbit  hw_nb=P3^6;    //使用此引脚接红外探头检测"南北"方向通过的车辆,该引脚会呈现低电平
sbit dula=P2^1;//段选信号
sbit wela=P2^0;//位选信号
sbit  RS = P1^6;//液晶指令数据信号
sbit E=P1^7;//液晶使能信号
sbit T_IO=P3^3;     //clk为DS1302的I/O数据线
sbit T_CLK=P3^2;    //DAT为DS1302的时钟信号线
sbit T_RST=P3^4;    //RST为DS1302的RST信号线 
sbit  Data=P3^1;       //温湿度IO
sbit dxred=P2^7;//东西方向红灯
sbit dxyellow=P2^6;//东西方向黄灯
sbit dxgreen=P2^5;//东西方向绿灯
sbit nbred=P2^4;//南北方向红灯
sbit nbyellow=P2^3;//南北方向黄灯
sbit nbgreen=P2^2;//南北方向绿灯
sbit key_jinzhi=P1^0;//禁止按键
sbit key_zeng=P1^4;//增按键
sbit key_jian=P1^5;//减按键
sbit key_night=P1^1;//晚上按键
sbit key_dxgreen_nbred=P1^2;//东西绿灯南北红灯
sbit key_dxred_nbgreen=P1^3;//东西红灯南北绿灯
sbit buzzer=P3^0;//蜂鸣器
uchar data set_time=10;        //设置方向的时间    
uchar data num_che_dx=0;        //设置变量用于记录东西通行车量的个数
uchar data num_che_nb=0;        //设置变量用于记录南北通行车辆的个数

uchar bdata datbyte;
sbit datbyte0=datbyte^0;
sbit datbyte7=datbyte^7;
uchar time_1302[7]={0x00,0x00,0x00,0x03,0x07,0x03,0x08};//设置时间初始值数组
                 //  秒   分   时   号  月份 星期  年
//DS1302函数声明
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void chushi();//红路灯初始化
void display_led();//红绿灯显示    
void get_1302(uchar time[]);//获取时间
void write_ds1302(uchar dat);//写入字节
uchar r_1302(uchar add);//读取数据
void w_1302(uchar add,uchar dat);//指定位置写入
uchar read_ds1302(void);//
void init_1302(uchar *time);//1302初始化
void change();//1302数值转换
uchar  times[9];//保存时间
uchar  date[11];//保存日期
unsigned char  key_value;//获取到按键的值
signed char  humi_value;//湿度
signed char  temp_value;//温度
unsigned char now_window;//当前显示窗口
unsigned char curr_menu;

void delay(uint);//延时
void display(uchar);//数码管显示
uchar num,num1,shi,ge;//数码管十位和个位显示数据
int s=0,n,a,b,c,d,e;//a是总时间增减的基数,b是东西南北一方增或减的基数,c是东西方向增减数,d是南北方向增减数
void delay(uint xms)//延迟x毫秒
{
  uint i,j;
    for(i=xms;i>0;i--)
     for(j=110;j>0;j--);
}    
void hw_dongxi()//东西红外探头
{
    
    if(hw_dx==0)                //东西红外探头
    {
        delay(10);               //调用显示,用于延时消抖和按键检测方法基本相同
        if(hw_dx==0)            //如果确定有车辆经过
        {
            if(dxgreen==0)        //东西通行的时间
            {        
                num_che_dx++ ;    //用于记录东西绿灯时经过的车辆数
            }
            else
            {
                buzzer=1;            //蜂鸣器开
                delay(1000);
            }
                while(!hw_dx);    //等待释放
                
        }
    }
}
void hw_nanbei()//南北红外探头
{

    if(hw_nb==0)                //南北红外探头
    {        
        delay(10);               //调用显示,用于延时消抖和按键检测方法基本相同 
        if(hw_nb==0)            //如果确定有车辆经过
        {
            if(nbgreen==0)        //东西通行的时间
            {
                        
                num_che_nb++;    //用于记录南北绿灯时经过的车辆数
            }
            else
            {
                buzzer=1;            //蜂鸣器开
                delay(1000);
            }
            while(!hw_nb);        //等待释放        
        }
    } 
}
void dxhong_nblv()//东西红灯,南北绿灯
{
    dxred=0;
    dxyellow=1;
    dxgreen=1;
    nbred=1;
    nbyellow=1;
    nbgreen=0;

    
}
void dxhuang_nblv()//东西黄灯,南北绿灯
{

  dxred=1;
    dxyellow=0;
    dxgreen=1;
    nbred=1;
    nbyellow=1;
    nbgreen=0;
}
void dxlv_nbhong()//东西绿灯,南北红灯
{

  dxred=1;
    dxyellow=1;
    dxgreen=0;
    nbred=0;
    nbyellow=1;
    nbgreen=1;
}
void dxlv_nbhuang()//东西绿灯,南北黄灯
{
    
  dxred=1;
    dxyellow=1;
    dxgreen=0;
    nbred=1;
    nbyellow=0;
    nbgreen=1;
}    

void led_panduan()//led显示判断
{
  if(s==60+d)//一次普通循环
    {
     s=0;
    }
    if(s==61+d)//晚上时的显示
    {
      dxred=1;
    dxyellow=0;
    dxgreen=1;
    nbred=1;
    nbyellow=0;
    nbgreen=1;
    }
    if(s==62+d)//东西绿灯南北红灯的显示
    {
      dxlv_nbhong();
    }
    if(s==63+d)//东西红灯南北绿灯的显示
    {
      dxhong_nblv();
    }
    if(s==64+d)//禁止时led的显示
    {
          dxred=0;
    dxyellow=1;
    dxgreen=1;
    nbred=0;
    nbyellow=1;
    nbgreen=1;
    }
}
void panduan_hw_nb()//南北红外探头判断
{    
      hw_nanbei();
 if(s==0)
    {
    if(num_che_nb==0) //如果南北方向无车辆通行,表示正常情况
           b=b;    
    else if(num_che_nb<set_time/2)            //如果南北方向小于设定值,通行时间减少
      {
         TR1=0;
            TR0=0;
          b=b-5;
            c=b;
            s=0;
            num=15+c+a;
       num_che_nb=0;
      TR1=1;
            TR0=1;
            if(b==0)
           {
            b=15;
           }
      }
     else               //如果此时南北通行的车辆数大于预设通行量,通行时间增加
         {
            TR1=0;
            TR0=0;
           b=b+5;
            c=b;
            s=0;
            num=15+c+a;
       num_che_nb=0;
           TR1=1;
              TR0=1;
           if(b==35)
             {
             b=15;    
                }                    
          }
    }
}
void panduan_hw_dx()//东西红外探头判断
{
  hw_dongxi();
    if(s==15+c+a)
    {
      if(num_che_dx==0)            //如果东西方向无车辆通行,表示是正常通行量 
          b=b;    
    else if(num_che_dx<set_time/2)            //如果东西方向小于设定值,通行时间减少
        {
            TR1=0;
            TR0=0;
          b=b+5;
            c=b;
            s=15+c+a;
            num=45+d-c-a;    
             num_che_nb=0;
             TR1=1;
            TR0=1;
            if(b==35)
            {
            b=15;
                }
          }
       else           //如果此时东西通行的车辆数大于预设通行量,通行时间增加            
         {
             TR1=0;
            TR0=0;
           b=b-5;
            c=b;
            s=15+c+a;
            num=45+d-c-a;    
             num_che_dx=0;
           TR1=1;
            TR0=1;
             if(b==0)
           {
            b=15;
           }
         }
   }         
}
void panduan_hw()//红外探头判断函数
{
    panduan_hw_dx();//东西方向
 panduan_hw_nb();//南北方向
}
void key_z()//按键增
{
    if(key_zeng==0)
    {
    delay(10);
        if(key_zeng==0)
        {
            TR1=0;
            TR0=0;
          a=a+5;
            if(a==35)
             {
                a=0;
             }
            d=a*2;
            s=0;
            num=15+c+a;
            while(!key_zeng);
            TR1=1;
            TR0=1;
            
        }
        
    }
}

void key_j()//按键减
{
  if(key_jian==0)
    {
     delay(10);
        if(key_jian==0)
        {
            TR1=0;
            TR0=0;
           a=a-5;
            if(a==-20)
            {
             a=0;
          }
            d=a*2;
            s=0;
            num=15+c+a;
            while(!key_jian);
            TR1=1;
            TR0=1;
            
        }
        
    }
}
void key_n()//按键晚上
{
  if(key_night==0)
    {
      delay(10);
        if(key_night==0)
        {
            TR1=0;
            TR0=0;
          s=61+d;
            e=99;
            while(!key_night);
        }
    }
}
void key_jz()//按键禁止
{
    if(key_jinzhi==0)
    {
  delay(10);
        if(key_jinzhi==0)
        {
         TR1=0;
            TR0=0;
          s=64+d;
            e=99;
            while(!key_jinzhi);
        }
    } 
}
void key_nbgreen()//按键东西红灯南北绿灯
{
  if(key_dxred_nbgreen==0)
    {
      delay(10);
        if(key_dxred_nbgreen==0)
        {
         TR1=0;
            TR0=0;
          s=63+d;
            e=99;
            while(!key_dxred_nbgreen);
        }
    }
}
void key_dxgreen()//按键东西绿灯南北红灯
{
 if(key_dxgreen_nbred==0)
 {
     TR1=0;
            TR0=0;
          s=62+d;
            e=99;
     while(key_dxgreen_nbred);
 }
}
void key()//按键函数,按下按键跳转至函数
{
  
    key_z();
    key_j();
    key_n();
    key_jz();
     key_nbgreen();
    key_dxgreen();

 }


void display_led()//红路灯显示
{    
    
 if(s<10+c+a)
     dxhong_nblv();
    
 else if(s<15+c+a)
    
     dxhuang_nblv();
    
 else if(s<55+d)
     
      dxlv_nbhong();
 else if(s<60+d)

     dxlv_nbhuang();
 else 
      led_panduan();
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能           : 向LCD写入一个字节的命令
* 输    入         : u8com
* 输    出         : 无
*******************************************************************************/
void lcd_wri_com(unsigned char com)      //写入命令
{
    E = 0;     //使能清零
    RS = 0;     //选择写入命令
    
  dula=0;
    dula=1;
    DB = com;
    dula=0;
    delay(5);

    E = 1;     //写入时序
    delay(5);
    E = 0;
}

/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能           : 向LCD写入一个字节的数据
* 输    入         : u8dat
* 输    出         : 无
*******************************************************************************/

void lcd_wri_data(unsigned char dat)//写入数据
{
    E = 0;      //使能清零
    RS = 1;      //选择写入数据
    dula=0;
    dula=1;
    DB = dat;
    dula=0;
    delay(5);
    E = 1;      //写入时序
    delay(5);
    E = 0;
}
/*******************************************************************************
* 函 数 名         : WriString
* 函数功能           : 刷新屏幕显示
* 输    入         : hang,add,*p
* 输    出         : 无
*******************************************************************************/
void wri_string(unsigned char y,unsigned char x,unsigned char *p)
{
    if(y==1)//如果选择第一行
        lcd_wri_com(0x80+x);//选中地址
    else
        lcd_wri_com(0xc0+x);//选中地址
        while(*p)
        {
            lcd_wri_data(*p);//写入数据
            p++;
        }
}
/*******************************************************************************
* 函 数 名         : lcd_write_char
* 函数功能           :
* 输    入         :
* 输    出         : 无
*******************************************************************************/
void lcd_write_char(unsigned char y, unsigned char x, unsigned char dat) //列x=0~15,行y=0,1
{
    unsigned char temp_l, temp_h;
    if(y==1)//如果选择第一行
        lcd_wri_com(0x80+x);//选中地址
    else
        lcd_wri_com(0xc0+x);//选中地址
    temp_l = dat % 10;
    temp_h = dat / 10;
    lcd_wri_data(temp_h + 0x30);          //convert to ascii
    lcd_wri_data(temp_l + 0x30);
}
/*********************光标控制***********************/
void lcd1602_guanbiao(unsigned char y, unsigned char x,unsigned char on_off)
{
    if(on_off == 1)   //开光标
    {
        if(y==1)//如果选择第一行
        lcd_wri_com(0x80+x);
        else
        lcd_wri_com(0xc0+x);//将光标移动到秒个位
        lcd_wri_com(0x0f);//显示光标并且闪烁
    }
    else
    {
        if(y==1)//如果选择第一行
        lcd_wri_com(0x80+x);
        else
        lcd_wri_com(0xc0+x);//将光标移动到秒个位
        lcd_wri_com(0x0c);   //关光标
    }
}

/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能         : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/
void lcd_init(void)                          //LCD初始化子程序
{
    lcd_wri_com(0x38);//置功能8位双行
    lcd_wri_com(0x0c);//显示开关光标
    lcd_wri_com(0x06);//字符进入模式屏幕不动字符后移
    delay(5);//延时5ms
    lcd_wri_com(0x01);  //清屏
    wri_string(1,0,times);//初始化显示
    wri_string(1,6,date);
    wri_string(2,0,"H:   %RH T:   C ");//初始化显示
}
void DHT11_delay_us(unsigned char n)
{
    while(--n);
}

void DHT11_delay_ms(unsigned int z)
{
   unsigned int i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}

void DHT11_start()
{
   Data=1;
   DHT11_delay_us(2);
   Data=0;
   DHT11_delay_ms(30);   //延时18ms以上
   Data=1;
   DHT11_delay_us(30);
}

unsigned char DHT11_rec_byte()      //接收一个字节
{
   unsigned char i,dat=0;
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {
      while(!Data);   ////等待50us低电平过去
      DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(Data==1)    //数据为1时,使dat加1来接收数据1
         dat+=1;
      while(Data);  //等待数据线拉低
    }
    return dat;
}

void DHT11_receive()      //接收40位的数据
{
    unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
    DHT11_start();
    if(Data==0)
    {
        while(Data==0);   //等待拉高
        DHT11_delay_us(40);  //拉高后延时80us
        R_H=DHT11_rec_byte();    //接收湿度高八位
        R_L=DHT11_rec_byte();    //接收湿度低八位
        T_H=DHT11_rec_byte();    //接收温度高八位
        T_L=DHT11_rec_byte();    //接收温度低八位
        revise=DHT11_rec_byte(); //接收校正位

        DHT11_delay_us(25);    //结束

        if((R_H+R_L+T_H+T_L)==revise)      //校正
        {
            RH=R_H;
            RL=R_L;
            TH=T_H;
            TL=T_L;
        }
        humi_value = RH;
        temp_value = TH;
    }
}
/******************************************************
 ** 函数名:init_all_hardware
 ** 描述  :初始化所有硬件,及其变量参数。
 ** 输入  :无
 ** 输出  :无
 ** 调用  :主程序
 ******************************************************/
void init_all_hardware(void)
{
            
        
        lcd_init();
        lcd_write_char(2,2,humi_value);
        lcd_write_char(2,11,temp_value);
        lcd_wri_com(0xcd);
        lcd_wri_data(0xdf);
        key_value = 20;
        now_window = normal_mode;
    
        curr_menu = 0;
}

void display(uchar numdis)
{
        shi=numdis/10;//把num的除数给十位
        ge=numdis%10;//把num的余数给各位        
  wela=1;//打开位选
    P0=0xaa;//选择数码管的第一个
    wela=0;
    dula=1;//段选打开
    P0=table[shi];
    dula=0;
    P0=0xff;//消影
    delay(7);
    wela=1;
    P0=0x55;//选择数码管第二个
    wela=0;
    dula=1;
    P0=table[ge];
    dula=0;
    P0=0xff;
    delay(7);    

}

void main()//主函数
{
    
  TMOD=0x11;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TH1=(65536-50000)/256;
    TL1=(65536-50000)%256;
    EA=1;
    ET0=1;
    TR0=1;
    ET1=1;
    TR1=1;
    b=15;
    c=15;
    a=0;
    d=0;
    num=15+c+a;
    buzzer=0;
     get_1302(time_1302);//获取时间
     change(); //时间转换
    init_all_hardware();//初始化硬件,
    while(1)
    {
        
            
         key();//判断按键是否被按下
            panduan_hw();//判断车流量
        display_led();    //红绿灯显示
    display(e);//数码管显示
        get_1302(time_1302);//获取时间
         change(); //时间转换
        
    }
}

//DS1302相关函数
/*==========================================
       D S 1 3 0 2  初 始 化
===========================================*/

void init_1302(uchar *time)
{uchar i, add;
 //uchar time_bcd[7];
 add=0x80;//0写入,1读出
 w_1302(0x8e,0x00);
 for(i=0;i<7;i++)
  {w_1302(add,*time);
   add+=2;
   time++;
   }
 w_1302(0x8e,0x80);
}

//===========================
//    读取当前时间
//===========================

void get_1302(uchar time[])
{uchar i;
 uchar add=0x81;
 w_1302(0x8e,0x00);
 for(i=0;i<7;i++)
 { 
   time[i]=r_1302(add); 
   add+=2;
   }
 w_1302(0x8e,0x80);
}    
/*=================================
   DS1302写入一个字节(上升沿有效)
=================================*/

void write_ds1302(uchar dat)
{uchar i;
 datbyte=dat;
 for(i=0;i<8;i++)
 {T_IO=datbyte0;
  T_CLK=1;
  T_CLK=0;
  datbyte=datbyte>>1;
  }
}

/*=======================================
   DS1302读取一个字节(下降沿有效)
=======================================*/

uchar read_ds1302(void)
{uchar i;
 
 for(i=0;i<8;i++)
  {datbyte=datbyte>>1;
   datbyte7=T_IO;
   T_CLK=1;
   T_CLK=0;
   }
 return(datbyte);
}

/*=========================================
         指定位置读取数据
=========================================*/

uchar r_1302(uchar add)
{uchar temp,dat1,dat2;
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 write_ds1302(add);
 temp=read_ds1302();
 T_CLK=1;
 T_RST=0;
 dat1=temp/16;
 dat2=temp%16;
 temp=dat1*10+dat2;
 return(temp);
}

/*==========================================
        指定位置写入数据
==========================================*/

void w_1302(uchar add,uchar dat)
{
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 write_ds1302(add);
 write_ds1302(dat/10<<4|dat%10);
 T_CLK=1;
 T_RST=0;
}
//DS1302数值转换
void change()
{ 
 // 时 间 的 转 换
  times[0]=time_1302[2]/10+'0';
  times[1]=time_1302[2]%10+'0';
  times[2]=':';
  times[3]=time_1302[1]/10+'0';
  times[4]=time_1302[1]%10+'0';
//  times[5]=':';
//  times[6]=time_1302[0]/10+'0';
//  times[7]=time_1302[0]%10+'0';
    times[5]='\0';
  // 日 期 的 转 换
    date[0]='2';
    date[1]='0';
  date[2]=time_1302[6]/10+'0';
  date[3]=time_1302[6]%10+'0';
  date[4]='/';
  date[5]=time_1302[4]/10+'0';
  date[6]=time_1302[4]%10+'0';
  date[7]='/';
  date[8]=time_1302[3]/10+'0';
  date[9]=time_1302[3]%10+'0';
    date[10]='\0';
}

void T0_time() interrupt 1//定时器0
{
  TH0=(65536-50000)/256;        //0.05s=50ms
     TL0=(65536-50000)%256;
     n++;
     if(n==20)
     {n=0;
     s++;
     
         }
}
void T1_time() interrupt 3//定时器1
{
  TH1=(65536-50000)/256;//重装初值
    TL1=(65536-50000)%256;
    num1++;
    if(num1==20)//50x20=1s,到了20次说明1s到了
    {
       num1=0;//把num1清零,重新计数20次
        num--;//每一秒num减一
        if(num==0)//num到达0s
            if(s==15+c+a)
                num=45+d-c-a;
            else
             num=15+c+a;//num重新计数    
            e=num;
            
    }
}