找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2624|回复: 6
打印 上一主题 下一主题
收起左侧

本人新手,想做一个ds18b20的温度监测系统

[复制链接]
跳转到指定楼层
楼主
ID:216275 发表于 2017-7-1 09:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于是小白,只能看着大佬框架做出来一部分,但还是不成功呀,模拟电路就是不亮。。。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:149988 发表于 2017-7-1 11:01 | 只看该作者

RE: 本人新手,想做一个ds18b20的温度监测系统

这是经过普中开发板试验正确的程序,很稳定。温度检测用DS18b20,显示用DS1602,1602第一行显示设定温度上限值和下限值,第二行显示检测温度值。独立按键K1接P1.0用以设定温度,K2接P1.1用以设定温度上限值,K3接P1.2用以设定温度下限值。晶振11.0592MHz或12MHz。
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int  
#define uchar unsigned char
sbit IO_18B20=P3^7;  //DS18B20的数据IO口
sbit EN_1602=P2^7;   //1602时序操作:使能
sbit RS_1602=P2^6;   //1602时序操作:读写选择端R/W=L
sbit RW_1602=P2^5;   //1602时序操作:写状态或写数据选择端RS=L
sbit GND=P2^4;
sbit K1=P1^0;   //设置键      
sbit K2=P1^1;   //增加键              
sbit K3=P1^2;   //减少键
sbit buzzer=P1^7;
uchar S1num;//秒、分、时、星期、日、月、年
uchar data Display[5];
uchar tflag;  //温度正负标志
uchar L_ge=2;
char L_shi=2;
uchar H_ge=4;
uchar H_shi=2;
uchar H_bai=0;
uint T_Value;  //温度值
bit keyflag=0;
//void readtime();
void delay(uint z) //延时子程序
{
  uint x,y;
  for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
void delay_18B20(unsigned int i) //18B20延时1微秒
{
  while(i--);
}
/*********************将地址命令和时钟数据传送DS1602***************/
void write_1602dat(uchar dat)  /*时钟数据传送P0*/
{
  RS_1602=1;   //1602的rs为0时,接收命令,为1时接收数据
  P0=dat; //把void write_shu(uchar shu)中的COM中的数据给P0口
  delay(5);
  EN_1602=1;
  delay(5);
  EN_1602=0;
  delay(5);
}
void write_1602com(uchar com)  /*地址命令传送P0*/
{
  RS_1602=0;   //1602的rs为0时,接收命令,为1时接收数据
  P0=com; //把void write_com(uchar com)中的COM中的数据给P0口
  delay(5);
  EN_1602=1;
  delay(5);
  EN_1602=0;
  delay(5);
}
/************************地址和数据过度缓冲函数**********************/
void Write1602(uchar add,uchar dat)  /*写入地址和时钟数据函数*/
{
  write_1602com(add);                //写入地址函数
  write_1602dat(dat);                //写入时钟数据函数
}
/****************************1602初始化*******************************/
void init_1602()  /*定义一个初始化子程序*/
{
  EN_1602=0;
  RW_1602=0;
  write_1602com(0x38); //将0x38赋com,设置显示模式:4位总线、双行显示、显示5x7的点阵字符
  write_1602com(0x0e); //将0x0e赋com,设置光标:开显示、无光标,光标不闪烁
  write_1602com(0x06); //将0x06赋com,写一个数据,指针自动加1,整屏不移动,N=1、S=0
  write_1602com(0x80); //将0x80赋com,设置数据指针起点,第一行左边第一个字符
  write_1602com(0x01); //将0x01赋com,清屏
  Write1602(0x80+0x40+1,(0x54));  //第2行第2位,设定'符号T'
  Write1602(0x80+0x40+2,(0x65));  //第2行第3位,设定'符号e'
  Write1602(0x80+0x40+3,(0x6d));  //第2行第4位,设定'符号m'
  Write1602(0x80+0x40+4,(0x70));  //第2行第5位,设定'符号p'
  Write1602(0x80+0x40+5,':');     //第2行第6位,设定':'
  Write1602(0x80+0x40+13,(0xdf)); //第2行第14位,设定'0'
  Write1602(0x80+0x40+14,'C');    //第2行第15位,设定'C'
  Write1602(0x80,(0x48));    //第1行第1位,设定'H'
  Write1602(0x80+1,':');     //第1行第2位,设定':'
  Write1602(0x80+6,(0xdf));  //第1行第7位,设定'温度符号'
  Write1602(0x80+7,'C');     //第1行第8位,设定'温度符号'
  Write1602(0x80+9,(0x4c));  //第1行第10位,设定'L'
  Write1602(0x80+10,':');    //第1行第11位,设定':'
  Write1602(0x80+14,(0xdf)); //第1行第15位,设定'温度符号'
  Write1602(0x80+15,'C');    //第1行第16位,设定'温度符号'
}
/***********************ds1820温度显示子函数*********************/
void Ds1820RST()  /*ds1820复位*/
{
  unsigned char x=0;
  IO_18B20 = 1;           //IO_1302复位
  delay_18B20(4);     //延时
  IO_18B20 = 0;           //DQ拉低
  delay_18B20(100);   //精确延时大于480us
  IO_18B20 = 1;           //拉高
  delay_18B20(40);
}
uchar Read18B20()  /*读数据*/
{
  uchar i=0;
  uchar dat = 0;
  for (i=8;i>0;i--)
  {   
    IO_18B20 = 0; //给脉冲信号
    dat>>=1;
    IO_18B20 = 1; //给脉冲信号
    if(IO_18B20) dat|=0x80;
    delay_18B20(10);
  }
  return(dat);
}
void Write18B20(uchar wdata)  /*写数据*/
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    IO_18B20 = 0;
    IO_18B20 = wdata&0x01;  //从最低位输入
    delay_18B20(10);
    IO_18B20 = 1;
    wdata>>=1;
  }
}
read_temp()  /*读取温度值并转换*/
{
  uchar Temp_L,Temp_H;
  Ds1820RST();      //Ds1820复位(初始化)
  Write18B20(0xcc); //跳过读序列号
  Write18B20(0x44); //启动温度转换
  Ds1820RST();      //Ds1820复位(初始化)   
  Write18B20(0xcc); //跳过读序列号
  Write18B20(0xbe); //读取温度
  Temp_L=Read18B20();
  Temp_H=Read18B20();
  T_Value=Temp_H;
  T_Value<<=8;
  T_Value=T_Value|Temp_L;
  if(T_Value<0x0fff)
  tflag=0;
  else
  {
    T_Value=~T_Value+1;
    tflag=1;
  }
  T_Value=T_Value*(0.625); //T_Value是2进制,每一个单位'1'=0.625度
  return(T_Value);
}
/**************************检测温度值显示***********************/
void ds1820disp()  /*温度值显示*/
{  
  uchar Symbol;
  read_temp();  
  Display[0]=T_Value/1000+0x30;     //分解百位数
  Display[1]=T_Value%1000/100+0x30; //分解十位数
  Display[2]=T_Value%100/10+0x30;   //分解个位数
  Display[3]=T_Value%10+0x30;   //分解小数点后第1位
  if(tflag==0)
  Symbol=0x2b;//正温度不显示符号,地址来源液晶屏字符表
  else
  Symbol=0x2d;//负温度显示负号:-,地址来源液晶屏字符表
/*  if(Display[0]==0x30)
  {
    Display[0]=0x20;//如果百位为0,不显示,地址来源液晶屏字符表
    if(Display[1]==0x30)
    {
      Display[1]=0x20;//如果百位为0,十位为0也不显示,地址来源液晶屏字符表
    }
  }*/
  write_1602com(0x80+0x40+6);   //符号显示地址
  write_1602dat(Symbol);        //显示符号
  write_1602com(0x80+0x40+7);   //温度百位显示地址
  write_1602dat(Display[0]);    //显示测量温度百位
  write_1602com(0x80+0x40+8);   //温度十位显示地址
  write_1602dat(Display[1]);    //显示测量温度十位
  write_1602com(0x80+0x40+9);  //温度个位显示地址
  write_1602dat(Display[2]);    //显示测量温度个位
  write_1602com(0x80+0x40+10);  //温度小数点位显示地址
  write_1602dat(0x2e);          //显示小数点,地址来源液晶屏字符表
  write_1602com(0x80+0x40+11);  //温度小数位显示地址
  write_1602dat(Display[3]);    //显示测量温度小数点后第1位
  Write1602(0x80+11,'+');  //将ASC码
  Write1602(0x80+2,'+');  //将ASC码   
}
void L_ge_xs()  //低温度设定
{
  Write1602(0x80+13,0x30+L_ge);  //将ASC码
}
void L_shi_xs()  //低温度设定
{
  Write1602(0x80+12,0x30+L_shi);  //将ASC码
}
void H_ge_xs()  //低温度设定
{
  Write1602(0x80+5,0x30+H_ge);  //将ASC码
}
void H_shi_xs()  //低温度设定
{
  Write1602(0x80+4,0x30+H_shi);  //将ASC码
}
void H_bai_xs()  //低温度设定
{
  Write1602(0x80+3,0x30+H_bai);  //将ASC码
}
void compare()
{
  uint H_value=(H_bai*100)+(H_shi*10)+H_ge;
  uint L_value=(L_shi*10)+L_ge;
  T_Value=T_Value/10;
  if(T_Value>=H_value)
  {
    buzzer=0;
    delay(2000);
    buzzer=1;
    delay(2000);
  }
  if(T_Value<=L_value)
  {
    buzzer=0;
    delay(2000);
    buzzer=1;
    delay(2000);
  }   
}
/*********************键盘扫描****************************/
void key_scan()  /*键盘扫描*/
{
  if(K1==0)        //key时钟设置键,K1=0时,说明设置键key按下
  {
    delay(20);       //延时5ms,防止抖动
    if(K1==0);     //在检测一次,防止误动作
    {   
      while(!K1);  //判断功能键是否放开
      S1num++;      //K1按下次数检测变量+1
      if(S1num==9) //如果键值key1n+1=9执行下一句,如果键值key1n+1!=9执行switch(key1n)
      S1num=1;   //设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环
      switch(S1num) //如果S1num=1执行case 1,如果S1num=2执行case 2,以此类推
      {
        case 1:
        keyflag=1;  //K1键按下检测标记,keyflag=1,说明K1键被按下
        write_1602com(0x80+14);
        write_1602com(0x0f); break;  //开显示、开光标、光标闪烁
        case 2: write_1602com(0x80+13); break;  //光标选择
        case 3: write_1602com(0x80+12); break;
        case 4: write_1602com(0x80+6); break;
        case 5: write_1602com(0x80+5); break;
        case 6: write_1602com(0x80+4); break;
        case 7: write_1602com(0x80+3); break;
        case 8: S1num=0;
        keyflag=0;   
        write_1602com(0x0c);//不显示光标                           
        break;
      }
    }
  }
  if(S1num!=0)  //如果key按下次数检测变量S1num!=0,说明时钟调整还在进行,可以检测K1键
  {
    if(K2==0)   //K2键是时钟调整增加键,如果K1==0,K2键被按下,可以向下运行
    {
      delay(5); //延时5ms
      while(!K2);   //K2==0取反K2=1,进入大循环
      switch(S1num) //如果S1num=1执行case 1,如果S1num=2执行case 2,以此类推
      {
        case 1: L_ge++;
        if(L_ge==10) L_ge=0x00;  
        Write1602(0x80+13,0x30+L_ge);  //将ASC码      
        break;
        case 2: L_shi++;
        if(L_shi==10) L_shi=0x00;  
        Write1602(0x80+12,0x30+L_shi);  //将ASC码      
        break;
        case 3:
        Write1602(0x80+11,'+');  //将ASC码           
        break;
        case 4: H_ge++;
        if(H_ge==10) H_ge=0x00;  
        Write1602(0x80+5,0x30+H_ge);  //将ASC码      
        break;
        case 5: H_shi++;
        if(H_shi==10) H_shi=0x00;  
        Write1602(0x80+4,0x30+H_shi);  //将ASC码      
        break;
        case 6: H_bai++;
        if(H_bai==10) H_bai=0x00;  
        Write1602(0x80+3,0x30+H_bai);  //将ASC码      
        break;
        case 7:
        Write1602(0x80+2,'+');  //将ASC码            
        break;
        default:break;
      }
    }
    if(K3==0)
    {
    delay(5);
      while(!K3);
      switch(S1num)
      {
      case 1: L_ge--;
        if(L_ge==-1) L_ge=9;
        Write1602(0x80+13,0x30+L_ge);  //将ASC码  
        break;
        case 2: L_shi--;
        if(L_shi==-1) L_shi=9;
        Write1602(0x80+12,0x30+L_shi);  //将ASC码  
        break;
        case 3:
        Write1602(0x80+11,(0x2d));  //将ASC码            
        break;
        case 4: H_ge--;
        if(H_ge==-1) H_ge=9;  
        Write1602(0x80+5,0x30+H_ge);  //将ASC码      
        break;
        case 5: H_shi--;
        if(H_shi==-1) H_shi=9;  
        Write1602(0x80+4,0x30+H_shi);  //将ASC码      
        break;
        case 6: H_bai--;
        if(H_bai==-1) H_bai=9;  
        Write1602(0x80+3,0x30+H_bai);  //将ASC码      
        break;
        case 7:
        Write1602(0x80+2,'-');  //将ASC码           
        default: break;
      }
    }
  }
}
/*****************************主函数*****************************/
void main()
{
  GND=0;
  delay(100);
  init_1602();
  while(1)
  {
    key_scan();
    if(keyflag==0)
    {
      
      L_ge_xs();
      L_shi_xs();
      H_ge_xs();   //低温度设定
      H_shi_xs();  //低温度设定
      H_bai_xs();  //低温度设定
      ds1820disp();
      compare();
    }
  }
}
回复

使用道具 举报

板凳
ID:82765 发表于 2017-7-1 12:12 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

地板
ID:179958 发表于 2017-7-1 13:06 | 只看该作者
一点一点实现,模块化完善,先做到能正常显示,然后能读取18b20的温度值,再加其他功能。这样在哪一步出问题,就重点学习,努力解决,要不问题在哪儿都不清楚,那调试是很让人心累的,加油
回复

使用道具 举报

5#
ID:164602 发表于 2017-7-2 08:46 | 只看该作者
我一个朋友的设计,你看看,可能对你有帮助。
分享===DS18B20读取多个温度及测量精度设置流程
回复

使用道具 举报

6#
ID:216378 发表于 2017-7-2 19:29 | 只看该作者
可以先用串口读出来(把时序调整好,延时用STC ISP软件计算),再慢慢加外设。比如加485,数码管,LCD,喇叭。
回复

使用道具 举报

7#
ID:212168 发表于 2017-7-3 17:55 | 只看该作者
先在开发板上实验一下,再自己做板,焊工尽量要好
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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