找回密码
 立即注册

QQ登录

只需一步,快速开始

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

DS18B20温度传感器程序及仿真

  [复制链接]
跳转到指定楼层
楼主
DS18B20数字温度传感器
PROTEUS仿真
LCD显示屏LM016L
AT89C51




所有文件下载 : DS18B20温度传感器proteus仿真.zip (64.02 KB, 下载次数: 50)

  1. /***********************lcd1602.c文件程序源代码*************************/
  2. #include <reg51.h>
  3. #define LCD1602_DB   P0
  4. sbit LCD1602_RS = P1^0;
  5. sbit LCD1602_RW = P1^1;
  6. sbit LCD1602_E  = P1^5;
  7. void LcdWaitReady()  //等待液晶准备好
  8. {
  9.     unsigned char sta;
  10.    
  11.     LCD1602_DB = 0xFF;
  12.     LCD1602_RS = 0;
  13.     LCD1602_RW = 1;
  14.     do
  15.     {
  16.         LCD1602_E = 1;
  17.         sta = LCD1602_DB; //读取状态字
  18.         LCD1602_E = 0;
  19.     } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
  20. }
  21. void LcdWriteCmd(unsigned char cmd)  //写入命令函数
  22. {
  23.     LcdWaitReady();
  24.     LCD1602_RS = 0;
  25.     LCD1602_RW = 0;
  26.     LCD1602_DB = cmd;
  27.     LCD1602_E  = 1;
  28.     LCD1602_E  = 0;
  29. }
  30. void LcdWriteDat(unsigned char dat)  //写入数据函数
  31. {
  32.     LcdWaitReady();
  33.     LCD1602_RS = 1;
  34.     LCD1602_RW = 0;
  35.     LCD1602_DB = dat;
  36.     LCD1602_E  = 1;
  37.     LCD1602_E  = 0;
  38. }
  39. void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str)  //显示字符串,屏幕起始坐标(x,y),字符串指针str
  40. {
  41.     unsigned char addr;
  42.    
  43.     //由输入的显示坐标计算显示RAM的地址
  44.     if (y == 0)
  45.         addr = 0x00 + x; //第一行字符地址从0x00起始
  46.     else
  47.         addr = 0x40 + x; //第二行字符地址从0x40起始
  48.    
  49.     //由起始显示RAM地址连续写入字符串
  50.     LcdWriteCmd(addr | 0x80); //写入起始地址
  51.     while (*str != '\0')      //连续写入字符串数据,直到检测到结束符
  52.     {
  53.         LcdWriteDat(*str);
  54.         str++;
  55.     }
  56. }
  57. void LcdInit()  //液晶初始化函数
  58. {
  59.     LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
  60.     LcdWriteCmd(0x0C);  //显示器开,光标关闭
  61.     LcdWriteCmd(0x06);  //文字不动,地址自动+1
  62.     LcdWriteCmd(0x01);  //清屏
  63. }
  64. /***********************DS18B20.c文件程序源代码*************************/
  65. #include <reg51.h>
  66. #include <intrins.h>
  67. sbit IO_18B20 = P3^2;  //DS18B20通信引脚
  68. void DelayX10us(unsigned char t)  //软件延时函数,延时时间(t*10)us
  69. {
  70.     do {
  71.         _nop_();
  72.         _nop_();
  73.         _nop_();
  74.         _nop_();
  75.         _nop_();
  76.         _nop_();
  77.         _nop_();
  78.         _nop_();
  79.     } while (--t);
  80. }
  81. bit Get18B20Ack(void)  //复位总线,获取存在脉冲,以启动一次读写操作
  82. {
  83.     bit ack;
  84.    
  85.     EA = 0;   //禁止总中断
  86.     IO_18B20 = 0;     //产生500us复位脉冲
  87.     DelayX10us(50);
  88.     IO_18B20 = 1;
  89.     DelayX10us(6);    //延时60us
  90.     ack = IO_18B20;   //读取存在脉冲
  91.     while(!IO_18B20); //等待存在脉冲结束
  92.     EA = 1;   //重新使能总中断
  93.    
  94.     return ack;
  95. }
  96. void Write18B20(unsigned char dat)  //向DS18B20写入一个字节数据
  97. {
  98.     unsigned char mask;
  99.    
  100.     EA = 0;   //禁止总中断
  101.     for (mask=0x01; mask!=0; mask<<=1)  //低位在先,依次移出8个bit
  102.     {
  103.                 IO_18B20 = 0;         //产生2us低电平脉冲
  104.         _nop_();
  105.                 _nop_();
  106.         if ((mask&dat) == 0)  //输出该bit值
  107.             IO_18B20 = 0;
  108.         else
  109.             IO_18B20 = 1;
  110.                 DelayX10us(6);        //延时60us
  111.                 IO_18B20 = 1;         //拉高通信引脚
  112.     }
  113.     EA = 1;   //重新使能总中断
  114. }
  115. unsigned char Read18B20(void)  //从DS18B20读取一个字节数据
  116. {
  117.     unsigned char dat;
  118.     unsigned char mask;
  119.    
  120.     EA = 0;   //禁止总中断
  121.             for (mask=0x01; mask!=0; mask<<=1)  //低位在先,依次采集8个bit
  122.     {
  123.         IO_18B20 = 0;         //产生2us低电平脉冲
  124.                 _nop_();
  125.                 _nop_();
  126.                 IO_18B20 = 1;         //结束低电平脉冲,等待18B20输出数据
  127.                 _nop_();              //延时2us
  128.                 _nop_();
  129.         if (!IO_18B20)        //读取通信引脚上的值
  130.                 dat &= ~mask;
  131.         else
  132.             dat |= mask;
  133.                 DelayX10us(6);        //再延时60us
  134.             }
  135.     EA = 1;   //重新使能总中断
  136.     return dat;
  137. }
  138. bit Start18B20()  //启动一次18B20温度转换,返回值代表是否启动成功
  139. {
  140.     bit ack;
  141.    
  142.     ack = Get18B20Ack();   //执行总线复位,并获取18B20应答
  143.     if (ack == 0)          //如18B20正确应答,则启动一次转换
  144.     {
  145.             Write18B20(0xCC);  //跳过ROM操作
  146.             Write18B20(0x44);  //启动一次温度转换
  147.     }
  148.     return ~ack;  //ack==0表示操作成功,所以返回值为其取反值
  149. }
  150. bit Get18B20Temp(int *temp)  //读取DS18B20温度值,返回值代表是否读取成功
  151. {
  152.     bit ack;
  153.     unsigned char LSB, MSB; //16bit温度值的低字节和高字节
  154.    
  155.     ack = Get18B20Ack();    //执行总线复位,并获取18B20应答
  156.     if (ack == 0)           //如18B20正确应答,则读取温度值
  157.     {
  158.             Write18B20(0xCC);   //跳过ROM操作
  159.             Write18B20(0xBE);   //发送读命令
  160.             LSB = Read18B20();  //读温度值的低字节
  161.             MSB = Read18B20();  //读温度值的高字节
  162.         *temp = ((int)MSB << 8) + LSB;  //合成为16bit整型数
  163.     }
  164. return ~ack;  //ack==0表示操作应答,所以返回值为其取反值
  165. }
  166. /***********************main.c文件程序源代码*************************/
  167. #include <reg51.h>
  168. bit flag1s = 0;          //1s定时标志
  169. unsigned char T0RH = 0;  //T0重载值的高字节
  170. unsigned char T0RL = 0;  //T0重载值的低字节
  171. void ConfigTimer0(unsigned int ms);
  172. unsigned char IntToString(unsigned char *str, int dat);
  173. extern bit Start18B20();
  174. extern bit Get18B20Temp(int *temp);
  175. extern void LcdInit();
  176. extern void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str);
  177. void main ()
  178. {
  179.     bit res;
  180.     int temp;        //读取到的当前温度值
  181.     int intT, decT;  //温度值的整数和小数部分
  182.     unsigned char len;
  183.     unsigned char str[12];
  184.     LcdInit();        //初始化液晶
  185.     Start18B20();     //启动DS18B20
  186.     ConfigTimer0(10); //T0定时10ms
  187.     EA = 1;           //开总中断
  188.    
  189.     while(1)
  190.     {
  191.         if (flag1s)  //每秒更新一次温度
  192.         {
  193.             flag1s = 0;
  194.             res = Get18B20Temp(&temp);  //读取当前温度
  195.             if (res)                    //读取成功时,刷新当前温度显示
  196.             {
  197.                 intT = temp >> 4;             //分离出温度值整数部分
  198.                 decT = temp & 0xF;            //分离出温度值小数部分
  199.                 len = IntToString(str, intT); //整数部分转换为字符串
  200.                 str[len++] = '.';             //添加小数点
  201.                 decT = (decT*10) / 16;        //二进制的小数部分转换为1位十进制位
  202.                 str[len++] = decT + '0';      //十进制小数位再转换为ASCII字符
  203.                 while (len < 6)               //用空格补齐到6个字符长度
  204.                 {
  205.                     str[len++] = ' ';
  206.                 }
  207.                 str[len] = '\0';              //添加字符串结束符
  208.                 LcdShowStr(3, 0, "temperature");
  209.                 LcdShowStr(7, 1, str);        //显示到液晶屏上
  210.             }
  211.             else                        //读取失败时,提示错误信息
  212.             {
  213.                 LcdShowStr(6, 0, "error!");
  214.             }
  215.             Start18B20();               //重新启动下一次转换
  216.         }
  217.     }
  218. }
  219. unsigned char IntToString(unsigned char *str, int dat)  //整型数转换为十进制字符串,返回值为转换后的字符串长度
  220. {
  221.     signed char i;
  222.     unsigned char len = 0;
  223.     unsigned char buf[6];
  224.    
  225.     if (dat < 0)  //如果为负数,首先取绝对值,并添加负号
  226.     {
  227.         dat = -dat;
  228.         *str++ = '-';
  229.         len++;
  230.     }
  231.     for (i=0; i<=4; i++)  //由低到高转换为十进制位
  232.     {
  233.         buf[ i] = dat % 10;
  234.         dat /= 10;
  235.     }
  236.     for (i=4; i>=1; i--)  //查找有效数字最高位,以忽略更高位的‘0’
  237.     {
  238.         if (buf[ i] != 0)
  239.         {
  240.             break;
  241.         }
  242.     }
  243.     for ( ; i>=0; i--)  //有效数字位转换为ASCII码
  244.     {
  245.         *str++ = buf[ i] + '0';
  246.         len++;
  247.     }
  248.     *str = '\0';        //添加字符串结束符
  249.    
  250.     return len;  //返回字符串长度
  251. }
  252. void ConfigTimer0(unsigned int ms)  //T0配置函数
  253. {
  254.     unsigned long tmp;
  255.    
  256.     tmp = 11059200 / 12;      //定时器计数频率
  257.     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  258.     tmp = 65536 - tmp;        //计算定时器重载值
  259.     tmp = tmp + 12;           //修正中断响应延时造成的误差
  260.    
  261.     T0RH = (unsigned char)(tmp >> 8);  //定时器重载值拆分为高低字节
  262.     T0RL = (unsigned char)tmp;
  263.     TMOD &= 0xF0;   //清零T0的控制位
  264.     TMOD |= 0x01;   //配置T0为模式1
  265.     TH0 = T0RH;     //加载T0重载值
  266.     TL0 = T0RL;
  267.     ET0 = 1;        //使能T0中断
  268.     TR0 = 1;        //启动T0
  269. }
  270. void InterruptTimer0() interrupt 1  //T0中断服务函数
  271. {
  272.     static unsigned char tmr1s = 0;
  273.    
  274.     TH0 = T0RH;  //定时器重新加载重载值
  275.     TL0 = T0RL;
  276.     tmr1s++;
  277.     if (tmr1s >= 100)  //定时1s
  278.     {
  279.         tmr1s = 0;
  280.         flag1s = 1;
  281.     }
  282. }
复制代码


评分

参与人数 2黑币 +55 收起 理由
天才2333333 + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:130007 发表于 2016-7-12 13:14 | 只看该作者
可以放两个温度传感器吗
回复

使用道具 举报

板凳
ID:48580 发表于 2016-7-20 10:40 | 只看该作者
sdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
回复

使用道具 举报

地板
ID:980762 发表于 2021-11-16 09:41 | 只看该作者
这个显示器会乱码吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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