找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机两路DS18B20温度检测仿真与源码(带详细注释)

[复制链接]
跳转到指定楼层
楼主
两路DS18B20温度仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)



单片机源程序如下(注释非常详细):
  1. #include<reg51.h>                  //预处理命令,定义SFR的头文件
  2. #include<math.h>                        //数学函数库文件
  3. #define uchar unsigned char                //定义无符号字符变量 uchar
  4. #define uint unsigned int         //定义无符号字符变量 uint         
  5. #define lcd_data P0       //定义LCD1602接口 P0
  6. sbit P1_1=P1^1;
  7. sbit P1_0=P1^0;
  8. sbit DQ1=P3^7;        //将DQ1位定义为P3.7引脚
  9. sbit DQ=P3^6;         //将DQ位定义为P3.6引脚                                 
  10. sbit lcd_RS=P2^0;                     //将RS位定义为P2.0引脚
  11. sbit lcd_RW=P2^1;                    //将RW位定义为P2.1引脚
  12. sbit lcd_EN=P2^2;                    //将EN位定义为P2.2引脚
  13. uchar t[2],speed,temperature;      //用来存放温度值
  14. uchar DS18B20_is_ok;
  15. uchar TempBufferl[16]={0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xdf,0x43,'\0'};
  16. uchar tab[16]={0x20,0x20,0x20,0x54,0x20,0x4d,0x6f,0x6e,0x69,0x74,0x6f,0x72,'\0'};   //显示“T Monitor”
  17. /***********************LCD显示子程序*****************************/
  18. void delay_20ms(void)     //延时20ms函数
  19. {  
  20.    uchar i,temp;                    //声明变量i,temp
  21.    for(i=20;i>0;i--)           //循环
  22.    {
  23.      temp=248;                                //给temp赋值248
  24.          while(--temp);                         //temp减1是否等于0,否则继续执行该行
  25.          temp=248;                                  //给temp赋值248
  26.          while(--temp);                           //temp减1是否等于0,否则继续执行该行
  27.    }
  28. }
  29. void delay_38us(void)  //延时38μs函数
  30. {
  31.    uchar temp;                        //声明变量temp
  32.    temp=18;                                // 给temp赋值
  33.    while(--temp);                 //temp减1是否等于0,否则继续执行该行
  34. }
  35. void delay_1520us(void)  //延时1520μs函数
  36. {
  37.    uchar i,temp;                  //声明变量i,temp
  38.    for(i=3;i>0;i--)                   //循环
  39.    {
  40.      temp=252;                                //给temp赋值
  41.      while(--temp);                         //temp减1是否等于0,否则继续执行该行
  42.    }
  43. }
  44. uchar lcd_rd_status()      //读取LCD602的状态,主要用于判断是否忙
  45. {
  46.    uchar tmp_sts;                           //声明变量tmp_sts
  47.    lcd_data=0xff;          //初始化P3口
  48.    lcd_RW=1;                                 //RW=1 读
  49.    lcd_RS=0;                                 //RS=0 命令,合起来表示读命令(状态)
  50.    lcd_EN=1;                                 //EN=1,打开EN,LCD1602开始输出命令数据,100ns后命令数据有效
  51.    tmp_sts=lcd_data;                  //读取命令到tmp_sts
  52.    lcd_EN=0;                                  //关闭LCD1602
  53.    lcd_RW=0;                                  //把LCD1602设置成写
  54.    return tmp_sts;                  //函数返回值tmp_sts
  55. }
  56. void lcd_wr_com(uchar command)          //写一个命令到LCD1602
  57. {
  58.    while(0x80&lcd_rd_status());          //写之前先判断LCD1602是否忙,看读出的命令的最高位是否为1,为1表示忙,继续读,直到不忙
  59.    lcd_RW=0;
  60.    lcd_RS=0;                                         //RW=0,RS=0写命令
  61.    lcd_data=command;                         //把需要写的命令写到数据线上
  62.    lcd_EN=1;
  63.    lcd_EN=0;                                         //EN高电平脉冲,命令写入
  64. }
  65. void lcd_wr_data(uchar sjdata)          //写一个显示数据到LCD1602
  66. {
  67.    while(0x80&lcd_rd_status());          //写之前先判断LCD1602是否忙,看读出的命令的最高位是否为1,为1表示忙,继续读,直到不忙
  68.    lcd_RW=0;
  69.    lcd_RS=1;                                         //RW=0,RS=1写显示数据
  70.    lcd_data=sjdata;                         //把需要写的显示数据写到数据线上
  71.    lcd_EN=1;
  72.    lcd_EN=0;                                         //EN高电平脉冲,命令写入
  73.    lcd_RS=0;       
  74. }
  75. void Init_lcd(void)                        //初始化LCD1602
  76. {
  77.    delay_20ms();                                 //调用延时
  78.    lcd_wr_com(0x38);                   //设置16*2格式,5*8点阵,8位数据接口
  79.    delay_38us();                                  //调用延时
  80.    lcd_wr_com(0x0c);                   //开显示,不显示光标
  81.    delay_38us();                                  //调用延时
  82.    lcd_wr_com(0x01);                   //清屏
  83.    delay_1520us();                        //调用延时
  84.    lcd_wr_com(0x06);                  //显示一个数据后光标自动+1
  85. }
  86. void GotoXY(uchar x,uchar y)        //设置位置,X为列,y为行
  87. {                                                               
  88.    if(y==0)
  89.      lcd_wr_com(0x80|x);                         //如果Y为0,则显示第一行
  90.    if(y==1)
  91.      lcd_wr_com(0xc0|x);                          //如果Y为1,则显示第二行
  92. }
  93. void Print(uchar *str)                          //显示字符串函数
  94. {                                                                       
  95.    while(*str!='\0')                                   //判断字符串是否显示完
  96.    {
  97.      lcd_wr_data(*str);                         //写数据
  98.      str++        ;
  99.    }
  100. }
  101. void LCD_Print(uchar x,uchar y,uchar *str)          //X为列值,Y为行值,str是要显示的字符串
  102. {
  103.    GotoXY(x,y);                                                                  //设定显示位置
  104.    Print(str);                                                                 //显示字符串
  105. }
  106. /************************系统显示子函数********************/
  107. void covert1()                                                         //温度转化程序
  108. {
  109.    uchar x=0x00;                                                         //变量初始化
  110.    if(t[1]>0x07)                                                         //判断正负温度
  111.    {
  112.      TempBufferl[3]=0x2d;                                   //0x2d为“-”的ASCII码
  113.      t[1]=~t[1];                                                   //负数的补码
  114.      t[0]=~t[0];                                                   //换算成绝对值
  115.      x=t[0]+1;                                                           //加1
  116.      t[0]=x;                                                           //把X的值送入t[0]
  117.      if(x>255)                                                           //如果X大于255
  118.      t[1]++;                                                           //t[1]加1
  119.    }
  120.    else                          
  121.      TempBufferl[3]=0x2b;                                  //0xfe为变“+”的ASCII码
  122.    t[1]<<=4;                                                           //将高字节左移4位
  123.    t[1]=t[1]&0x70;                                           //取出高字节的3个有效数字位
  124.    x=t[0];                                                           //将t[0]暂存到X,因为取小数部分还要用它
  125.    x>>=4;                                                                   //右移4位
  126.    x=x&0x0f;                                                           //和前面两句就是取出t[0]的高四位
  127.    t[1]=t[1]|x ;                                                    //将高低字节的有效值的整数部分拼成一个字节
  128.    temperature=t[1];
  129.    TempBufferl[4]=t[1]/100+0x30;                        //加0X30为变0-9ASCII码
  130.    if(TempBufferl[4]==0x30)                                 //如果百位为0
  131.    TempBufferl[4]=0xfe;                                         //百位数消隐
  132.    TempBufferl[5]=(t[1]%100)/10+0x30;         //分离出十位
  133.    TempBufferl[6]=(t[1]%100)%10+0x30;         //分离出个位
  134. }
  135. /*********************DS18B20函数**********************/
  136. void delay_18B20(uint i)        //延时程序
  137. {
  138.    while(i--);
  139. }
  140. void Init_DS18B20(void)                                        //DS18B20初始化函数
  141. {
  142.    uchar x=0;
  143.    if(P1_0==1&P1_1==0)                                                  //按下P1_1
  144.    {
  145.      TempBufferl[0]=0x32;                                          //设置LCD第二行的第一位为2
  146.          TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为:
  147.      DQ1=1;                                                                                //DQ1复位
  148.          delay_18B20(8);                                                        //稍做延时
  149.             DQ1=0;                                                                           //单片机将DQ1拉低
  150.          delay_18B20(80);                                                  //精确延时大于480us
  151.             DQ1=1;                                                                        //拉高总线
  152.          delay_18B20(14);                                                   //确保发出存在脉冲
  153.          x=DQ1;                                   //稍作延迟后,如果X=0则初始化成功,如果X=1则初始化失败
  154.      delay_18B20(20);}
  155.    if(P1_0==0&P1_1==1)                                                        //按下P1_0
  156.    {
  157.          TempBufferl[0]=0x31;                                          //设置LCD第二行的第一位为1
  158.          TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为:
  159.          DQ=1;                                                                           //DQ1复位
  160.          delay_18B20(8);                                                   //稍做延时
  161.             DQ=0;                                                                                //单片机将DQ1拉低
  162.          delay_18B20(80);                                                  //精确延时大于480us
  163.             DQ=1;                                                                           //拉高总线
  164.          delay_18B20(14);                                                   //确保发出存在脉冲
  165.          x=DQ;                                   //稍作延迟后,如果X=0则初始化成功,如果X=1则初始化失败
  166.      delay_18B20(20);
  167.    }                                                                                  
  168.    if(P1_0==1&P1_1==1)                                                   //无按键按下
  169.    {
  170.      TempBufferl[0]=0x20;                                          //设置LCD第二行的第一位为空白
  171.      TempBufferl[1]=0x20;                                          //设置LCD第二行的第二位为空白
  172.    }
  173. }
  174. uchar ReadOneChar(void)                                                 //DS18B20读一个字节函数
  175. {
  176.    unsigned char i=0;
  177.    unsigned char dat0=0;
  178.    for(i=8;i>0;i--)
  179.    {
  180.      if(P1_0==1&P1_1==0)                                                  //按下P1_1
  181.      {
  182.            TempBufferl[0]=0x32;                                          //设置LCD第二行的第一位为“2”
  183.            TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为“:”
  184.            DQ1=0;                                                                                //读前总线保持为低
  185.        dat0>>=1;
  186.        DQ1=1;                                                     //开始读总线释放                       
  187.        if(DQ1) dat0|=0x80;                                         //从DS18B20总线读得一位
  188.            delay_18B20(4);                                   //延时一段时间
  189.          }
  190.    if(P1_0==0&P1_1==1)                                                   //按下P1_0
  191.    {
  192.          TempBufferl[0]=0x31;                                          //设置LCD第二行的第一位为1
  193.          TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为:
  194.          DQ=0;                                                                                 //读前总线保持为低
  195.      dat0>>=1;
  196.      DQ=1;                                              //开始读总线释放                               
  197.      if(DQ) dat0|=0x80;                                                                          //从DS18B20总线读得一位
  198.          delay_18B20(4);                    //延时一段时间
  199.    }
  200.    if(P1_0==1&P1_1==1)                   //无按键按下
  201.    {
  202.      TempBufferl[0]=0x20;                                          //设置LCD第二行的第一位为空白
  203.      TempBufferl[1]=0x20;                                          //设置LCD第二行的第二位为空白
  204.    }
  205.   }
  206.   return(dat0);                                                           //返回数据
  207. }
  208. void WriteOneChar(uchar dat1)                                //DS18B20写一个字节函数
  209. {
  210.    uchar i=0;
  211.    for(i=8;i>0;i--)
  212.    {
  213.      if(P1_0==1&P1_1==0)                                                  //按下P1_1
  214.      {
  215.           TempBufferl[0]=0x32;                                          //设置LCD第二行的第一位为“2”
  216.           TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为“:”
  217.           DQ1=0;                //开始写入DS18B20总线要处于复位(低)状态
  218.           DQ1=dat1&0x01;        //写入下一位                                       
  219.           delay_18B20(5);                                                 
  220.       DQ1=1;                 //重新释放总线
  221.           dat1>>=1;                 //把一个字节分成8个BIT环移给DQ1
  222.          }          
  223.      if(P1_0==0&P1_1==1)         //按下P1_0
  224.      {
  225.           TempBufferl[0]=0x31;                                          //设置LCD第二行的第一位为1
  226.           TempBufferl[1]=0x3a;                                          //设置LCD第二行的第二位为:
  227.           DQ=0;                                 //开始写入DS18B20总线要处于复位(低)状态
  228.           DQ=dat1&0x01;                        //写入下一位                       
  229.           delay_18B20(5);                                                  
  230.       DQ=1;                 //重新释放总线
  231.           dat1>>=1;                 //把一个字节分成8个BIT环移给DQ
  232.          }                                                                  
  233.      if(P1_0==1&P1_1==1)           //无按键按下
  234.      {
  235.       TempBufferl[0]=0x20;                                          //设置LCD第二行的第一位为空白
  236.       TempBufferl[1]=0x20;                                          //设置LCD第二行的第二位为空白
  237.          }
  238.    }
  239. }                                                                                  
  240. void ReadTemperature()                                          //读取DS18B20当前温度
  241. {
  242.   delay_18B20(80);                                                        //延时一段时间
  243.   Init_DS18B20();
  244.   WriteOneChar(0xcc);                                           //跳过读序列列号的操作
  245.   WriteOneChar(0x44);                                          //启动温度转换
  246.   delay_18B20(80);                                                   //延时一段时间
  247. ……………………

  248. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
两路DS18B20.zip (464.64 KB, 下载次数: 94)






分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:57896 发表于 2018-1-16 17:15 | 只看该作者
参考一下,谢谢分享
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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