找回密码
 立即注册

QQ登录

只需一步,快速开始

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

悬赏求助!用1602LCD和温度传感器DS18B20设计的温度报警器程序编写求助!

[复制链接]
ID:258271 发表于 2017-12-12 22:46 | 显示全部楼层 |阅读模式
6黑币
编写了程序但是仿真不成功,温度显示不正常而且改变不了温度,三个按钮的功能均没反应!求助大神!

以下是仿真不成功的程序:
#include <reg52.h>
#include<intrins.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
sbit RW = P2^1;          //定义LCD的读、写选择端
sbit RS = P2^0;           //定义LCD的数据、命令选择端
sbit EN = P2^2;                 //定义LCD的使能信号端
sbit DS = P3^3;                 //定义DS18B20的IO口
sbit L=P2^3;                 //绿灯
sbit H=P2^6;                 //红灯
sbit LS=P3^7;                 //蜂鸣器
sbit k1=P1^1;                 //显示64位的ROM
sbit k2=P1^7;                 //显示当前温度
sbit k3=P1^4;                 //显示温度上限及下线,并支持调节
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(750);                         //温度转换时间需要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);
                   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();                         //扫描按键
    }
}


仿真后的图片。。。

仿真后的图片。。。
回复

使用道具 举报

ID:258566 发表于 2017-12-13 14:35 | 显示全部楼层
  1. int gettmpvalue(void)
  2. {
  3.         uchar tempL, tempH;
  4.         int sdate;
  5.         bit fg = 0;
  6.         sendchangecmd();
  7.         sendreadcmd();
  8.         tempL = readbyte();        //读取低八位
  9.         tempH = readbyte();        //读取高八位
  10.         if (tempH >= 0xf8)
  11.         {  fg=1;
  12.        
  13.                 if (tempL == 0)
  14.                 {   
  15.                         tempH = (~tempH + 1);
  16.                         sdate = tempH * 16;         

  17.                 }
  18.                 else
  19.                 {

  20.                         tempH = ~tempH;
  21.                         tempL = ~tempL + 1;
  22.                         sdate = tempH * 16 + tempL / 16;

  23.                 }
  24.         }
  25.         else
  26.                 sdate = tempH * 16 + tempL / 16;

  27.         if (fg)
  28.                 return -sdate*100;
  29.    else
  30.         return sdate*100;

  31. }
复制代码

hex.zip (2.21 KB, 下载次数: 47)
回复

使用道具 举报

ID:111634 发表于 2017-12-13 17:04 | 显示全部楼层
本帖最后由 zl2168 于 2017-12-13 17:07 编辑

实例97  一线式DS18B20测温
⒈ DS18B20简介
⑴ 内部组织结构    …
⑵ 操作步骤和操作指令    …
⒉ 电路设计    …
⒊ 程序设计    …
⒋ Keil调试    …
⒌ Proteus仿真    …
Proteus仿真一下,确认有效。
实例97 DS18B20测温.rar (51.78 KB, 下载次数: 26)
回复

使用道具 举报

ID:258271 发表于 2017-12-13 20:18 | 显示全部楼层

可以提供一下完整的程序代码吗哈哈哈!这一段我不知道是加在哪里的呢
回复

使用道具 举报

ID:258566 发表于 2017-12-14 15:03 | 显示全部楼层
山不转水转 发表于 2017-12-13 20:18
可以提供一下完整的程序代码吗哈哈哈!这一段我不知道是加在哪里的呢

就是同名函数,把原函数删除,替换下。温度就显示正常了
回复

使用道具 举报

ID:437321 发表于 2018-12-1 19:57 来自手机 | 显示全部楼层
同学,你好,你这程序是错的啊
回复

使用道具 举报

ID:437321 发表于 2018-12-1 19:58 来自手机 | 显示全部楼层
山不转水转 发表于 2017-12-13 20:18
**** 作者被禁止或删除 内容自动屏蔽 ****

同学。你这程序是错的吧?我运行了一下,错误一大推
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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