找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2872|回复: 0
收起左侧

单只DS18B20测温程序(1602写单字符方式)

[复制链接]
ID:110653 发表于 2016-3-29 01:03 | 显示全部楼层 |阅读模式

DS18B20是一种很常用的数字温度传感器,温度检测范围是-55~+125度,手册 说明在-10~+85度范围内检测误差为±0.5度,作者在自己的产品中随机抽样验证 了几只传感器,在-25度误差0.1度,+25度与+50度误差小于0.1度,可见这种传感 器实际精度是很高的,传感器引脚如图19-1所示,工作电压范围是3.0~5.5V,通 常使用+5V,电源接反或接错一般是不会损坏传感器的,对于单只DS18B20的使用,我们按图19-2连接即可。







电路和介绍详见:http://www.51hei.com/bbs/dpj-47286-1.html(在这贴附件中可下载完整的源码压缩包)
  1. //单只DS18B20的温度检测,测温范围-55 —— +125度,1602液晶显示。
  2. #include "STC15W4K.H"
  3. #include "DS18b20.h"
  4. #include "myfun.h"
  5. #include "LCD1602.h"
  6. bit flag;                              // flag=0表示正温,flag=1表示负温。
  7. unsigned char baiw,shiw,gew;           // 百位、十位、个位 ASCII码
  8. unsigned char point_1,point_2,point_3,point_4;    // 小数点后1、2、3、4位ASCII码
  9.         
  10. //****************温度数据处理函数************************/
  11. void gettemp()                           //读取温度值
  12. {                     
  13.          unsigned int temp0,temp1,temp;      // 存放小数、整数、符号,10000倍小数值
  14.          unsigned char temh,teml;                  // 存放原始高字节与低字节         
  15.          temp=DS18B20_ReadTemperature();         // 从18B20中读取2字节原始温度值
  16.          flag=0;
  17.          if ((temp&0xf800)!=0)                   // 如果是负温,将补码取反加1变为原码
  18.          {
  19.                  temp=~temp        +1;
  20.                  flag=1;
  21.          }        
  22.          temh=temp/256;                                   // 高字节(5位符号+3位数据)
  23.          teml=temp%256;                                   // 低字节(4位整数+4位小数)
  24.          
  25.          temp0=teml&0x0F;              // 4 位小数
  26.      temp1=(temh<<4)|(teml>>4);    // 8 位整数(最高一位符号0不用管)      
  27.      baiw=temp1/100+48;            // 百位ASCII码         
  28.      shiw=(temp1%100)/10+48;       // 十位 ASCII码
  29.      gew=(temp1%100)%10+48;            // 个位 ASCII码  
  30.      temp=temp0*625;               // 将结果中的小数乘以分辨温度0.0625
  31.                                                             // 扩大10000倍进行输出,不用浮点,同样可以保留4位小数精度
  32.          point_1=temp/1000+48;                   // 小数点后1位ASCII码
  33.          point_2=(temp%1000)/100+48;   // 小数点后2位ASCII码
  34.          point_3=(temp%100)/10+48;           // 小数点后3位ASCII码
  35.          point_4=temp%10+48;                   // 小数点后4位ASCII码
  36. }

  37. void port_mode()            // 端口模式
  38. {
  39.         P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
  40.         P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
  41. }

  42. void main()
  43. {
  44.         unsigned char xPos,yPos;
  45.         unsigned char *s="Now temp is:";
  46.         port_mode();                      // 所有IO口设为准双向弱上拉方式。
  47.         xPos=0;                              // xPos表示水平右移字符数(0-15)
  48.         yPos=0;                              // yPos表示垂直下移字符数(0-1)
  49.         delay100ms();                 // 等待LCD1602上电时内部复位
  50.         LCD1602_Init();
  51.         WriteString(xPos,yPos,s);          // X坐标、Y坐标、字符串,屏幕左上角为坐标原点        
  52.         DS18B20_SetResolution(3); //设置DS18B20的分辨率为12位(默认值,新器件可以不作任何设置)
  53.         while(1)
  54.         {
  55.                 gettemp();
  56.                 if(flag)      // 负温度
  57.                 {
  58.                         WriteChar(0,1,'-');
  59.                 }
  60.                 if(!flag)     // 正温度
  61.                 {
  62.                         WriteChar(0,1,'+');
  63.                 }               
  64.                 WriteChar(1,1,baiw);
  65.                 WriteChar(2,1,shiw);
  66.                 WriteChar(3,1,gew);
  67.                 WriteChar(4,1,'.');
  68.                 WriteChar(5,1,point_1);
  69.                 WriteChar(6,1,point_2);
  70.                 WriteChar(7,1,point_3);
  71.                 WriteChar(8,1,point_4);

  72.                 SetCur(NoCur);                  //  有显示无光标
  73.         }
  74. }
复制代码

ds18b20.c

  1. /****************《51单片机轻松入门-基于STC15W4K系列》配套例程 *************
  2. ★★★★★★★★★★★★★★★★★★★★★★★★
  3. 《51单片机轻松入门-基于STC15W4K系列》 一书已经由北航出版社正式出版发行。
  4.   作者亲手创作的与教材配套的51双核实验板(2个MCU)对程序下载、调试、仿真方便,不需要外部
  5.   仿真器与编程器,这种设计方式彻底解决了系统中多个最高优先级谁也不能让谁的中断竞争问题。
  6.   QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
  7.         验证信息:STC15单片机
  8.   邮箱:xgliyouquan@126.com
  9.   ★★★★★★★★★★★★★★★★★★★★★★★★*/

  10. #include "DS18b20.h"
  11. #include "myfun.h"
  12. sbit  DQTest=P2^2;    //时间调整观察参考引脚        
  13. /****************************************************************/
  14. unsigned char DS18B20_Reset()
  15. {
  16.         unsigned char x=0;
  17.         DQ=1;           // DQ拉高
  18.                         //DQTest=1;     // 时间调整观察参考引脚
  19.         delay2us();            // 延时约2uS
  20.         DQ=0;           // 单片机将DQ拉低         
  21.                     //DQTest=0;          // 时间调整观察参考引脚
  22.         delay720us();   // 要求延时 480us~960us (这里取中心值720uS)
  23.         DQ=1;           // DQ拉高释放总线
  24.                             //DQTest=1;          // 时间调整观察参考引脚
  25.                         // 以上是由单片机产生"复位脉冲"
  26.         delay75us();    // 要求延时大于60 us  (这里取75uS)
  27.         x=DQ;           // DS18B20产生"存在脉冲"
  28.                         // 检测DQ 如果为低,说明复位成功,DS18B20存在
  29.                         // 如果为高,说明复位失败,DS18B20损坏或不存在
  30.         delay500us();   // 让18B20释放总线,避免影响到下一步操作。
  31.         return x;            // 返回复位结果
  32. }

  33. void DS18B20_WriteBit(unsigned char bdat)   // 向DS18B20写入一个位
  34. {
  35.         DQ=1;           // 将数据线置为高电平
  36.                                         //DQTest=1;        // 时间调整观察参考引脚
  37.         delay2us();            // 两次写过程间隔大于1us,这里取2uS      
  38.         DQ=0;                // 开始一个写过程
  39.                                         //DQTest=0;        // 时间调整观察参考引脚
  40.         delay4us();     // 低电平保持1us以上,这里延时约4uS,
  41.         DQ=bdat;
  42.         delay60us();    // 延时60uS,写过程开始15us后DS18B20对数据线进行采样
  43.                         // 写周期在60us-120 us之间。
  44.         DQ=1;                          // 释放总线
  45.                                         //DQTest=1;        // 时间调整观察参考引脚
  46. }  
  47. void DS18B20_WriteByte(unsigned char dat)        // 向DS18B20写入一个字节
  48. {
  49.         unsigned char i=0;
  50.         for(i=0;i<8;i++)                       // 调用8次写时间片实现写入字节(8个位)
  51.         {
  52.                 DS18B20_WriteBit(dat&(1<<i));      // 从低位开始写入,0xCC&1=(0100 1110 &0000 0001)=        0
  53.         }
  54. }

  55. unsigned char DS18B20_ReadBit()         // 从DS18B20读取一个位
  56. {
  57.         unsigned char bdat=0;
  58.         DQ=1;           // 将数据线置为高电平
  59.                                 DQTest=1;        // 时间调整观察参考引脚
  60.         delay2us();            // 两次读过程间隔大于1us,这里取2uS
  61.         DQ=0;           // 开始一个读过程
  62.                                 DQTest=0;        // 时间调整观察参考引脚
  63.         delay4us();     // 低电平保持1us以上,这里取4uS
  64.         DQ=1;           // 开始读取数据线状态
  65.                                 DQTest=1;   // 时间调整观察参考引脚
  66.         delay4us();     // 读时间片开始后15us内主机对数据线进行采样,这里取4uS
  67.         bdat=DQ;
  68.         delay60us();    // 读周期60us<T<120uS   (60 uS)
  69.         return bdat;  
  70. }

  71. unsigned char DS18B20_ReadByte()                 // 从DS18B20读取一个字节
  72. {
  73.         unsigned char i=0,dat=0;
  74.         for(i=0;i<8;i++)                     // 调用8次读过程实现字节读取(8个位)
  75.         {
  76.                 dat|=(DS18B20_ReadBit()<<i);     // 从低位开始读取
  77.         }
  78.         return(dat);
  79. }  

  80. void DS18B20_SetResolution(unsigned char res)           // 设置DS18B20的分辨率
  81. {                                                                                           // res:0:9位 1:10位 2:11位 3:12位
  82.         while(DS18B20_Reset());                    // 复位,通信前必须复位
  83.         DS18B20_WriteByte(0x4e);                   // 写暂存器指令
  84.         DS18B20_WriteByte(0xff);                   // 此值被写入TH
  85.         DS18B20_WriteByte(0xff);                   // 此值被写入TL
  86.         DS18B20_WriteByte(0x1f|(res<<5));          // 设置分辨率 (0 R1 R0 1   1 1 1 1)
  87. }

  88. unsigned int DS18B20_ReadTemperature()            // 从DS18B20中读取温度
  89. {
  90.         unsigned int Temp=0;  
  91.         DS18B20_Reset();                // 复位,通信前必须复位
  92.         DS18B20_WriteByte(0xcc);        // 如果总线上只有一个DS18B20,则可跳过ROM操作(0xCC)
  93.         DS18B20_WriteByte(0x44);        // 启动温度转换(0x44)
  94.                                                         // 实验结果:执行完上面 2 条命令后信号线将永久呈高电平状态
  95.         
  96. //        while(!DS18B20_ReadBit());      // 启动温度转换后要进行读忙,9~12位精度温度转换所需的
  97.                                         // 最长时间分别为93.75ms、187.5ms、375ms、750ms(实验结果:602mS)
  98.         delay760ms();                   // 这里也可以不判忙,避免数据线不停的发送数据,直接延时750ms再读取温度值。
  99.                
  100.         DS18B20_Reset();                // 温度转换后DS18B20处于空闲状态,要进行通信,需要重新复位
  101.         DS18B20_WriteByte(0xcc);        // 跳过ROM操作
  102.         DS18B20_WriteByte(0xbe);        // 写入读取暂存器命令
  103.                                         //(共可读9个寄存器,直接连续读取,前两个就是温度)
  104.         Temp=DS18B20_ReadByte();            // 读取的第一个字节是温度值的低字节,第二个字节是温度值的高字节。        
  105.         Temp|=((unsigned int)DS18B20_ReadByte())<<8;        // 将读到的两个字节进行整合
  106.         return Temp;                            // 返回读得的2个温度原始字节。                                                         
  107. }
复制代码



回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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