单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4146|回复: 5
收起左侧

单片机+ds18b20的lcd1602显示带详细注释的源码

[复制链接]
承蒙時光不棄 发表于 2018-4-17 14:54 | 显示全部楼层 |阅读模式
#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sbit DQ=P3^7;     //ds18b20
与单片机连接口
sbit RS=P3^0;     //1602写数据/写命令选择端口
                 //RS=1写数据,即要显示的内容
                 //RS=0写命令,即一些LCD设置命令
sbit RW=P3^1;     //1602读/写选择端,RW=0为写模式
sbit EN=P3^2;     //给EN一个高脉冲,将数据送入液晶控制器,完成写操作
uchar code str1[]={"^_^   Zhang Chao"};
uchar code str2[]={"    T=          "};
uchar data disdata[5];//百、十、个、小数位
uint tvalue;       //温度值
uchar tflag;      //温度正负标志
/*************************lcd1602设置子函数*******************************************************************/
void delay1ms(uint ms) //延时1毫秒子函数,形参为ms(不够精确的)
{
unsigned int i,j;
      for(i=0;i<ms;i++)
       for(j=0;j<110;j++);
}
void wr_com(uchar com)//lcd
写控制指令子函数,形参为com
{
    delay1ms(1);     //调用延时子函数,并用实参1代替延时子函数中的形参ms
    RS=0;            //RS=0进入写命令状态,即一些LCD设置命令
    RW=0;            //RW=0为写模式
    EN=0;           //EN=0时不能完成写操作
    P2=com;          //把要设置的指令码com送给P2口
    delay1ms(1);
    EN=1;            //给EN一个高脉冲,将数据送入液晶控制器,完成写操作
    delay1ms(1);
    EN=0;            //EN=0时不能完成写操作
}
void wr_dat(uchar dat)//lcd写显示数据子函数,形参为dat
{
    delay1ms(1);
    RS=1;           //RS=1
进入写数据状态,即要显示的内容
    RW=0;           //RW=0为写模式
    EN=0;           //EN=0时不能完成写操作
    P2=dat;         //把要显示的数据dat送给P2口
    delay1ms(1);
    EN=1;           //给EN一个高脉冲,将数据送入液晶控制器,完成写操作
    delay1ms(1);
    EN=0;          //EN=0时不能完成写操作
}
void lcd_init()    //lcd初始化设置子函数,不带参数,0x38是显示模式设置,其余是显示开/关及光标设置,无顺序
{
    delay1ms(15);
    wr_com(0x38); //调用写控制指令子函数,并用实参"0011 1000"代替形参com
                   //0x38表示设置为16*2显示,每个块为5*7点阵,8位数据接口
    delay1ms(5);
wr_com(0x08); //调用写控制指令子函数,并用实参"0000 1000"代替形参com
                   //0x08表示设置为关显示、不显示光标、光标不闪烁
    delay1ms(5);
    wr_com(0x01); //调用写控制指令子函数,并用实参"0000 0001"代替形参com
                //0x01表示显示数据清屏(数据指针清0,所有显示清0)
    delay1ms(5);
    wr_com(0x06);//调用写控制指令子函数,并用实参"0000 0110"代替形参com
                //0x06表示当读或写一个字符后地址指针加1,且光标加1;当写一个字符时,整屏显示不移动
    delay1ms(5);
    wr_com(0x0c);//调用写控制指令子函数,并用实参"0000 1100"代替形参com
                  //0x0c打开显示、不显示光标、光标不闪烁
    delay1ms(5);
}
void display(uchar *p)//lcd显示字符串子函数
{
    while(*p!='\0')  //测试是否等于'\0',即判断是否结尾
    {
wr_dat(*p);  //显示指针所指的字符串
        p++;         //指针加1
        delay1ms(1);
    }
}
init_play()//初始化显示子函数
{
    lcd_init();   //调用lcd初始化设置子函数,对LCD进行初始化
    wr_com(0x80);  //调用写控制指令子函数,并用实参"1000 0000"代替形参com
                   //并将数据指针定位到第一行第一个字符处
    display(str1);//从第一行第一个字符处显示字符串str1
    wr_com(0x80+0x40);//调用写控制指令子函数,并用实参"1000 0000"代替形参com
                   //并将数据指针定位到第二行第一个字符处   
    display(str2); //从第二行第一个字符处显示字符串str2
}
/**************************************************************************************************************/
/******************************ds18b20程序******************************************************************/
void delay_18b20(uint i)//延时1微秒
{
    while(i--);
}
void ds18b20rst()  //ds18b20初始化子函数
                   //要求"数据线拉高-延时-数据线拉低-延时大于480微妙-数据线拉高-延时等待"                     
{
    uchar x=0;
    DQ = 1;      //信号线DQ复位
    delay_18b20(4); //延时
    DQ = 0;      //DQ拉低
    delay_18b20(100); //精确延时大于480us
    DQ = 1;      //拉高
    delay_18b20(40);
}
void ds18b20wr(uchar wdata)/*写数据子函数,无返回值,含参数*/
{
      uchar i=0;
     for (i=8; i>0; i--)//
要写完一个字节,故需要重复8次以下操作
     {
      DQ = 0;         //数据线拉低
      DQ = wdata&0x01;//wdata是一个形参,将其与0000 0001进行按位与
                      //按从低到高的顺序发送数据(一次发送一位)
      delay_18b20(10);
      DQ = 1;        //最后将数据线拉高
      wdata>>=1;     //将wdata右移1位
     }
}
uchar ds18b20rd()    //读数据子函数,是有返回值dat
{
    uchar i=0;
    uchar dat = 0;
    for (i=8;i>0;i--)//要读完一个字节,故需要重复8次以下操作
     {
DQ = 0;     //给脉冲信号
        dat>>=1;
        DQ = 1;     //给脉冲信号
        if(DQ)
        dat|=0x80;
        delay_18b20(10);
     }
    return(dat);    //返回dat
}
read_temp()         //读取温度值并转换的子函数,有返回值温度值tvalue
{
    uchar a,b;
    ds18b20rst();  //调用ds18b20初始化子函数
    ds18b20wr(0xcc);//调用写数据子函数,向ds18b20写命令0xcc
                    //ccH表示跳过ROM读序列号,适用于单机工作,直接向18b20发送温度变换命令
    ds18b20wr(0x44);//调用写数据子函数,向ds18b20写命令0x44
//44H表示启动ds18b20温度转换,结果自行存入9字节的RAM中
    ds18b20rst();   //调用ds18b20初始化子函数
    ds18b20wr(0xcc);//同上
    ds18b20wr(0xbe);//调用写数据子函数,向ds18b20写命令0xbe
                    //beH表示读取RAM中9字节的温度数据
    a=ds18b20rd(); //调用读数据子函数,并将所得数据给a
    b=ds18b20rd(); //
    tvalue=b;      //把b的值给tvalue
    tvalue<<=8;    //tvalue左移8位
    tvalue=tvalue|a;//tvalue与a进行按位或
    if(tvalue<0x0fff)//
      tflag=0;      //前五位为0时,读取的温度为正,标志位为0,此时只要
                    //将测得数值乘以0.0625即可得到实际温度
    else            //前五位为1时,读取的温度为负,标志位为1,此时需要
    {              //将测得数值取反后再加1,再乘以0.0625即可得到实际温度
       tvalue=~tvalue+1;
          tflag=1;     //此时表示负温度
}
    tvalue=tvalue*(0.625);//
温度值扩大10倍,精确到1位小数
    return(tvalue); //返回温度值
}
/*************************************************************************************************************/
/************************温度值显示**************************************************************************/
void ds18b20disp()//温度值显示
{
    uchar flagdat;
    disdata[0]=tvalue/1000+0x30;    //百位数
    disdata[1]=tvalue%1000/100+0x30;//十位数
    disdata[2]=tvalue%100/10+0x30;  //个位数
    disdata[3]=tvalue%10+0x30;     //小数位
    if(tflag==0)
      flagdat=0x2b;               //正温度显示符号:+
    else
flagdat=0x2d;               //负温度显示负号:-
    if(disdata[0]==0x30)
    {
       disdata[0]=0x20;           //如果百位为0,不显示
        if(disdata[1]==0x30)
         {
            disdata[1]=0x20;     //如果百位为0,十位为0也不显示
         }
    }
    wr_com(0x80+0x46);           //定位数据指针的位置:第二行第六个字符处
    wr_dat(flagdat);             //显示符号位
    wr_com(0x80+0x47);             //定位数据指针的位置:第二行第七个字符处
    wr_dat(disdata[0]);         //显示百位
    wr_com(0x80+0x48);             //定位数据指针的位置:第二行第八个字符处
    wr_dat(disdata[1]);         //显示十位
    wr_com(0x80+0x49);             //定位数据指针的位置:第二行第九个字符处
    wr_dat(disdata[2]);         //显示个位
wr_com(0x80+0x4a);                 //定位数据指针的位置:第二行第十个字符处
    wr_dat(0x2e);               //显示小数点
    wr_com(0x80+0x4b);             //定位数据指针的位置:第二行第十一个字符处
    wr_dat(disdata[3]);         //显示小数位
}
/**************************************************************************************************************/
/********************主程序*********************************************************************************/
void main()
{
    init_play();                //调用lcd初始化显示子函数
    while(1)
    {
        read_temp();          //调用ds18b20读取温度
        ds18b20disp();        //调用温度显示子函数
    }
}


回复

使用道具 举报

欣北想要好好做 发表于 2018-11-19 20:54 | 显示全部楼层
有没有电路仿真图
回复

使用道具 举报

bg4rfb 发表于 2018-11-21 08:58 | 显示全部楼层
谢谢分享,学习了!
回复

使用道具 举报

习惯就好了 发表于 2019-4-16 14:21 | 显示全部楼层
代码有问题 不能用
回复

使用道具 举报

企鹅挠痒 发表于 2019-5-8 09:31 | 显示全部楼层
修改了一下IO地址,proteus仿真完美运行
回复

使用道具 举报

吉吉baby 发表于 2019-5-22 09:15 | 显示全部楼层
1602数据口?
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机教程网

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