找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单只18B20测温程序(1602写字符串方式)

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

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. /****************《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. //单只DS18B20的温度检测,测温范围-55 —— +125度,1602液晶显示。
  11. #include "STC15W4K.H"
  12. #include "DS18b20.h"
  13. #include "myfun.h"
  14. #include "LCD1602.h"
  15. bit flag;                      // flag=0表示正温,flag=1表示负温。
  16. unsigned char str[10];                   // 最长字符10字节,比如:-123.4567/0
  17. unsigned char Long_Str(long dat,unsigned char *str) // 长整型数转换为字符串,返回值为转换后的字符串长度
  18. {
  19.         signed char i=0;
  20.         unsigned char len = 0;
  21.         unsigned char buf[11];           // 长整数最大值4294967295,转ASCII码后占用10+1=11字节
  22.         if (dat < 0)               // 如果为负数,首先取绝对值,并添加负号
  23.         {
  24.                 dat = -dat;
  25.                 *str++ = '-';
  26.                 len++;
  27.         }
  28.         do
  29.         {                               // 低位在前高位在后顺序排列
  30.                 buf[i++] = dat % 10+0x30;        // C语言中数组下标固定从0开始
  31.                 dat /= 10;
  32.         } while (dat > 0);
  33.     len += i;                 // i最后的值就是有效字符的个数
  34.     while (i-- > 0)           // 高位在前低位在后顺序排列
  35.     {
  36.         *str++ = buf[i] ;
  37.     }     
  38.         *str = 0;                 // 添加字符串结束符方便使用KEIL自带的字符串处理函数处理
  39.         return len;               // 返回字符串长度
  40. }

  41.         
  42. //****************温度数据处理函数************************/
  43. void gettemp()                           //读取温度值
  44. {                     
  45.          unsigned int temp0,temp1,temp;      // 存放小数、整数、符号,10000倍小数值
  46.          unsigned char temH,temL;                  // 存放原始高字节与低字节
  47.          unsigned char len;                                          // 温度整数部分字符串长度
  48.          temp=DS18B20_ReadTemperature();         // 从18B20中读取2字节原始温度值
  49.          flag=0;
  50.          if ((temp&0xf800)!=0)                   // 如果是负温,将补码取反加1变为原码
  51.          {
  52.                  temp=~temp        +1;
  53.                  flag=1;
  54.          }        
  55.          temH=temp/256;                                   // 高字节(5位符号+3位数据)
  56.          temL=temp%256;                                   // 低字节(4位整数+4位小数)
  57.          
  58.          temp0=temL&0x0F;              // 4 位小数
  59.      temp1=(temH<<4)|(temL>>4);    // 8 位整数(最高一位符号0不用管)
  60.          
  61.          len=Long_Str(temp1,str);
  62.          str[len++]='.';                           // 添加小数点,覆盖原有字符串结束符0
  63.          temp=temp0*625;               // 将结果中的小数乘以分辨温度0.0625
  64.                                                             // 扩大10000倍进行输出,不用浮点,同样可以保留4位小数精度
  65.          str[len++]= temp/1000+48;                   // 小数点后1位ASCII码
  66.          str[len++]=(temp%1000)/100+48;    // 小数点后2位ASCII码
  67.          str[len++]=(temp%100)/10+48;           // 小数点后3位ASCII码
  68.          str[len++]= temp%10+48;                   // 小数点后4位ASCII码
  69.          str[len]= 0;                                           // 添加字符串结束符
  70. }
  71. void port_mode()            // 端口模式
  72. {
  73.         P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
  74.         P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
  75. }
  76. void main()
  77. {
  78.         unsigned char xPos,yPos;
  79.         unsigned char *s="Now temp is:";
  80.         port_mode();                      // 所有IO口设为准双向弱上拉方式。
  81.         xPos=0;                              // xPos表示水平右移字符数(0-15)
  82.         yPos=0;                              // yPos表示垂直下移字符数(0-1)
  83.         delay100ms();                 // 等待LCD1602上电时内部复位
  84.         LCD1602_Init();
  85.         WriteString(xPos,yPos,s);          // X坐标、Y坐标、字符串,屏幕左上角为坐标原点        
  86.         DS18B20_SetResolution(3);     // 设置DS18B20的分辨率为12位(默认值,新器件可以不作任何设置)
  87.         while(1)
  88.         {
  89.                 gettemp();
  90.                 WriteString(0,1,str);
  91.                 SetCur(NoCur);                  //  有显示无光标
  92.         }
  93. }
复制代码

lcd1602.h文件

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

  11. void delay2_uS ()  // 22.1184MHz
  12. {
  13.     unsigned char t=9;
  14.         while(--t);
  15. }

  16. //        正常读写操作之前检测LCD控制器状态
  17. //  读状态时序:RS=0,RW=1,E=1,判断忙完毕后释放总线
  18. void WaitIdle()
  19. {
  20.         unsigned char tmp;
  21.         RS=0;                          // 命令
  22.         RW=1;                          // 读取
  23.         DPORT=0xff;                  // 为接收数据作准备
  24.         _nop_();          // 短暂延时
  25.         E=1;                   // 使能LCD1602
  26.         delay2_uS();                  // LCD1602在E为高电平区间输出数据到端口
  27.         for(;;)
  28.         {
  29.                 tmp=DPORT;           // 将数据端口上的值赋给tmp
  30.                 tmp&=0x80;           // 最高位为1时表示液晶模块正忙,不能对其进行操作
  31.                 if(        tmp==0)           // 其余6位表示内部当前显示地址,无实际用途。
  32.                         break;
  33.         }
  34.         E=0;                           // 释放总线
  35. }
  36.         
  37. // 向LCD1602液晶写入一字节数据,dat-待写入数据值
  38. // 写数据时序:RS=1,RW=0,D7——D0 = 数据,E=正脉冲,液晶在脉冲下降沿采样数据。
  39. void LcdWriteDat(unsigned char dat)
  40. {
  41.     WaitIdle();                        // 等待LCD1602空闲
  42.         RS=1;                                // 数据
  43.         RW=0;                                // 写
  44.         DPORT=dat;                        // 将待写数据送到数据端口
  45.         _nop_();            // 短暂延时
  46.         E=1;                                // 使能LCD1602
  47.         delay2_uS();                        // LCD1602在E为高电平区间读取数据端口上的值
  48.         E=0;                            // 关闭LCD1602使能,释放总线           
  49. }

  50. // 向LCD1602液晶写入一字节命令,cmd-待写入命令值
  51. // 写命令时序:RS=0,RW=0,D7——D0 = 数据,E=正脉冲,液晶在脉冲下降沿采样数据。
  52. void LcdWriteCmd(unsigned char cmd)
  53. {
  54.     WaitIdle();                        // 等待LCD1602空闲
  55.         RS=0;                                // 命令
  56.         RW=0;                                // 写
  57.         DPORT=cmd;                        // 将命令码输出在数据端口上
  58.         _nop_();            // 短暂延时
  59.         E=1;                                // 使能LCD1602
  60.         delay2_uS();                        // LCD1602在E为高电平区间读取数据端口上的值
  61.         E=0;                                 // 关闭LCD1602使能,释放总线
  62. }

  63. // 清屏命令:清除显示内容,将1602内部RAM全部填入空白的ASCII码20H
  64. //                         光标归位,将光标撤回到屏幕左上角的坐标原点
  65. //           将1602内部显示地址设为0  
  66. void ClrLcd()              
  67. {        
  68.         LcdWriteCmd(0x01);
  69. }

  70. // 内部函数用于设置显示字符起始坐标
  71. void LcdPos(unsigned char xPos,unsigned char yPos)         
  72. {
  73.         unsigned char tmp;
  74.         xPos&=0x0f;                      // x位置范围是0~15
  75.         yPos&=0x01;                      // y位置范围是0~1
  76.         if(yPos==0)                         // 显示第一行
  77.                 tmp=xPos;                  // 第一行字符地址从 0x00 开始
  78.         else
  79.                 tmp=xPos+0x40;          // 第二行字符地址从 0x40 开始
  80.         tmp|=0x80;                          // 设置 RAM 地址
  81.         LcdWriteCmd(tmp);
  82. }

  83. void SetCur(unsigned char Para)            // 设置光标
  84. {
  85.         switch(Para)
  86.         {        
  87.                 case 0:
  88.                 {        
  89.                         LcdWriteCmd(0x08);        break;              // 关显示
  90.                 }
  91.                 case 1:
  92.                 {        
  93.                         LcdWriteCmd(0x0c);        break;             // 开显示但无光标
  94.                 }
  95.                 case 2:
  96.                 {
  97.                         LcdWriteCmd(0x0e);        break;             // 开显示有光标但不闪烁
  98.                 }
  99.                 case 3:
  100.                 {
  101.                         LcdWriteCmd(0x0f);        break;             // 开显示有光标且闪烁
  102.                 }
  103.                 default:
  104.                         break;
  105.         }
  106. }

  107. //在指定的行与列显示指定的字符,xpos:行,ypos:列,c:待显示字符
  108. void WriteChar(unsigned char xPos,unsigned char yPos,unsigned char Dat)
  109. {
  110.         LcdPos(xPos,yPos);
  111.         LcdWriteDat(Dat);
  112. }

  113. // 在液晶上显示字符串,xpos:行坐标,ypos:列坐标,str-字符串指针
  114. void WriteString(unsigned char xPos,unsigned char yPos,unsigned char *s)
  115. {        
  116.         unsigned char i=0;
  117.         LcdPos(xPos,yPos);                  // 起始坐标
  118.         while(s[i])
  119.         {
  120.                 LcdWriteDat(s[i]);
  121.                 i++;
  122.                 if (i>=16)  break;          // 超出16个字符外的数据丢弃
  123.         }
  124. }

  125. // LCD 1602初始化
  126. void LCD1602_Init()            
  127. {
  128.         LcdWriteCmd(0x38);             // 显示模式设置,设置16×2显示,5×7点阵,8位数据接口
  129.         LcdWriteCmd(0x08);             // 显示关闭,不显示光标、光标不闪烁
  130.         LcdWriteCmd(0x01);             // 显示清屏
  131.         LcdWriteCmd(0x06);             // 显示光标移动位置
  132.         LcdWriteCmd(0x0c);             // 显示开及光标设置
  133. }
复制代码



回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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