找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6152|回复: 9
收起左侧

用1602LCD与DS18B20设计的温度报警器

  [复制链接]
ID:110638 发表于 2016-3-24 21:16 | 显示全部楼层 |阅读模式
#include <reg52.h>
#include<intrins.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
sbit RW = P1^1;          //定义LCD的读、写选择端
sbit RS = P1^0;           //定义LCD的数据、命令选择端
sbit EN = P1^2;                 //定义LCD的使能信号端
sbit DS = P3^5;                 //定义DS18B20的IO口
sbit L=P1^3;                 //绿灯
sbit H=P1^4;                 //红灯
sbit LS=P3^4;                 //蜂鸣器
sbit k1=P2^4;                 //显示64位的ROM
sbit k2=P2^3;                 //显示当前温度
sbit k3=P2^0;                 //显示温度上限及下线,并支持调节
sbit k4=P2^1;                 //        上限加
sbit k5=P2^2;                  //        下限减
uchar k=2;                         //当前温度显示标志位
uchar table0[] = " Current Temp : ";         //当前温度
uchar table1[] = " -- ROM CODE -- ";         //显示DS18B20的ROM
uchar table2[] = "ALARM TEMP Hi Lo";         //显示上下限温度
uchar table3[] = "Hi:    Lo:      ";
uchar table4[] = {0,0,0,0,0,0,0,0};
uchar tempHL[] = { 20, 1};                                 //上下限温度的初始值                                                                                  
void delayms(uint a)     //延时函数
{
    uint i,j;
    for(i = a; i > 0; i--) for(j = 100; j > 0; j--);
}
void writecom(uchar com)  //写地址,也就是显示的数据的位置
{
        RS = 0;                
        P0 = com;
        EN = 1;
        delayms(1);
        EN = 0;
}
void writedata(uchar dat) //写数据,也就是显示的数据
{
        RS = 1;
        P0 = dat;
        EN = 1;
        delayms(1);
        EN = 0;
}
void init()                   //LCD初始化
{
        RW = 0;
        writecom(0x38);          //16*2显示,5*7点阵
        writecom(0x0c);
        writecom(0x06);
        writecom(0x01);   //清除LCD的显示内容
}

void writestring(uchar * str, uchar length)           //写数据的过度函数。length:长度
{
    uchar i;
    for(i = 0; i < length; i++)
    {
         writedata(str[i]);
     }
}
void delay(uint num)        //延时函数
{
  while( --num );
}

DSinit(void)        //初始化ds1820  
{  
     DS= 1;      //DS复位
     delay(8);    //稍做延时
     DS= 0;      //将DS拉低
     delay(90);   //精确延时 大于 480u
     DS= 1;       //拉高总线
     delay(110);
     DS= 1;

}

uchar read_bit(void)     //读一位(bit)
{
uchar i;
DS= 0;                      //将DS拉低开始读时间隙
DS= 1;                         // then return high
for (i=0; i<3; i++);         // 延时15μs
return(DS);                         // 返回 DS线上的电平值
}

uchar readbyte()        // 读一个字节  
{
uchar i = 0;
uchar dat = 0;
for (i=0;i<8;i++)
{                                  // 读取字节,每次读取一个字节
if(read_bit()) dat|=0x01<<i;           // 然后将其左移
    delay(4);
  }
    return (dat);
}

void write_bit(char bitval)       //写一位  
{
DS= 0;                                        // 将DS拉低开始写时间隙
if(bitval==1) DS=1;          // 如果写1,DS返回高电平
delay(5);                                       // 在时间隙内保持电平值,
DS= 1;                      // delay函数每次循环延时16μs,因此delay(5) = 104μs
}       

void writebyte(uchar dat)  //写一个字节
{
  uchar i = 0;
  uchar temp;
   for (i=0; i<8; i++)         // 写入字节, 每次写入一位
   {

   temp = dat>>i;                
   temp &= 0x01;                
   write_bit(temp);

  }
  delay(5);
}         
void sendchangecmd()           //DS18B20?开始获取温度并转换
{
    DSinit();                         //DS18B20复位
    delayms(1);                      
    writebyte(0xcc);           //写跳过读ROM指令
    writebyte(0x44);           //写温度转换指令
}

void sendreadcmd()                   //读取寄存器中存储的温度数据
{
    DSinit();                           //DS18B20复位
    delayms(1);
    writebyte(0xcc);            //写跳过读ROM指令
    writebyte(0xbe);            //读取暂存器的内容
}         

int gettmpvalue()
{
    uint tmpvalue;
    float t;
    uchar low, high;
    sendreadcmd();                   //读取寄存器中存储的温度数据
    low = readbyte();            //读取低八位
    high = readbyte();           //读取高八位
    tmpvalue = high;
    tmpvalue <<= 8;                   //高八位左移八位
    tmpvalue |= low;       //两个字节组合为1个字
    t = tmpvalue * 0.0625 * 100;   //分辨率为0.0625,在此将值扩大100倍
    return t;
}

void display(int v)            //显示子函数
{
    uchar i;
    uchar datas[] = {0, 0, 0, 0, 0, 0, 0, 0};  //定义缓存数组datas
    uint tmp = abs(v);                                                   //abs是求绝对值函数
    datas[0] = tmp % 10000 / 1000;
    datas[1] = tmp % 1000 / 100;
    datas[2] = tmp % 100 / 10;
    datas[3] = tmp % 10;
        datas[4] = 80;                                                //空格的前30的ASCALL码
        datas[5] = 175;                                                //温度符号的前30的ASCALL码
        datas[6] = 19;                                                //C的前30的ASCALL码
    writecom(0xc0+3);
    if(v < 0)                                  //当V小于0则输出负号
    {
        writestring("- ", 2);
   }
    else
    {
       writestring("+ ", 2);          //当V大于0则输出正号
    }
    for(i = 0; i != 7; i++)
    {
        writedata('0'+datas[i]);   //显示温度
        if(i == 1)
        {
           writedata('.');                  //显示温度的小数点
        }
    }

}

void Read_RomCord()                   //读取64位序列码
{
     unsigned char j;
     DSinit();
     writebyte(0x33);      // 读序列码的操作
     for (j = 0; j < 8; j++)
         {
          table4[j] = readbyte();
         }
}

void Disp_RomCode()                           //数据转换与显示
{
   uchar j,i;
   writecom(0xc0);         //LCD第二行初始位置
   for(j=0;j<8;j++)
   {
    i=((table4[j]&0xf0)>>4);
    if(i>9)
     { i=i+0x37;}
    else{i=i+0x30;}         
    writedata(i);        //高位数显示
    i=(table4[j]&0x0f);
    if(i>9)
     {i=i+0x37;}
    else {i=i+0x30;}         
    writedata(i);        //低位数显示
   }
}

void lcd_display()                 //按键扫描
{
  uchar i,m;
  uchar hl[]={0, 0, 0, 0, 0};
  if(k1 == 0) k = 1;
  if(k2 == 0) k = 2;                                                                                                                                                                                          
  if(k3 == 0) k = 3;
  if(tempHL[0]<=gettmpvalue()/100)
       delayms(100),LS=!LS,H=~H;
  else
       LS=1,H=1;
  if(m==1)
{
          if(tempHL[1]>=gettmpvalue()/100)
               delayms(100),LS=!LS,L=~L;
          else
               LS=1,L=1;
  }
  switch(k)
  {
        case 1:                                                       //显示64位的ROM
                   writecom(0x01);
                   writecom(0x80);
                   writestring(table1, 16);
                   Read_RomCord();           //读取64位序列码
                   Disp_RomCode();                 //显示64位序列
           delayms(500);                         //温度转换时间需要750ms以上
                   break;
        case 2:                                                 //显示当前温度
                   delayms(750);                         //温度转换时间需要750ms以上
                   sendchangecmd();
                   writecom(0x01);
                   writecom(0x80);
                   writestring(table0, 16);
                   display(gettmpvalue());
                   break;
        case 3:                                                     //显示温度上限及下线,并支持调节
                   writecom(0x80);
                   writestring(table2, 16);
                   writecom(0xC0);
                   writestring(table3, 16);
                   if(k4==0) {tempHL[0]++;if(m==1) tempHL[1]++;if(m==0){tempHL[1]--;if(tempHL[1]==0)m=1;}delayms(100);}
                   if(k5==0) {tempHL[0]--;if(m==0) tempHL[1]++;if(m==1){tempHL[1]--;if(tempHL[1]==0)m=0;}delayms(100);}
                   hl[0] = tempHL[0] / 10;
                   hl[1] = tempHL[0] % 10;
                   if(m==1) hl[2] = 80;
                   if(m==0) hl[2] = 128;
                   hl[3] = tempHL[1] / 10;
                   hl[4] = tempHL[1] % 10;
                   writecom(0xC0+4);
                   for(i = 0; i != 2; i++)
                    {
                        writedata('0'+hl[i]);        //显示上限温度
                         }
                   writecom(0xC0+11);
                   for(i = 2; i != 5; i++)
                    {
                        writedata('0'+hl[i]);         //显示下限温度
                         }
                   break;
  }
}
void main()
{
        sendchangecmd();                        //读取寄存器中存储的温度数据
    init();                                                //LCD初始化
    writecom(0x80);                                //选择LCD第一行
    writestring(table0, 16);        //显示当前温度的英文字母
    while(1)
    {
        lcd_display();                         //扫描按键
    }
}


评分

参与人数 2黑币 +60 收起 理由
send + 10 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2016-3-27 19:44 | 显示全部楼层
楼主能分享个电路图吗?
回复

使用道具 举报

ID:121641 发表于 2016-5-24 22:33 | 显示全部楼层
楼主棒!我已经仿真好了,坐等焊板子
回复

使用道具 举报

ID:97714 发表于 2016-5-28 09:33 | 显示全部楼层
感谢楼主,正需要这类资料
回复

使用道具 举报

ID:125111 发表于 2016-6-4 20:32 | 显示全部楼层
分地区二姐夫脾气额阀门哦我去
回复

使用道具 举报

ID:184584 发表于 2017-4-19 19:48 | 显示全部楼层
能不能把仿真电路图发一下??
回复

使用道具 举报

ID:184584 发表于 2017-4-19 19:48 | 显示全部楼层
能不能把仿真电路图发一下??
回复

使用道具 举报

ID:170098 发表于 2017-5-16 15:27 | 显示全部楼层
我觉得还是发个图,这样学习起来也比较快
回复

使用道具 举报

ID:830316 发表于 2020-11-6 18:54 | 显示全部楼层
15966025623 发表于 2016-5-28 09:33
感谢楼主,正需要这类资料

求分享一下。谢谢
回复

使用道具 举报

ID:312000 发表于 2020-12-1 10:25 | 显示全部楼层
有没有原理图
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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