找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7613|回复: 8
收起左侧

51单片机DS18B20温度计源码(华氏和摄氏度的转换功能)

  [复制链接]
ID:390243 发表于 2018-9-4 10:34 | 显示全部楼层 |阅读模式
利用51单片机DS18B20和1602做的温度计,可以实现温度上限报警,进行华氏和摄氏度的转换,利用三个按键实现这些功能。

单片机源程序如下:
  1. /*作者:王先生
  2. 51单片机:清华电子的板
  3. #include<reg52.h>
  4. #include<intrins.h>
  5. #include<math.h>

  6. typedef unsigned char uchar;
  7. typedef unsigned int  uint;

  8. sbit DS = P2^2;//DS18B20接口
  9. sbit BP = P2^3;//蜂鸣器
  10. sbit DU = P2^6;//数码管段选码
  11. sbit WE = P2^7;//数码管位选码
  12. sbit key_s1 = P3^0;
  13. sbit key_s2 = P3^1;
  14. sbit key_s3 = P3^2;
  15. sbit EN = P3^4;//LCD使能端
  16. sbit RS = P3^5;//LCD数据命令选择端
  17. sbit RW = P3^6;//LCD读写选择端

  18. uint FF;
  19. uint DD,LL;
  20. uint K=0;
  21. uint M=0;
  22. uint s=0;

  23. void delayus(uchar us)
  24. {
  25.     while(us--);//us--要6.5us,进入一次函数11.95us;
  26. } //微秒延时   
  27. void LCD_READ_BUSY() //忙不忙
  28. {
  29.     uchar busy;
  30.     P0 = 0XFF;
  31.     RS = 0;
  32.     RW = 1;
  33.     do
  34.     {
  35.         EN = 1;
  36.         busy = P0;
  37.         EN = 0;
  38.     }while(busy&0X80);
  39.     EN = 1;
  40. }      
  41. void LCD_WRITE_CMD(uchar cmd)//写一个字节命令流程
  42. {
  43.     LCD_READ_BUSY();//判断忙不忙
  44.     RS = 0;
  45.     RW = 0;
  46.     P0 = cmd;
  47.     EN = 1;
  48.     EN = 0;
  49. }
  50. void LCD_WRITE_DATE(uchar dat)//写一个字节数据
  51. {
  52.     LCD_READ_BUSY();
  53.     RS = 1;
  54.     RW = 0;
  55.     P0 = dat;
  56.     EN = 1;
  57.     EN = 0;
  58. }
  59. void LCD_OneChar(uchar x, uchar y,uchar dat)//指定位置显示字符
  60. {
  61.     if(y)   
  62.     x |= 0x40;//位选或
  63.     x |= 0x80;
  64.     LCD_WRITE_CMD(x);
  65.     LCD_WRITE_DATE(dat);        
  66. }
  67. void LCD_Str(uchar x, uchar y, uchar *str)//指定位置显示字符串
  68. {
  69.     if(y)
  70.     x |= 0x40;
  71.     x |= 0x80;
  72.     LCD_WRITE_CMD(x);
  73.     while(*str != '\0')
  74.     {
  75.         LCD_WRITE_DATE(*str++);
  76.     }
  77. }
  78. void LCD_Init()     //    初始化
  79. {
  80.     LCD_WRITE_CMD(0x38); //    设置16*2显示,5*7点阵,8位数据接口
  81.     LCD_WRITE_CMD(0x0c); //开显示
  82.     LCD_WRITE_CMD(0x06); //读写一字节后地址指针加1
  83.     LCD_WRITE_CMD(0x01); //清除显示
  84. }

  85. bit ds_init()//单总线初始化程序
  86. {
  87.     bit  i;
  88.     DS = 1;
  89.     _nop_();
  90.     DS = 0;
  91.     delayus(75);//拉低总线;保持480us以上,75*6.5+11.95=499.45ms
  92.     DS = 1;//释放总线
  93.     delayus(1);//1*6.5+11.95=18.45us等待发回信号(15-60us)
  94.     i = DS;
  95.     delayus(20);//读取存在信号的时间20*6.5+11.95=141.95us
  96.     DS = 1;    //释放总线
  97.     _nop_();
  98.     return(i);//i=0代表DS18B20已经准备好了
  99. }
  100. void displayN(int c)//温度正常显示
  101. {   
  102.     uint i;
  103.     uchar M1,M2,M3,M4;
  104.     uchar TestStr[] = {"Tem:"};
  105.     uchar TestStr1[] = {"DB:WYX"};
  106.     /*if(c<0)
  107.     {m = 2;}
  108.     else if(c>=0)
  109.     {m = 0;}*/
  110.     i = abs(c);
  111.     M1 = i/1000;//千位
  112.     M2 = i%1000/100;//百位
  113.     M3 = i%1000%100/10;//十位
  114.     M4 = i%10;    //个位
  115.             
  116.     DU = 0;
  117.     WE = 0;//关闭数码管显示
  118.     LCD_Init();//1602初始化
  119.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  120.     LCD_Str(0, 1, &TestStr1[0]);    //显示字符串
  121.     LCD_OneChar(6 , 0, 43+s);//正负号
  122.     LCD_OneChar(7, 0, M1+48); //显示温度
  123.     LCD_OneChar(8, 0, M2+48);
  124.     LCD_OneChar(9 , 0, M3+48);//正负号
  125.     LCD_OneChar(10, 0, 46);
  126.     LCD_OneChar(11, 0, M4+48);
  127.     LCD_OneChar(12, 0, 39);
  128.     LCD_OneChar(13, 0, 67);
  129.     LCD_OneChar(15, 0, 78+DD*10);  //显示蜂鸣器开关
  130.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  131. }
  132. void displayM(int c)
  133. {   
  134.     uchar M1,M2,M3,M4;
  135.     int i,m;
  136.     uchar TestStr[] = {"Tem:"};
  137.     uchar TestStr1[] = {"High"};
  138.     if(c<0)
  139.     {m = 2;}
  140.     else if(c>=0)
  141.     {m = 0;}
  142.     i = abs(c);

  143.     M1 = i/1000;//千位
  144.     M2 = i%1000/100;//百位
  145.     M3 = i%1000%100/10;//十位
  146.     M4 = i%10;    //个位
  147.             
  148.     DU = 0;
  149.     WE = 0;//关闭数码管显示
  150.     LCD_Init();//1602初始化
  151.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  152.     LCD_Str(7, 1, &TestStr1[0]);    //显示字符串
  153.     LCD_OneChar(6 , 0, 43+m);//正负号
  154.     LCD_OneChar(7, 0, M1+48); //显示温度
  155.     LCD_OneChar(8, 0, M2+48);
  156.     LCD_OneChar(9 , 0, M3+48);//正负号
  157.     LCD_OneChar(10, 0, 46);
  158.     LCD_OneChar(11, 0, M4+48);
  159.     LCD_OneChar(12, 0, 39);
  160.     LCD_OneChar(13, 0, 67);
  161.     LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
  162.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  163. }
  164. void displayL(int c)
  165. {   
  166.     uchar M1,M2,M3,M4;
  167.     int i,m;
  168.     uchar TestStr[] = {"Tem:"};
  169.     uchar TestStr1[] = {"Low"};
  170.     if(c<0)
  171.     {m = 2;}
  172.     else if(c>=0)
  173.     {m = 0;}
  174.     i = abs(c);
  175.     M1 = i/1000;//千位
  176.     M2 = i%1000/100;//百位
  177.     M3 = i%1000%100/10;//十位
  178.     M4 = i%10;    //个位
  179.         
  180.     DU = 0;
  181.     WE = 0;//关闭数码管显示
  182.     LCD_Init();//1602初始化
  183.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  184.     LCD_Str(7, 1, &TestStr1[0]);    //显示字符串
  185.     LCD_OneChar(6 , 0, 43+m);//正负号
  186.     LCD_OneChar(7, 0, M1+48); //显示温度
  187.     LCD_OneChar(8, 0, M2+48);
  188.     LCD_OneChar(9 , 0, M3+48);//正负号
  189.     LCD_OneChar(10, 0, 46);
  190.     LCD_OneChar(11, 0, M4+48);
  191.     LCD_OneChar(12, 0, 39);
  192.     LCD_OneChar(13, 0, 67);
  193.     LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
  194.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  195. }
  196. void displayNF(int c)
  197. {   
  198.     uchar M1,M2,M3,M4;
  199.     uchar TestStr[] = {"Tem:"};
  200.     uchar TestStr1[] = {"DB:WYX"};
  201.     uint p,i;
  202.     /*if(c<0)
  203.     {m = 2;}
  204.     else
  205.     {m = 0;}*/
  206.     i = abs(c);
  207.     p = i*9/5+320;
  208.     M1 = p/1000;
  209.     M2 = p%1000/100;//百位
  210.     M3 = p%1000%100/10;//十位
  211.     M4 = p%10;    //个位
  212.             
  213.     DU = 0;
  214.     WE = 0;//关闭数码管显示
  215.     LCD_Init();//1602初始化
  216.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  217.     LCD_Str(0, 1, &TestStr1[0]);    //显示字符串
  218.     LCD_OneChar(6 , 0, 43+s);//显示正负
  219.     LCD_OneChar(7, 0, M1+48); //显示温度
  220.     LCD_OneChar(8, 0, M2+48);
  221.     LCD_OneChar(9, 0, M3+48);
  222.     LCD_OneChar(10, 0, 46);
  223.     LCD_OneChar(11, 0, M4+48);
  224.     LCD_OneChar(12, 0, 39);
  225.     LCD_OneChar(13, 0, 67+FF);
  226.     LCD_OneChar(15, 0, 78+DD*10);  //显示蜂鸣器开关
  227.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  228. }
  229. void displayMF(int c)
  230. {   
  231.     uchar M1,M2,M3,M4;
  232.     uchar TestStr[] = {"Tem:"};
  233.     uchar TestStr1[] = {"High"};
  234.     uint p,m,i;
  235.     if(c<0)
  236.     {m = 2;}
  237.     else
  238.     {m = 0;}
  239.     i = abs(c);
  240.     p = i*9/5+320;
  241.     M1 = p/1000;
  242.     M2 = p%1000/100;//百位
  243.     M3 = p%1000%100/10;//十位
  244.     M4 = p%10;    //个位
  245.             
  246.     DU = 0;
  247.     WE = 0;//关闭数码管显示
  248.     LCD_Init();//1602初始化
  249.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  250.     LCD_Str(7, 1, &TestStr1[0]);    //显示字符串
  251.     LCD_OneChar(6 , 0, 43+m);//显示正负
  252.     LCD_OneChar(7, 0, M1+48); //显示温度
  253.     LCD_OneChar(8, 0, M2+48);
  254.     LCD_OneChar(9, 0, M3+48);
  255.     LCD_OneChar(10, 0, 46);
  256.     LCD_OneChar(11, 0, M4+48);
  257.     LCD_OneChar(12, 0, 39);
  258.     LCD_OneChar(13, 0, 67+FF);
  259.     LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
  260.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  261. }
  262. void displayLF(int c)
  263. {   
  264.     uchar M1,M2,M3,M4;
  265.     uchar TestStr[] = {"Tem:"};
  266.     uchar TestStr1[] = {"Low"};
  267.     uint p,m,i;
  268.     if(c<0)
  269.     {m = 2;}
  270.     else
  271.     {m = 0;}
  272.     i = abs(c);
  273.     p = i*9/5+320;
  274.     M1 = p/1000;
  275.     M2 = p%1000/100;//百位
  276.     M3 = p%1000%100/10;//十位
  277.     M4 = p%10;    //个位
  278.             
  279.     DU = 0;
  280.     WE = 0;//关闭数码管显示
  281.     LCD_Init();//1602初始化
  282.     LCD_Str(0, 0, &TestStr[0]);    //显示字符串
  283.     LCD_Str(7, 1, &TestStr1[0]);    //显示字符串
  284.     LCD_OneChar(6 , 0, 43+m);//显示正负
  285.     LCD_OneChar(7, 0, M1+48); //显示温度
  286.     LCD_OneChar(8, 0, M2+48);
  287.     LCD_OneChar(9, 0, M3+48);
  288.     LCD_OneChar(10, 0, 46);      //.
  289.     LCD_OneChar(11, 0, M4+48);
  290.     LCD_OneChar(12, 0, 39);      //'
  291.     LCD_OneChar(13, 0, 67+FF);//C或F
  292.     LCD_OneChar(15, 0, 78+DD*10);//X或者N
  293.     LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  294. }
  295. void displayLE()
  296. {
  297.      uchar TestSt1[] = {"Error"};
  298.      uchar TestSt2[] = {"Low#High"};
  299.      LCD_Init();
  300.      LCD_Str(5, 0, &TestSt1[0]);
  301.      LCD_Str(4, 1, &TestSt2[0]);
  302.      LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
  303.      LCD_OneChar(15, 1, 78+LL*10);  //显示指示灯开关
  304.      
  305. }
  306. void write_byte(uchar dat)//写一个字节
  307. {
  308.     uchar i;
  309.     for(i=0;i<8;i++)//一次写一位,一个字节循环8次
  310.     {
  311.         DS = 0;
  312.         _nop_();//产生写时序(15US内满足要求)
  313.         DS = dat&0X01; //与
  314.         delayus(9);//延时大于60US 9*6.5+11.95=70.45us 同时满足写0写1
  315.         DS = 1;//释放总线
  316.         _nop_();
  317.         dat>>=1;//右移一位
  318.     }
  319. }

  320. uchar read_byte()//读一个字节
  321. {
  322.     uchar i,j,dat;
  323.     for(i=0;i<8;i++)
  324.     {
  325.         DS = 0;
  326.         _nop_();//产生读时序
  327.         DS = 1;
  328.         _nop_();//释放总线
  329.         j = DS;
  330.         delayus(9);//读取数据大于60US 9*6.5+11.95=70.45us
  331.         DS = 1;
  332.         _nop_();
  333.         dat = (j<<7)|(dat>>1);
  334.     }
  335.     return(dat);
  336. }
  337. void beep(int m,gao,di)//按键与警报程序
  338. {   
  339.     if(m>=gao)
  340.     {
  341.         if(di<=gao)      //判断最低报警温度是否低于最高报警温度
  342.         {
  343.             BP = DD;
  344.             P1 = 0XEE+LL*0X11;
  345.         }
  346.         else if(di>gao)
  347.         {
  348.             BP = 1;
  349.             P1 = 0X7E+LL*0X81;
  350.         }
  351.     }
  352.     else if(m<=di)
  353.     {
  354.         if(di<=gao)      //判断最低报警温度是否低于最高报警温度
  355.         {
  356.             BP = DD;
  357.             P1=0X77+LL*0X88;
  358.         }
  359.         else if(di>gao)
  360.         {
  361.             BP = 1;
  362.             P1 = 0X7E+LL*0X81;
  363.         }

  364.     }
  365.     else
  366.     {
  367.         if(di<=gao)     //判断最低报警温度是否低于最高报警温度
  368.         {
  369.             BP = 1;
  370.             P1=0XBB+LL*0X44;
  371.         }
  372.         else if(di>gao)
  373.         {
  374.             BP = 1;
  375.             P1 = 0X7E+LL*0X81;
  376.         }
  377.     }
  378. }

  379. void main()
  380. {
  381.     int i,h;
  382.     uint j=0;
  383.     float t;
  384.     int gao=330,di=270;
  385.     uchar L,H;
  386.     while(1)
  387.     {
  388.         ds_init();//初始化函数
  389.         write_byte(0XCC);//发送跳跃ROM指令(0xcc)
  390.         write_byte(0X44);//发送温度转换指令(0X44)
  391.         ds_init();//初始化DS18B20
  392.         write_byte(0XCC);//发送跳跃ROM指令(0xcc)
  393.         write_byte(0XBE);//读取DS18B20暂存器的值(0Xbe)
  394.         L = read_byte(); //温度低字节
  395.         H = read_byte();//温度高字节
  396.         i = H;
  397.         i <<=8;
  398.         i|=L;//与,把L写到低字节里
  399.         if(H >= 0x08)    //判断是否为负数
  400.         {
  401.             i = ~i + 1;//负数是以补码的形式存放的需要我们需要取反加1
  402.             s = 2;  //显示负数符号
  403.         }
  404.         else s = 0;
  405.         t=i*0.0625;
  406.         i = t*10;//10.125--101.25--101.75--10.2(四舍五入)
  407.         
  408.         if(key_s1 == 0)    //第一位选程序
  409.         {
  410.             delayus(10);//防抖
  411.             if(key_s1 == 0)
  412.             {
  413.                 j=j+1 ;
  414.                 if(j>=3)
  415.                 j=0;
  416.             }
  417.             while(!key_s1);
  418.         }
  419.         if(j==1) //调最高温度
  420.         {
  421.             h = gao;
  422.             if(key_s2 == 0)//按键2增加温度
  423.             {
  424.                 delayus(20);//防抖
  425.                 if(key_s2 == 0)
  426.                 {
  427.                     h=h+1 ;
  428.                 }
  429.                 while(!key_s2);
  430.             }
  431.             else if(key_s3 == 0)//按键3减小温度
  432.             {
  433.                 delayus(20);
  434.                 if(key_s3 == 0)
  435.                 {
  436.                     h=h-1;
  437.                 }
  438.                 while(!key_s3);
  439.             }
  440.             if(K==0)
  441.             {
  442.                 displayM(h);
  443.             }
  444.             else if(K==1)
  445.             {
  446.             //    p = h*(5/9)+320;
  447.                 displayMF(h);
  448.             }
  449.             gao = h;
  450.         }   
  451.         else if(j==2)//调最低温度        
  452.         {
  453.             h = di;
  454.             if(key_s2 == 0)//按键2增加温度
  455.             {
  456.                 delayus(20);//防抖
  457.                 if(key_s2 == 0)
  458.                 {
  459.                     h=h+1 ;
  460.                 }
  461.                 while(!key_s2);
  462.             }
  463.             else if(key_s3 == 0)//按键3减小温度
  464.             {
  465.                 delayus(20);
  466.                 if(key_s3 == 0)
  467.                 {
  468.                     h=h-1;
  469.                 }
  470.                 while(!key_s3);
  471.             }
  472.             if(K==0)
  473.             {
  474.                 displayL(h);
  475.             }
  476.             else if(K==1)
  477.             {
  478.             //    p = h*(5/9)+320;
  479.                 displayLF(h);
  480.             }
  481.             di = h;
  482.          }
  483.         else if(j==0) //显示温度
  484.         {   
  485.             if(key_s2 == 0)//温度转化
  486.             {
  487.                 delayus(20);//防抖
  488.                 if(key_s2 == 0)
  489.                 {
  490.                     K=K+1 ;
  491.                     if(K>1)
  492.                     K=0;
  493.                 }
  494.                 while(!key_s2);
  495.             }
  496.             if(key_s3 == 0)//蜂鸣器与指示灯开关
  497.             {
  498.                 delayus(20);//防抖
  499.                 if(key_s3 == 0)
  500.                 {
  501.                     M=M+1 ;
  502.                     if(M>3)
  503.                     M=0;
  504.                 }
  505.                 while(!key_s3);
  506.             }
  507.             if(K==0)
  508.             {
  509.                  FF=0;       //摄氏度
  510.             }
  511.             else if(K==1)
  512.             {
  513.                 FF=3;       //华氏
  514.             }
  515. /****************判断蜂鸣器与指示灯开关程序*******************/
  516.             if(M==0)       //蜂鸣器关指示灯开
  517.             {
  518.                  DD=1;
  519.                 LL=0;       //蜂鸣器关
  520.             }
  521.             else if(M==1)  //蜂鸣器开指示灯开
  522.             {
  523.                 DD=0;
  524.                 LL=0;      
  525.             }
  526.             else if(M==2)  //蜂鸣器开指示灯关
  527.             {
  528.                 DD=0;
  529.                 LL=1;
  530.             }
  531.             else if(M==3)  //蜂鸣器关指示灯关
  532.             {
  533.                 DD=1;
  534.                 LL=1;
  535.             }
  536. /*****************温度显示及判断程序执行*****************/
  537.             if(K==0)       //选择显示摄氏度
  538.             {
  539.                 if(di>gao)
  540.                 displayLE();
  541.                 else if(di<=gao)
  542.                 displayN(i);
  543.             }
  544.             else if(K==1)  //选择显示华氏
  545.             {
  546.                 if(di>gao)
  547.                 displayLE();
  548.                 else if(di<=gao)
  549.                 displayNF(i);
  550.             }
  551.             beep(i,gao,di);//报警判断
  552.         }
  553.     }
  554. }
  555. //打开是85.0,因为初始值是85.

复制代码

评分

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

查看全部评分

回复

使用道具 举报

ID:420008 发表于 2018-11-3 10:15 | 显示全部楼层
lz你的板子是哪一个?
回复

使用道具 举报

ID:390243 发表于 2018-11-24 12:42 | 显示全部楼层
这个板子就是TB上的清翔电子的51板子
回复

使用道具 举报

ID:671488 发表于 2019-12-29 00:01 | 显示全部楼层
真好的程序
回复

使用道具 举报

ID:717683 发表于 2021-6-23 08:49 来自手机 | 显示全部楼层
有没有原理图
回复

使用道具 举报

ID:1034617 发表于 2022-6-14 13:49 | 显示全部楼层
请问有没有原理图呀~
回复

使用道具 举报

ID:1081665 发表于 2023-6-2 18:52 | 显示全部楼层
有没有仿真图呀
回复

使用道具 举报

ID:1083179 发表于 2023-6-10 12:26 来自手机 | 显示全部楼层
电子加油 发表于 2023-6-2 18:52
有没有仿真图呀

你好,仿真图找到了吗?分享一下可以吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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