标题: 单片机DS18b20温度检测程序 [打印本页]

作者: zhangjinyu    时间: 2022-9-21 00:37
标题: 单片机DS18b20温度检测程序
  1. #include<reg51.h>                                  //51单片机的头文件
  2. #define uchar unsigned char           //宏定义,用uchar来代替unsigned char(无符号字符型变量,也即是无符号的8位变量),
  3.                                                                 //宏定义的原因就是书写方便,宏定义后,uchar可直接用来定义变量
  4. #define uint unsigned int                //原因同上,不过要注意,unsigned int为无符号的整型变量

  5. uint present;                    // 实际温度(扩大了10倍)  
  6. uint setting=30;                                 //设定值

  7. sbit led=P3^5;                                        //sbit是用来管脚的。此处定义LED灯由P3.5口控制
  8. sbit buzzer=P3^6;                                //蜂鸣器由P3.6口控制
  9. sbit DS=P3^7;                                        //读取温度引脚

  10. sbit NixieTube0_DIG1=P1^2;                 //        实际温度显示十位数字的数码管位选端
  11. sbit NixieTube0_DIG2=P1^3;                 ////        实际温度显示个位数字的数码管位选端
  12. sbit NixieTube1_DIG1=P1^4;                 ////        设定温度显示十位数字的数码管位选端
  13. sbit NixieTube1_DIG2=P1^5;                 ////        设定温度显示个位数字的数码管位选端
  14.          
  15. sbit add=P1^0; //按键加
  16. sbit sub=P1^1; //按键减

  17. unsigned char code table[]={0x82,0xF3,0x4A,0x62,0x33,0x26,0x06,0xE3,0x02,0x22};        //数码管端码表,相当于显示缓冲区,依次是0——9.



  18. void delay(uint count)     //延时函数,用来进行延时,应该是毫秒级延时
  19. {
  20.   uint i;
  21.   while(count)                          // count为函数的形参,当count为0时,跳出此处while循环
  22.   {
  23.     i=200;
  24.     while(i>0)                         //
  25.     i--;                                 //此i--和while(i>0)可以看成是一个整体,当i=0时,就会跳出,执行count--。
  26.     count--;                          //count自减一次,i就会由200减到0
  27.   }
  28. }
  29. /***********************************************************
  30. void initialize(void)//初始化函数
  31. 温度传感器采用的是DS18b20,此传感器采用的
  32. 是“单总线”来传输数据。
  33. 在使用DS18b20时,要对其进行初始化操作,其初始化的要求是(根据DS18b20的时序图得):
  34. (1)先将数据线置1,但是置1的时间要尽可能短(可以直接忽略此操作,因为51单片机引脚上电默认就是高电平。)。
  35. (2)将数据线(DS)拉低
  36. (3)延时750us左右
  37. (4)再将数据线(DS)拉高
  38. (5)进行短暂延时
  39. *****************************************************************/
  40. void initialize(void)                //初始化
  41. {
  42.                
  43.   uint i;
  44.   DS=0;                //将DS(P3.7)引脚拉低。请注意,这里的DS不是变量,而是单片机的引脚!!!                       
  45.   i=103;
  46.   while(i>0)i--;   //延时
  47.   DS=1;                           //将DS拉高
  48.   i=4;
  49.   while(i>0)i--;   //短暂延时
  50. }
  51. /*************************************************************************************
  52. 说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。
  53. 函数作用:bit tmpreadbit(void)  //温度读取函数,此处读取的是温度的1个bit,带返回值
  54. 函数使用举例:A=tmpreadbit();        // 变量A保存的只是温度的一个bit
  55. DS18B20温度读取时序用单片机来实现的步骤如下:
  56. (1) 数据线DS拉低
  57. (2) 延时6us左右
  58. (3)将数据线DS拉高
  59. (4)延时4us左右
  60. (5) 此时DS便会得到一个状态位,即1个Bit的数据
  61. (6)延时30us左右

  62. **************************************************************************************/
  63. bit tmpreadbit(void)  //温度读取函数,此处读取的是温度的1个bit.带返回值
  64. {
  65.    uint i;
  66.    bit dat;
  67.    DS=0;i++;                  //将数据线拉低并延时
  68.    DS=1;i++;i++;          //将数据线拉高并延时
  69.    dat=DS;                          //读取1个bit数据,此处注意,DS变成了输入引脚,DS18b20的数据会保存到局部变量dat中
  70.    i=8;while(i>0)i--;  //延时
  71.    return (dat);          //将读取的数据返回
  72. }
  73. /***********************************************************************************************
  74. 说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。温度一共8个bit,此函数共读了8次
  75. 函数作用:uchar tmpread(void)  //温度读取函数,此处读取的是温度数据的原始数据,带返回值
  76. 函数使用举例:A=tmpread();        // 变量A保存的是温度的原始数据
  77. *************************************************************************************************/
  78. uchar tmpread(void)
  79. {
  80.   uchar i,j,dat;
  81.   dat=0;
  82.   for(i=1;i<=8;i++)        //采用for 循环,读取原始温度数据
  83.   {
  84.     j=tmpreadbit();         //读取一个位
  85.     dat=(j<<7)|(dat>>1);//读取的温度最低位在前,这样刚好一个字节的温度在dat中
  86.   }
  87.   return(dat);        //将温度数据返回
  88. }

  89. void tmpwritebyte(uchar dat) // 写指令函数, dat为形参。
  90. {
  91.   uint i;
  92.   uchar j;
  93.   bit testb;
  94.   for(j=1;j<=8;j++)        //for循环,8次,刚好写一个字节
  95.   {
  96.     testb=dat&0x01;        //将形参的最低位与1相与,1&1=1,0&1=0;
  97.     dat=dat>>1;                //执行完testb=dat&0x01;把传入的形参右移一位,方便判断下一位数据是0还是1,共移位8次,保证写入一个字节
  98.     if(testb)     //write 1
  99.     {
  100.       DS=0;
  101.       i++;i++;
  102.       DS=1;                         //DS=1的延时比较长,写入的就是1
  103.       i=8;while(i>0)i--;
  104.     }
  105.     else
  106.     {
  107.       DS=0;       //write 0
  108.       i=8;while(i>0)i--;        //DS=0的延时比较长,写入的就是0
  109.       DS=1;
  110.       i++;i++;
  111.     }

  112.   }
  113. }

  114. void tmpchange(void)         //温度转换函数,
  115. {
  116.   initialize();         //初始
  117.   delay(1);
  118.   tmpwritebyte(0xcc); //跳过读ROM指令
  119.   tmpwritebyte(0x44); //告诉DS18b20转换温度
  120. }

  121. uint tmp() //转换函数,将原始数据转化成实际的温度数据      
  122. {
  123.   float tt;
  124.   uchar a,b;
  125.   initialize();         //初始化
  126.   delay(1);                 //延时
  127.   tmpwritebyte(0xcc);//跳过读ROM指令
  128.   tmpwritebyte(0xbe); //读温度指令
  129.   a=tmpread();        // 低8位数据,即温度的小数部分
  130.   b=tmpread(); //高8位,即温度的整数部分
  131.   present=b;
  132.   present<<=8;  //将整数部分右移8位        
  133.   present=present|a;  //将两个字节组合成一个字
  134.   tt=present*0.0625;   //分辨率是0.0625,即原始数据*分辨率=实际温度
  135.   present=tt*10+0.5;   //乘10表示小数点后面只取一位,+0.5是表示四舍五入
  136.   return present;           //返回实际温度
  137. }

  138.         //用的是共阳极数码管,显示原理采用的是动态显示
  139. void display0(uint temp)   //温度显示函数 ,temp 为形参   
  140. {
  141.         uchar A1,A2,A2t;
  142.                                         ////此处注意!因温度读取函数中 present=tt*10+0.5;即将温度扩大了10倍,所以原始温度的十位变成了百位,
  143.                                         //各位变成了十位,十分位变成了个位,因此我们只需取百位上的数字和十位上的数字即可。注意,是数字,不是数!
  144.            A1=temp/100;         //取模,将百位数字取下,存到变量A1中,
  145.         A2t=temp%100;        //取余,比如传进来的temp=325,则325%100=25;
  146.         A2=A2t/10;                //将余数对10取模,比如 25/10=2;
  147.    
  148.     NixieTube0_DIG1=1; //打开数码管位选端
  149.     if(A1<=9|A1>=0)           //判断A1是否位一位数字,实际温度的十位上的数字
  150.     P2=table[A1];          //送入显示
  151.     delay(1);                   //延时,待显示稳定
  152.     NixieTube0_DIG1=0;        // 关断数码管

  153.     NixieTube0_DIG2=1;        //打开数码管位选端
  154.     if(A2<=9|A2>=0)            //判断A2是否位一位数字,实际温度的个位上的数字
  155.     P2=table[A2];                //送入显示
  156.     delay(1);                         //延时,待显示稳定
  157.     NixieTube0_DIG2=0;          // 关断数码管
  158.    

  159. }

  160. void display1(uint spare)   //设定温度显示      
  161. {
  162.     uchar B1,B2;
  163.     B1=spare/10;        //将设定温度对10取模,获取十位上的数字
  164.     B2=spare%10;        //将设定温度对10取余,获取个位上的数字

  165.     NixieTube1_DIG1=1; ////打开数码管位选端
  166.     P2=table[B1];           //送入十位上的数字
  167.     delay(1);                   ////延时,待显示稳定
  168.     NixieTube1_DIG1=0; //关断显示
  169.    
  170.     NixieTube1_DIG2=1;        //打开显示
  171.     P2=table[B2];                //送入个位上的数字
  172.     delay(1);                        //延时,待显示稳定
  173.     NixieTube1_DIG2=0;        //关断显示
  174. }

  175. void main()         //主函数
  176. {
  177.    
  178.         uchar a;
  179.         uchar b;
  180.         uchar c;

  181.         P2=0xf7; //对P2口初始化,开机先不让数码管显示
  182.         NixieTube0_DIG1=1; //初始化,数码管位选端拉高
  183.         NixieTube0_DIG2=1;        //同上
  184.         NixieTube1_DIG1=1;        //同上
  185.         NixieTube1_DIG2=1;        //同上
  186.         buzzer=0; //蜂鸣器引脚拉低,上电,蜂鸣器响一秒
  187.         delay(1000); //延时1S左右

  188.     while(1)
  189.     {
  190.         tmpchange();//向温度传感器写入温度转换指令
  191.         if(add==1)         //如果 按键加 没有按下
  192.                 b=1;         //b=1;b的作用相当于松手检测
  193.         if(add==0&b==1)        //如果按键按下
  194.         {
  195.                         if(setting==99)
  196.                         {}
  197.                         else
  198.                         {
  199.                                 setting++;//设定值自加一次
  200.                             b=0;   //只有按下松手后,再按 按键加 才能再次使设定值自加一次
  201.                         }       
  202.         };
  203.         if(sub==1)        //按键减未被按下
  204.                 c=1;        //作用与b相同
  205.         if(sub==0&c==1)         //如果按键减 被按下
  206.         {
  207.                         if(setting==0)
  208.                         {}
  209.                         else
  210.                         {
  211.                         setting--;//设定值自减一次
  212.                             c=0;   //作用同上面的b
  213.                         }

  214.         };

  215.             if(present<=setting*10)         //如果实际温度小于设定温度
  216.         {
  217.             buzzer=0;                 //蜂鸣器不响
  218.             led=0;                         //灯亮
  219.         }
  220.         else
  221.         {
  222.             buzzer=0;         //否则 蜂鸣器响
  223.                       led=1;                //灯不亮
  224.         }

  225.         for(a=10;a>0;a--)
  226.             {
  227.                 display0(tmp());  //显示实际温度
  228.                 display1(setting); //显示设定温度
  229.         }
  230.     }
  231. }
复制代码







欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1