找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2935|回复: 6
收起左侧

单片机超声波测距仿真为什么LCD1602只亮却没有显示?

[复制链接]
ID:899677 发表于 2021-5-4 22:47 | 显示全部楼层 |阅读模式
50黑币
原理图和程序是买实物时送的,但我照原理图搭了仿真,把hex文件导进去LCD没有显示,大哥们这是为啥?这是单片机程序:
#include <REG52.H>      //器件配置文件
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit  RX = P2^1;
sbit  TX = P2^0;

sbit LCM_RW = P2^6; //定义LCD引脚
sbit LCM_RS = P2^5;
sbit LCM_E   =P2^7;
#define LCM_Data  P0

sbit K1= P3^2; //定义Keyboard引脚
sbit K2= P3^3;
uchar Slong=30;   // 报警距离值    如果需要修改报警距离,则改此处数值就可。
sbit speak=P1^7;   //蜂鸣器报警的口线定义

#define Busy    0x80 //用于检测LCM状态字中的Busy标识

void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);

unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
unsigned char code juli[] ={"The distance is"};
unsigned char code kaiji[] = {"             "};

unsigned char code ASCII[15] =  {'0','1','2','3','4','5','6','7','8','9','.','-','M','S'};

static unsigned char DisNum = 0; //显示用指针               
unsigned int  time=0;
unsigned char  timer=0;
unsigned char pinlv=0;
unsigned char cishu=0;
unsigned long S=0;
bit      flag =0;
bit  flag_one=0;
bit  flag_two=0;
unsigned char disbuff[4]={ 0,0,0,0,};


#include "eeprom52.h"

void delayms(unsigned int ms)
{
   unsigned char i=100,j;
   for(;ms;ms--)
   {
       while(--i)
       {
          j=10;
          while(--j);
       }
   }
}

/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
   SectorErase(0x2000);
   byte_write(0x2001, Slong);
   byte_write(0x2060, a_a);
}

/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{

   Slong = byte_read(0x2001);
   a_a      = byte_read(0x2060);
}

/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
   read_eeprom();       //先读
   if(a_a != 2)      //新的单片机初始单片机内问eeprom
   {
       Slong = 30;
       a_a = 2;
       write_eeprom();
   }  
}



//写数据
void WriteDataLCM(unsigned char WDLCM)
{
   ReadStatusLCM(); //检测忙
   LCM_Data = WDLCM;
   LCM_RS = 1;
   LCM_RW = 0;
   LCM_E = 0; //若晶振速度太高可以在这后加小的延时
   LCM_E = 0; //延时
   LCM_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
   if (BuysC) ReadStatusLCM(); //根据需要检测忙
   LCM_Data = WCLCM;
   LCM_RS = 0;
   LCM_RW = 0;  
   LCM_E = 0;
   LCM_E = 0;
   LCM_E = 1;
}

//读数据
unsigned char ReadDataLCM(void)
{
   LCM_RS = 1;
   LCM_RW = 1;
   LCM_E = 0;
   LCM_E = 0;
   LCM_E = 1;
   return(LCM_Data);
}

//读状态
unsigned char ReadStatusLCM(void)
{
   LCM_Data = 0xFF;
   LCM_RS = 0;
   LCM_RW = 1;
   LCM_E = 0;
   LCM_E = 0;
   LCM_E = 1;
   while (LCM_Data & Busy); //检测忙信号
   return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{

    WriteCommandLCM(0x38);//设置模式
   WriteCommandLCM(0x0c);//不显示光标
   WriteCommandLCM(0x06);//设置指针自加
   WriteCommandLCM(0x01);//清屏
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
   Y &= 0x1;
   X &= 0xF; //限制X不能大于15,Y不能大于1
   if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
   X |= 0x80; //算出指令码
   WriteCommandLCM(X, 1); //发命令字
   WriteDataLCM(DData); //发数据
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
   unsigned char ListLength;

  ListLength = 0;
   Y &= 0x1;
   X &= 0xF; //限制X不能大于15,Y不能大于1
   while (DData[ListLength]>0x19) //若到达字串尾则退出
       {
          if (X <= 0xF) //X坐标应小于0xF
              {
                  DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
                 ListLength++;
                 X++;
              }
       }
}

//5ms延时
void Delay5Ms(void)
{
   unsigned int TempCyc = 5552;
   while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
   unsigned char TempCycA = 5;
   unsigned int TempCycB;
   while(TempCycA--)
       {
          TempCycB=7269;
          while(TempCycB--);
       };
}


void key()
{
      if(!K1)            //按下按键
          {
                delayms(5);       //延时去抖
                if(!K1)
                 {
                   Slong+=1;       //每按下一次,数值加10
                      write_eeprom();       //保存数据
                      flag_one=0;
           }
                 while(!K1);      //等待按键弹起
           }


            if(!K2)            //按下按键
          {
                delayms(5);       //延时去抖
                if(!K2)
                 {
                   Slong-=1;       //每按下一次,数值加10
                      write_eeprom();       //保存数据
                      flag_one=0;
           }
                 while(!K2);      //等待按键 弹起
           }


            if(flag_one==0)
              {
                 flag_one=1;
                 disbuff[0]=Slong%1000/100;
           disbuff[1]=Slong%1000%100/10;
           disbuff[2]=Slong%1000%10 %10;
                 DisplayOneChar(9, 1, ASCII[13]);    //显示S
                 DisplayOneChar(10, 1, ':'); //显示M
           DisplayOneChar(11, 1, ASCII[disbuff[0]]);
           DisplayOneChar(12, 1, ASCII[10]); //显示点
           DisplayOneChar(13, 1, ASCII[disbuff[1]]);
           DisplayOneChar(14, 1, ASCII[disbuff[2]]);
           DisplayOneChar(15, 1, ASCII[12]); //显示M

        }

}



warn()                //报警函数
   {
     if( S>Slong*4/5 && S<=Slong*5/5 )     //当距离小于等于设定的报警值时
        {
        pinlv=1;     //蜂咛器报警等级
     }

         if( S>Slong*3/5 && S<=Slong*4/5 )     //当距离小于等于设定的报警值时
        {
        pinlv=2;     //蜂咛器报警等级
     }

          if( S>Slong*2/5 && S<=Slong*3/5 )     //当距离小于等于设定的报警值时
        {
        pinlv=3;     //蜂咛器报警等级
     }

          if( S>Slong*1/5 && S<=Slong*2/5 )     //当距离小于等于设定的报警值时
        {
        pinlv=4;     //蜂咛器报警等级
     }

          if(  S<=Slong*1/5 )     //当距离小于等于设定的报警值时
        {
        pinlv=5;     //蜂咛器报警等级
     }

         if(S>Slong)       //当距离大于设定的报警值时
        {
        pinlv=0;     // 蜂咛器不报警。
     }
  }


/********************************************************/
void Conut(void)
   {
    time=TH0*256+TL0;
    TH0=0;
    TL0=0;

    S=(time*1.7)/100;     //算出来是CM
    if((S>=700)||flag==1) //超出测量范围显示“-”
    {
     flag=0;

     DisplayOneChar(0, 1, ASCII[11]);
     DisplayOneChar(1, 1, ASCII[10]); //显示点
     DisplayOneChar(2, 1, ASCII[11]);
     DisplayOneChar(3, 1, ASCII[11]);
     DisplayOneChar(4, 1, ASCII[12]); //显示M
    }
    else
    {
     disbuff[0]=S%1000/100;
     disbuff[1]=S%1000%100/10;
     disbuff[2]=S%1000%10 %10;
     DisplayOneChar(0, 1, ASCII[disbuff[0]]);
     DisplayOneChar(1, 1, ASCII[10]); //显示点
     DisplayOneChar(2, 1, ASCII[disbuff[1]]);
     DisplayOneChar(3, 1, ASCII[disbuff[2]]);
     DisplayOneChar(4, 1, ASCII[12]); //显示M
    }
   }
/********************************************************/
void zd0() interrupt 1       //T0中断用来计数器溢出,超过测距范围
  {
    flag=1;                        //中断溢出标志
  }
/********************************************************/
void  StartModule()              //启动模块
  {
     TX=1;                                //启动一次模块
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     TX=0;
  }
/********************************************************/









/*********************************************************/
void main(void)
{

   unsigned char TempCyc;
   Delay400Ms(); //启动等待,等LCM讲入工作状态
   LCMInit(); //LCM初始化
   Delay5Ms(); //延时片刻(可不要)
   DisplayListChar(0, 0, juli);
   DisplayListChar(0, 1, kaiji);
   //ReadDataLCM();//测试用句无意义
   //for (TempCyc=0; TempCyc<10; TempCyc++)
   Delay400Ms(); //延时
   init_eeprom();              //读eeprom数据
   while(1)
   {
     TMOD=0x11;         //设T0为方式1,GATE=1;
   TH0=0;
   TL0=0;         
   TH1=0xf8;        //2MS定时
   TL1=0x30;
   ET0=1;             //允许T0中断
   ET1=1;           //允许T1中断
   TR1=1;           //开启定时器
   EA=1;            //开启总中断  

   while(1)
     {
          key();
          if(flag_two==0)
          {
           flag_two=1;
        StartModule();
       while(!RX);      //当RX为零时等待
        TR0=1;              //开启计数
        while(RX);          //当RX为1计数并等待
        TR0=0;              //关闭计数
       Conut();         //计算
          warn();
          }
   }
   }
}




void  zd3()  interrupt 3       //
  {
    TH1=0x3c;
    TL1=0xb0;
    cishu++;
    timer++;
   if(timer>=10) //500ms刷新一次
    {
      flag_two=0;
    }

    if(pinlv==0)  { speak=1; }

    if(pinlv==1)
    {
      if(cishu>=5)
             {
                  cishu=0;
           speak=~speak;
         }
    }

       if(pinlv==2)
    {
      if(cishu>=4)
             {
                  cishu=0;
           speak=~speak;
         }
    }

       if(pinlv==3)
    {
      if(cishu>=3)
             {
                   cishu=0;
           speak=~speak;
         }
    }

       if(pinlv==4)
    {
      if(cishu>=2)
             {
                  cishu=0;
           speak=~speak;
         }
    }


       if(pinlv==5)
    {
      if(cishu>=1)
             {
                  cishu=0;
           speak=~speak;
         }
    }


  }





仿真

仿真

原理图

原理图
回复

使用道具 举报

ID:96682 发表于 2021-5-5 02:31 来自手机 | 显示全部楼层
这仿真 P0 未接上拉排阻
回复

使用道具 举报

ID:390416 发表于 2021-5-5 09:08 | 显示全部楼层
关于超声波和LCD1602的结合  去这里下载 链接:https://pan.baidu.com/s/1GNJywOm2PXB_lEb1Vy3qaQ
提取码:1234
回复

使用道具 举报

ID:390416 发表于 2021-5-5 09:15 | 显示全部楼层
还有这个 LCD1602必须遵循比较严格的时间要求
http://www.51hei.com/bbs/dpj-205768-1.html
回复

使用道具 举报

ID:899677 发表于 2021-5-5 10:54 | 显示全部楼层
wc86110 发表于 2021-5-5 02:31
这仿真 P0 未接上拉排阻

我去接了,但是好像还是没有显示
回复

使用道具 举报

ID:904364 发表于 2021-5-5 18:04 | 显示全部楼层
vee引脚可调电阻的另一端接地试试
回复

使用道具 举报

ID:899677 发表于 2021-5-6 12:10 | 显示全部楼层
加了排阻,也把vee接地了,但是还是没啥用,仿真和程序都发上来了

仿真.zip

127.71 KB, 下载次数: 11

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表