找回密码
 立即注册

QQ登录

只需一步,快速开始

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

详细的程序分析:编程实现单片机ds18b20温度测量及显示系统

  [复制链接]
跳转到指定楼层
楼主
ID:298068 发表于 2018-3-27 23:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
编程实现基于单片机的温度测量及显示系统

  • 利用开发板上的ds18b20传感器测量当前温度,利用数码管输出当前温度值。
实现结果:
测试结果显示当前摄氏温度25.3度。
实现原理:
(1)独立数码管
数码管分为共阳极和共阴极数码管,
通过控制数码管中的8个二极管,来显示数字。
(2)多位共阴数码管和共阳数码管
本项目使用的是6位共阴数码管。
数码管控制主要通过段锁存和位锁存控制显示要显示的数字如温度。段锁存是指6位共阴极数码管段输出端连接锁存器74HC573的输出端,锁存器的输入端连接单片机接口P0。位锁存是指6位数码管位置输出端连接锁存器74HC573的输出端,锁存器的输入端连接单片机接口P0。段锁存器片选端接单片机接口P2.6,位锁存器片选端接单片机接口P2.7。
连接图如下:




程序分析:温度传感器DS18B20接单片机P2.2,段锁存接P2.6,位锁存接P2.7,unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
显示段码值0~9,Unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
分别对应相应的数码管点亮,即位码。
温度传感器的程序有测温的程序,测得的温度通过数码管显示出来。其中使用了延时和中断子程序。
  • 用液晶屏1602实现温度显示。
  • 利用按键实现摄氏温度和华氏温度的转换,并显示。
实现结果:
按下S2,显示摄氏温度如下
按下S2,显示华氏温度如下


实现原理:
在之前的温度显示模块加入按键功能程序,利用两种温度转换公式华氏温度=(摄氏温度*9/5)+32实现转换。
相关程序如下:
  1. void display(uint temp,uint hstemp)                                          //显示程序
  2. {

  3.    if(s2==0)                           
  4.    {

  5.    ser=temp/10;
  6.    SBUF=ser;
  7.    A1=temp/100;
  8.    A2t=temp%100;
  9.    A2=A2t/10;
  10.    A3=A2t%10;
  11.    dula=0;
  12.    P0=table[A1];                            //显示百位
  13.    dula=1;
  14.    dula=0;

  15.    wela=0;
  16.    P0=0x7e;
  17.    wela=1;
  18.    wela=0;
  19.    delay(1);

  20.    dula=0;
  21.    P0=table1[A2];                            //显示十位
  22.    dula=1;
  23.    dula=0;

  24.    wela=0;
  25.    P0=0x7d;
  26.    wela=1;
  27.    wela=0;
  28.    delay(1);

  29.    P0=table[A3];                            //显示个位
  30.    dula=1;
  31.    dula=0;

  32.    P0=0x7b;
  33.    wela=1;
  34.    wela=0;
  35.    delay(1);
  36.    }
  37.    if(s3==0)
  38.    {
  39.             
  40.    ser1=hstemp/10;
  41.    SBUF=ser1;
  42.    A11=hstemp/100;
  43.    A21t=hstemp%100;
  44.    A21=A21t/10;
  45.    A31=A21t%10;
  46.    dula=0;
  47.    P0=table[A11];                            //显示百位
  48.    dula=1;
  49.    dula=0;

  50.    wela=0;
  51.    P0=0x7e;
  52.    wela=1;
  53.    wela=0;
  54.    delay(1);

  55.    dula=0;
  56.    P0=table1[A21];                            //显示十位
  57.    dula=1;
  58.    dula=0;

  59.    wela=0;
  60.    P0=0x7d;
  61.    wela=1;
  62.    wela=0;
  63.    delay(1);

  64.    P0=table[A31];                            //显示个位
  65.    dula=1;
  66.    dula=0;

  67.    P0=0x7b;
  68.    wela=1;
  69.    wela=0;
  70.    delay(1);
  71.    }
  72. }
复制代码

程序分析:s2,s3代表按键分别接在单片机P3.4,p3.5上,当按键按下时单片机相应接口显示低电平,松开显示高电平。当检测到S2按下时,显示摄氏温度。当检测到S3按下时,显示华氏温度。主程序如下:
if(s2==0)
  {
  SendByte(A1*10+A2);
  SendStr(".");
  SendByte(A3);

  }
  if(s3==0)
  {            
                SendByte(A11*10+A21);
                 SendStr(".");
  SendByte(A3);
  }
  • 利用串口将当前温度值发送至电脑,电脑端利用串口助手进行接收和显示。
实现原理:
连接好串口或者usb转串口至电脑,下载该程序,打开电源, 打开串口调试程序,将波特率设置为9600,无奇偶校验,晶振11.0592MHz,发送和接收使用的格式相同。
串口通讯程序包括串口初始化,输出字节函数,输出字符串函数,主函数。温度传感器测得的温度数值通过串口通讯程序输出显示在电脑上。
实现结果:
当按下S2按键,电脑显示如下:
发送和接收都是16进制,1B=1*16+11*1=27,2E代表小数点,01=1,所以显示温度27.2摄氏度。
当按下S3按键,电脑显示如下:
发送和接收都是16进制,51=5*16+1*1=81,2E代表小数点,03=3,所以显示温度81.3华氏。

单片机源程序如下:
  1. //安装目录下的EXE文件打开后可在电脑上显示当前温度值
  2. #include <reg52.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit DS=P2^2;           //define interface
  6. uint temp;             // variable of temperature
  7. uchar flag1;            // sign of the result positive or negative
  8. sbit dula=P2^6;
  9. sbit wela=P2^7;
  10. sbit s2=P3^4;
  11. sbit s3=P3^5;
  12. uchar A1,A2,A2t,A3,ser,A11,A21,A21t,A31,ser1;
  13. unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
  14.                         0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
  15. unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
  16.                         0x87,0xff,0xef};


  17. void SendStr(unsigned char *s);
  18. /*------------------------------------------------
  19.                     串口初始化
  20. ------------------------------------------------*/
  21. void InitUART  (void)
  22. {

  23.     SCON  = 0x50;                                    // SCON: 模式 1, 8-bit UART, 使能接收
  24.     TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
  25.     TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz
  26.     TR1   = 1;                  // TR1:  timer 1 打开                        
  27.     EA    = 1;                  //打开总中断
  28.     //ES    = 1;                  //打开串口中断
  29. }        
  30. void delay(uint count)      //delay
  31. {
  32.   uint i;
  33.   while(count)
  34.   {
  35.     i=200;
  36.     while(i>0)
  37.     i--;
  38.     count--;
  39.   }
  40. }
  41. void DelayUs2x(unsigned char t)
  42. {  
  43. while(--t);
  44. }
  45. /*------------------------------------------------
  46. mS延时函数,含有输入参数 unsigned char t,无返回值
  47. unsigned char 是定义无符号字符变量,其值的范围是
  48. 0~255 这里使用晶振12M,精确延时请使用汇编
  49. ------------------------------------------------*/
  50. void DelayMs(unsigned char t)
  51. {

  52. while(t--)
  53. {
  54.      //大致延时1mS
  55.      DelayUs2x(245);
  56.               DelayUs2x(245);
  57. }
  58. }
  59. ///////功能:串口初始化,波特率9600,方式1///////
  60. void Init_Com(void)
  61. {
  62.      TMOD = 0x20;
  63.      PCON = 0x00;
  64.      SCON = 0x50;
  65.      TH1 = 0xFd;
  66.      TL1 = 0xFd;
  67.      TR1 = 1;
  68. }

  69. void dsreset(void)       //send reset and initialization command
  70. {
  71.   uint i;
  72.   DS=0;
  73.   i=103;
  74.   while(i>0)i--;
  75.   DS=1;
  76.   i=4;
  77.   while(i>0)i--;
  78. }

  79. bit tmpreadbit(void)       //read a bit
  80. {
  81.    uint i;
  82.    bit dat;
  83.    DS=0;i++;          //i++ for delay
  84.    DS=1;i++;i++;
  85.    dat=DS;
  86.    i=8;while(i>0)i--;
  87.    return (dat);
  88. }

  89. uchar tmpread(void)   //read a byte date
  90. {
  91.   uchar i,j,dat;
  92.   dat=0;
  93.   for(i=1;i<=8;i++)
  94.   {
  95.     j=tmpreadbit();
  96.     dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好一个字节在DAT里
  97.   }
  98.   return(dat);
  99. }

  100. void tmpwritebyte(uchar dat)   //write a byte to ds18b20
  101. {
  102.   uint i;
  103.   uchar j;
  104.   bit testb;
  105.   for(j=1;j<=8;j++)
  106.   {
  107.     testb=dat&0x01;
  108.     dat=dat>>1;
  109.     if(testb)     //write 1
  110.     {
  111.       DS=0;
  112.       i++;i++;
  113.       DS=1;
  114.       i=8;while(i>0)i--;
  115.     }
  116.     else
  117.     {
  118.       DS=0;       //write 0
  119.       i=8;while(i>0)i--;
  120.       DS=1;
  121.       i++;i++;
  122.     }

  123.   }
  124. }

  125. void tmpchange(void)  //DS18B20 begin change
  126. {
  127.   dsreset();
  128.   delay(1);
  129.   tmpwritebyte(0xcc);  // address all drivers on bus
  130.   tmpwritebyte(0x44);  //  initiates a single temperature conversion
  131. }

  132. uint tmp()               //get the temperature
  133. {
  134.   float tt;
  135.   uchar a,b;
  136.   dsreset();
  137.   delay(1);
  138.   tmpwritebyte(0xcc);
  139.   tmpwritebyte(0xbe);
  140.   a=tmpread();
  141.   b=tmpread();
  142.   temp=b;
  143.   temp<<=8;             //two byte  compose a int variable
  144.   temp=temp|a;
  145.   tt=temp*0.0625;
  146.   temp=tt*10+0.5;
  147.   return temp;
  148. }

  149. void readrom()          //read the serial
  150. {
  151.   uchar sn1,sn2;
  152.   dsreset();
  153.   delay(1);
  154.   tmpwritebyte(0x33);
  155.   sn1=tmpread();
  156.   sn2=tmpread();
  157. }


  158. void delay10ms()            //delay
  159.   {
  160.     uchar a,b;
  161.     for(a=10;a>0;a--)
  162.       for(b=60;b>0;b--);
  163.    }

  164. void display(uint temp,uint hstemp)                                          //显示程序
  165. {

  166.    if(s2==0)                           
  167.    {

  168.    ser=temp/10;
  169.    SBUF=ser;
  170.    A1=temp/100;
  171.    A2t=temp%100;
  172.    A2=A2t/10;
  173.    A3=A2t%10;
  174.    dula=0;
  175.    P0=table[A1];                            //显示百位
  176.    dula=1;
  177.    dula=0;

  178.    wela=0;
  179.    P0=0x7e;
  180.    wela=1;
  181.    wela=0;
  182.    delay(1);

  183.    dula=0;
  184.    P0=table1[A2];                            //显示十位
  185.    dula=1;
  186.    dula=0;

  187.    wela=0;
  188.    P0=0x7d;
  189.    wela=1;
  190.    wela=0;
  191.    delay(1);

  192.    P0=table[A3];                            //显示个位
  193.    dula=1;
  194.    dula=0;

  195.    P0=0x7b;
  196.    wela=1;
  197.    wela=0;
  198.    delay(1);
  199.    }
  200.    if(s3==0)
  201.    {
  202.             
  203.    ser1=hstemp/10;
  204.    SBUF=ser1;
  205.    A11=hstemp/100;
  206.    A21t=hstemp%100;
  207.    A21=A21t/10;
  208.    A31=A21t%10;
  209.    dula=0;
  210.    P0=table[A11];                            //显示百位
  211.    dula=1;
  212.    dula=0;

  213.    wela=0;
  214.    P0=0x7e;
  215.    wela=1;
  216.    wela=0;
  217.    delay(1);

  218.    dula=0;
  219.    P0=table1[A21];                            //显示十位
  220.    dula=1;
  221.    dula=0;

  222.    wela=0;
  223.    P0=0x7d;
  224.    wela=1;
  225.    wela=0;
  226.    delay(1);

  227.    P0=table[A31];                            //显示个位
  228.    dula=1;
  229.    dula=0;

  230.    P0=0x7b;
  231.    wela=1;
  232.    wela=0;
  233.    delay(1);
  234.    }
  235. }

  236. void SendByte(unsigned char dat)
  237. {
  238. SBUF = dat;
  239. while(!TI);
  240.       TI = 0;
  241. }
  242. void main()
  243. {
  244. uchar a;
  245. InitUART();
  246. Init_Com();
  247.   do
  248.   {
  249.     tmpchange();

  250. for(a=10;a>0;a--)
  251.   {   display(tmp(),(tmp()*9/5)+320);
  252. // delay(200);
  253.   }
  254.   if(s2==0)
  255.   {
  256.   SendByte(A1*10+A2);
  257.   SendStr(".");
  258.   SendByte(A3);

  259.   }
  260.   if(s3==0)
  261.   {            
  262.                 SendByte(A11*10+A21);
  263.                  SendStr(".");
  264.   SendByte(A3);
  265.   }

  266.               DelayMs(240);//延时循环发送
  267.     DelayMs(240);
  268.   }                while(1);
  269. }

  270. /*------------------------------------------------
  271.                     发送一个字符串
  272. ------------------------------------------------*/
  273. void SendStr(unsigned char *s)
  274. {
  275. while(*s!='\0')// \0 表示字符串结束标志,
  276.                 //通过检测是否字符串末尾
  277.   {
  278.   SendByte(*s);
  279.   s++;
  280.   }
  281. }

  282. 液晶显示温度程序
  283. #include <reg52.H>
  284. #include <intrins.H>
  285. #include <math.H>

  286. #define uchar unsigned char
  287.   #define uint unsigned int
  288. sbit dula = P2^6;
  289. sbit wela = P2^7;

  290. sbit RS = P3^5;   
  291. sbit LCDEN = P3^4;

  292. void delayUs()
  293. {
  294.     _nop_();
  295. }

  296. void delayMs(uint a)
  297. {
  298.     uint i, j;
  299.     for(i = a; i > 0; i--)
  300.         for(j = 100; j > 0; j--);
  301. }


  302. void writeComm(uchar comm)
  303. {
  304.      RS = 0;   
  305.     P0 = comm;
  306.     LCDEN = 1;
  307.      delayUs();
  308.     LCDEN = 0;
  309.     delayMs(1);
  310. }

  311. //写数据:RS=1, RW=0;
  312. void writeData(uchar dat)
  313. {
  314.      RS = 1;
  315.      P0 = dat;
  316.      LCDEN = 1;
  317.     delayUs();
  318.     LCDEN = 0;
  319.     delayMs(1);
  320. }


  321. void init()
  322. {

  323.      dula = wela = 0;
  324.     writeComm(0x38);
  325.    writeComm(0x0c);
  326.     writeComm(0x06);
  327.     writeComm(0x01);
  328. }

  329. void writeString(uchar * str, uchar length)
  330. {
  331.      uchar i;
  332.     for(i = 0; i < length; i++)
  333.     {
  334.          writeData(str[i]);
  335.      }
  336. }

  337. /**//*****************************DS18B20*******************************/
  338. sbit ds = P2^2;
  339. void dsInit()
  340. {

  341.     unsigned int i;
  342.     ds = 0;
  343.     i = 100;
  344.      while(i>0) i--;
  345.     ds = 1;  
  346.     i = 4;
  347.      while(i>0) i--;
  348. }

  349. void dsWait()
  350. {
  351.       unsigned int i;
  352.       while(ds);
  353.       while(~ds);
  354.       i = 4;
  355.       while(i > 0) i--;
  356. }


  357. bit readBit()
  358. {
  359.     unsigned int i;
  360.     bit b;
  361.     ds = 0;
  362.     i++;  
  363.     ds = 1;
  364.    i++; i++;
  365.     b = ds;
  366.     i = 8;
  367.     while(i>0) i--;
  368.     return b;
  369. }

  370. unsigned char readByte()
  371. {
  372.     unsigned int i;
  373.     unsigned char j, dat;
  374.    dat = 0;
  375.     for(i=0; i<8; i++)
  376.     {
  377.         j = readBit();

  378.         dat = (j << 7) | (dat >> 1);
  379.     }
  380.     return dat;
  381. }


  382. void writeByte(unsigned char dat)
  383. {
  384.     unsigned int i;
  385.     unsigned char j;
  386.     bit b;
  387.     for(j = 0; j < 8; j++)
  388.     {
  389.         b = dat & 0x01;
  390.         dat >>= 1;

  391.         if(b)  
  392.         {
  393.            ds = 0;          i++; i++;
  394.             ds = 1;   
  395.             i = 8; while(i>0) i--;
  396.         }
  397.         else
  398.         {
  399.             ds = 0;
  400.           i = 8; while(i>0) i--;
  401.             ds = 1;
  402.            i++; i++;
  403.         }
  404.    }
  405. }


  406. void sendChangeCmd()
  407. {
  408.     dsInit();   
  409.     dsWait();  
  410.     delayMs(1);   
  411.     writeByte(0xcc);
  412.     writeByte(0x44);
  413. }

  414. void sendReadCmd()
  415. {
  416.     dsInit();
  417.     dsWait();
  418.     delayMs(1);
  419.     writeByte(0xcc);
  420.     writeByte(0xbe);
  421. }


  422. int getTmpValue()
  423. {
  424.     unsigned int tmpvalue;
  425.     int value;
  426.     float t;
  427.     unsigned char low, high;
  428.     sendReadCmd();

  429.     low = readByte();
  430.     high = readByte();

  431.     tmpvalue = high;
  432.     tmpvalue <<= 8;
  433.     tmpvalue |= low;
  434.     value = tmpvalue;

  435.   \
  436.     t = value * 0.0625;
  437.     \
  438.     value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
  439.     return value;
  440. }

  441. void display(int v)
  442. {
  443.     unsigned char count;
  444.     unsigned char datas[] = {0, 0, 0, 0, 0};
  445.     unsigned int tmp = abs(v);
  446.     datas[0] = tmp / 10000;
  447.     datas[1] = tmp % 10000 / 1000;
  448.     datas[2] = tmp % 1000 / 100;
  449.     datas[3] = tmp % 100 / 10;
  450.     datas[4] = tmp % 10;
  451.     writeComm(0xc0+3);
  452.     if(v < 0)
  453.     {
  454.         writeString("- ", 2);
  455.    }
  456.     else
  457.     {
  458.        writeString("+ ", 2);
  459.     }
  460.     if(datas[0] != 0)
  461.     {
  462.         writeData('0'+datas[0]);
  463.     }
  464.     for(count = 1; count != 5; count++)
  465.     {
  466.         writeData('0'+datas[count]);
  467.         if(count == 2)
  468. ……………………

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

所有资料51hei提供下载:
单片机的温度测量及显示系统.docx (1.66 MB, 下载次数: 68)


评分

参与人数 2黑币 +55 收起 理由
why___1997 + 5
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:359772 发表于 2018-6-26 23:14 | 只看该作者
非常感谢分享
回复

使用道具 举报

板凳
ID:359889 发表于 2018-6-27 08:49 | 只看该作者
GANXIE
回复

使用道具 举报

地板
ID:437709 发表于 2018-12-2 16:02 | 只看该作者
谢谢楼主的分享,现在我已经大致明白了单片机内部这个部件的构造了,但可能我们的板子不一样,还有你的一些变量名我看不懂,我还是要好好学习才行。
回复

使用道具 举报

5#
ID:686251 发表于 2020-1-16 19:54 | 只看该作者
感谢分享
回复

使用道具 举报

6#
ID:915491 发表于 2022-6-24 11:39 | 只看该作者
可以使用,代码详细
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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