找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3709|回复: 4
收起左侧

学习做的DS18b20+LCD1602温度显示器,设计出来只亮背光灯,不出结果

[复制链接]
ID:269727 发表于 2018-1-1 14:01 | 显示全部楼层 |阅读模式
求位大神帮忙看看是哪里错了,按照这个电路图做出来的板子接上电源后,1602只有一个背光灯亮,在proteus上仿真也是这种情况,LCD只有一个背光灯亮,附上程序

#include <AT89X52.h>       //调用51单片机的头文件
#include <Intrins.h>  
//---------------------------------------
//1602液晶相关I/O设置
sbit E=P2^2;               //1602液晶的E脚接在P2.2口上
sbit RW=P2^1;              //1602液晶的RW脚接在P2.1口上
sbit RS=P2^0;              //1602液晶的RS脚接在P2.0口上
//---------------------------------------
sbit ds18b20=P3^7;       
//---------------------------------------
//1602液晶寄存器设置
unsigned char DISbuf;     //设置8位的unsigend char型寄存器用来暂存1602要显示的内容
//---------------------------------------          
unsigned char temp1;
unsigned char temp2;
unsigned char code table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};

void Delay(unsigned int nTimeDelay)
{
    unsigned int i;
    while (nTimeDelay--)
        for (i=0;i<125;i++);
}

bit Reset(void)
{
        unsigned int i;
   bit k;
   ds18b20=0;                             //拉低DQ总线开始复位       
   i=200;                                             //保持DQ低大约870uS,符合不低于48US的要求
   while(i>0)                             //保持DQ低大约870uS,符合不低于48US的要求
       i--;                               //保持DQ低大约870uS,符合不低于48US的要求            
   ds18b20=1;                             //拉高准备接收数据   
   i=18;                                            //大约80uS后
   while(i>0)                                    //大约80uS后
       i--;                                      //大约80uS后
   k=ds18b20;                               //读出数据并保存   
   i=91;                                                    //维持约400US,符合总读时隙不低于480US的要求
   while(i>0)                                    //维持约400US,符合总读时隙不低于480US的要求
       i--;                                      //维持约400US,符合总读时隙不低于480US的要求
   return k;               //k=0为复位成功,k=1为复位失败
}

unsigned char ReadByte(void)
{
        unsigned int i;
   unsigned char j,buf=0;
   for(j=0;j<8;j++)                        //接收8次还原一个字节数据
   {
                buf=buf>>1;                          //接收前,想将接收缓冲区右移
                ds18b20=0;                                 //拉低      
      _nop_();                       //维持2US,符合大于1US小于15US的规范
      _nop_();                       //维持2US,符合大于1US小于15US的规范
      _nop_();                       //维持2US,符合大于1US小于15US的规范
           _nop_();                       //维持2US,符合大于1US小于15US的规范
      ds18b20=1;                                  //拉高,为读数据做准备
                _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
           _nop_();                       //维持6US,符合大于1US小于15US的规范
                _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
           _nop_();                       //维持6US,符合大于1US小于15US的规范
                _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
      _nop_();                       //维持6US,符合大于1US小于15US的规范
           _nop_();                       //维持6US,符合大于1US小于15US的规范
                if(ds18b20==1) buf|=0x80;  //读出1位数据保存于buf中
                i=12;                                          //维持约52US,符合总读时隙不低于60US的要求
      while(i>0)                          //维持约52US,符合总读时隙不低于60US的要求
              i--;                             //维持约52US,符合总读时隙不低于60US的要求
        }
   return buf;             //退出的同时将接收缓冲区参数返回
}


void WriteByte(unsigned char dat)
{
        unsigned int i;
   unsigned char j;
   for(j=0;j<8;j++)
   {            
                if(dat&0x01)                        //如果写1
      {      
                   ds18b20=0;                         //拉低      
         _nop_();               //维持2US,符合大于1US小于15US的规范
         _nop_();               //维持2US,符合大于1US小于15US的规范
         _nop_();               //维持2US,符合大于1US小于15US的规范
                    _nop_();               //维持2US,符合大于1US小于15US的规范
         ds18b20=1;                          //拉高        
         i=14;                                  //维持约63US,符合不低于60US的要求
         while(i>0)                  //维持约63US,符合不低于60US的要求
                 i--;                     //维持约63US,符合不低于60US的要求
                }
      else                                                //如果写0
      {            
                        ds18b20=0;                         //拉低                 
         i=14;                                        //维持约63US,符合不低于60US的要求
         while(i>0)                        //维持约63US,符合不低于60US的要求
                 i--;                            //维持约63US,符合不低于60US的要求        
         ds18b20=1;                         //拉高                
         _nop_();               //维持2US,符合大于1US的规范
         _nop_();               //维持2US,符合大于1US的规范
         _nop_();               //维持2US,符合大于1US的规范
                    _nop_();               //维持2US,符合大于1US的规范
      }
                dat=dat>>1;                                //写入字节右移1位
        }
}


bit Convert(void)
{   
        if(Reset()==0)          //复位DS18B20
        {               
            WriteByte(0xcc);                //写入跳过序列号命令字 Skip Rom
      WriteByte(0x44);                //写入温度转换命令字 Convert T  
                  return 1;            //启动温度转换成功
        }
        else
        {          
                  return 0;            //启动温度转换失败
        }
}


void ReadFlash(void)
{   
        unsigned char Lsb,Msb;       
   if(Reset()==0)          //复位DS18B20
        {
      WriteByte(0xcc);                //写入跳过序列号命令字 Skip Rom
      WriteByte(0xbe);                //写入读取数据令字 Read Scratchpad
      Lsb=ReadByte();                //读出第一个字节暂存于LSB
      Msb=ReadByte();                //读出第二个字节暂存于MSB       
                  temp1=Lsb&0x0f;                //temp1内装温度参数的小数部分
      temp2=(Lsb>>4)|(Msb<<4);//temp2内装温度参数的整数部分          
        }       
        else
        {
                temp1=0;                                        //如果复位失败,温度参数清零
      temp2=0;                                        //如果复位失败,温度参数清零       
        }
}

void LCD1602_busy(void)
{
     P0_7=1;              //将P0.7置1,为读状态做准备
     RS=0;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
     RW=1;                //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
     E=1;                 //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
     while(P0_7==1);      //由P0.7读入1,表示1602液晶忙,需要等待
     E=0;                 //读完以后,恢复E的电平
}

void LCD1602_Write_com(unsigned char combuf)
{
     RS=0;                //选择指令寄存器
     RW=0;                //选择写状态
     P0=combuf;           //将命令字通过P0口送至DB
     E=1;                 //E高电平将命令字写入1602液晶
     E=0;                 //写完以后,恢复E的电平
}

void LCD1602_Write_com_busy(unsigned char combuf)
{
     LCD1602_busy();            //调用忙检测函数
     LCD1602_Write_com(combuf); //调用忙检测函数
}


void LCD1602_Write_data_busy(unsigned char databuf)
{
     LCD1602_busy();      //调用忙检测函数
     RS=1;                //选择数据寄存器
     RW=0;                //选择写状态
     P0=databuf;          //将命令字通过P0口送至DB
     E=1;                 //E高电平将命令字写入1602液晶
     E=0;                 //写完以后,恢复E的电平
}


void LCD1602_Write_address(unsigned char x,unsigned char y)
{
     x&=0x0f;             //列地址限制在0-15间
     y&=0x01;             //行地址限制在0-1间
     if(y==0)             //如果是第一行
         LCD1602_Write_com_busy(x|0x80);        //将列地址写入
     else                 //如果是第二行
         LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
}


void LCD1602_init(void)
{
     Delay(150);               //调用延时函数
     LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
     Delay(50);                //调用延时函数
     LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
     Delay(50);                //调用延时函数
     LCD1602_Write_com(0x38);       //8位数据总线,两行显示模式,5*7点阵显示
     LCD1602_Write_com_busy(0x38);  //8位数据总线,两行显示模式,5*7点阵显示
     LCD1602_Write_com_busy(0x08);  //显示功能关,无光标
     LCD1602_Write_com_busy(0x01);  //清屏
     LCD1602_Write_com_busy(0x06);  //写入新的数据后,光标右移,显示屏不移动
     LCD1602_Write_com_busy(0x0C);  //显示功能开,无光标
}


void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
{
     LCD1602_Write_address(x,y);    //先将地址信息写入
     LCD1602_Write_data_busy(buf);  //再写入要显示的数据
}


void main(void)            //主函数,单片机开机后就是从这个函数开始运行
{
   LCD1602_init();        //调用1602液晶初始化函数
   while(1)               //死循环,单片机初始化后,将一直运行这个死循环
   {
      if(Convert()==1)                                                 //启动转换
                {             
                    ReadFlash();                       //读取温度                           
         if(temp2>99) temp2=99;                         
                         if(temp1>15) temp1=0;                                                 
                        LCD1602_Disp(0,0,temp2/10+'0');  //温度整数部分十位                               
                   LCD1602_Disp(1,0,temp2%10+'0');  //温度整数部分个位
                        LCD1602_Disp(2,0,'.');  //.               
                        LCD1602_Disp(3,0,table[temp1]+'0');  //温度小数部分
                        LCD1602_Disp(4,0,0xdf);   //.
                        LCD1602_Disp(5,0,0x43);   //C                                                                 
            }   
    }
}


P6WM$}8M%JPHGHR4IWH[JKP.png
P6%PQP4)4EUI2UPRU56W3`L.png
HQF(JP4%SGVGJUQ3F4D(0ZG.png
回复

使用道具 举报

ID:82765 发表于 2018-1-1 17:56 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

ID:261000 发表于 2018-1-1 21:29 | 显示全部楼层
楼主如果是初学,建议程序分段调试。避免错误判断,提高效率,和成功率
回复

使用道具 举报

ID:126608 发表于 2018-1-2 06:39 | 显示全部楼层
先测量晶振两脚电压是否2.5v3.5v左右,如果是,硬件没问题。
回复

使用道具 举报

ID:269976 发表于 2018-1-2 08:56 | 显示全部楼层
从LCD1602_init函数先调试一下吧,慢慢来
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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