找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6804|回复: 3
收起左侧

DS18B20无线多点测温单片机程序

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

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(在这贴附件中可下载ds18b20无线多点测温的完整源码压缩包)
单片机下位机主程序如下(部分预览):

  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. //18B20多点测温程序,11.0592M晶振
  11. #include "STC15W4K.H"
  12. #include "usart.h"
  13. #include "ds18b20.h"
  14. #define CONVERT 0x44        // 收主机转换温度命令
  15. #define GETTEMP 0xaa        // 收主机读温度命令
  16. #define GETHOUSE 0xcc       // 收主机读仓库湿度命令
  17. #define GETAREA 0xd6        // 收主机读库区湿度命令
  18. #define GETSTATE 0x11       // 收主机通信检测命令
  19. #define SENDAREA 0xdd       // 向主机发库区湿度
  20. #define SENDHOUSE 0xce      // 向主机发仓库湿度
  21. #define CVTOK 0x88          // 向主机发转换温度完毕命令
  22. #define CPUOK 0x22                        // 向主机发通信正常命令
  23. #define TEMPDATA 0xbb       // 向主机发温度命令         
  24. unsigned char Port,Pin,count=0;         //单片机端口P0、P1、P2、P3,端口具体引脚(1-8),接收计数器

  25. unsigned char send_buff[14];          // 发送缓冲区14字节,加帧头帧尾共16字节每帧
  26. unsigned char ReceivdID_buff[8];  // 存储主机发来的rom ID为8字节
  27. unsigned char receivedcmd[16];    // 存放接收到的命令 1:帧头,2发送机号,3本机ID,4命令,5port,6pin,7-14ID,15CRC,16帧尾
  28. unsigned char temp_buff[9];       // 存储读取的温度字节,读温度为9字节,读rom ID为8字节

  29. unsigned char code CrcTable [256]={
  30. 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
  31. 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
  32. 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
  33. 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
  34. 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
  35. 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
  36. 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
  37. 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
  38. 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
  39. 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
  40. 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
  41. 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
  42. 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
  43. 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
  44. 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
  45. 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};       

  46. //反序CRC查表校验
  47. unsigned char crc8_f_table (unsigned char *ptr, unsigned char len)
  48. {
  49.         unsigned char i;
  50.         unsigned char crc =0;
  51.         for(i=0;i<len;i++)               // 查表校验
  52.         {
  53.                 crc= CrcTable[crc^ptr[i]];   // ^是按位异或运算符
  54.         }
  55.         return(crc);
  56. }
  57. void port_mode()            // 端口模式
  58. {
  59.         P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
  60.         P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
  61. }
  62. void main()         
  63. {
  64.         unsigned char i;
  65.         unsigned char crccount;          // crc校验次数       
  66.         unsigned char crc_data;          // crc校验结果
  67.         port_mode();                  // 所有IO口设为准双向弱上拉方式。
  68.         com_init();                              // 串口初始化        
  69.         while(1)
  70.         {                       
  71.                 if(count==16)    //count是全局变量,表示串口已收到的字节数
  72.                 {         
  73.                         count=0;
  74.                                         
  75.                         for(i=0;i<14;i++)
  76.                         {
  77.                                 send_buff[i]=receivedcmd[i+1];          //取出接收帧2——15字节(舍弃帧头帧尾),准备CRC校验
  78.                         }               
  79.                         crc_data=crc8_f_table(send_buff,14);  //发送缓冲区14字节全部参与CRC校验               
  80.                         if(crc_data==0&&receivedcmd[15]==FMEND)//如果CRC正确且帧尾有效
  81.                         {         
  82.                                 switch(send_buff[2])
  83.                                 {
  84.                                         case CONVERT:                           // 温度转换命令 0x44
  85.                                         {
  86.                                                 REN=0;                 // 禁止串口接收
  87.                                                 ES=0;                  // 关串口中断
  88.                                                 TempConvertAll();
  89.                                                 ES=1;                  //开串口中断
  90.                                                 REN=1;
  91.                                                 send_buff[0]=MYID;           // 本分机ID
  92.                                                 send_buff[1]=MAINID;   // 主机ID=0x00
  93.                                                 send_buff[2]=CVTOK;           // 温度转换完毕命令0x88
  94.                                                 crc_data=crc8_f_table(send_buff,13);
  95.                                                 send_buff[13]=crc_data;
  96.                                                 sendcombytes();                   // 发送一帧完整数据
  97.                                                 break;
  98.                             }
  99.                                         case GETTEMP:                           // 读取温度命令 0xaa
  100.                                         {                                                
  101.                                                 Port=send_buff[3];          // 确定端口(P0、P1、P2、P3)
  102.                                                 Pin=send_buff[4];          // 确定端口具体引脚(数据0x80、0x40、0x20、0x010、0x08、0x04、0x02、0x01)
  103.                                                 for(i=0;i<8;i++)
  104.                                                 {
  105.                                                         ReceivdID_buff[i]=send_buff[i+5];        // 匹配ROM命令必须用ReceivdID_buff[i]
  106.                                                 }
  107.                                                 REN=0;                // 禁止串口接收
  108.                                                 ES=0;                 // 关串口中断
  109.                                                 crccount=0;
  110.                                                 do                                          //同一ID传感器允许读4次温度,4次失败则退出。
  111.                                                 {
  112.                                                         GetTemp();
  113.                                                         crc_data=crc8_f_table(temp_buff,9);         //要使用校验码,读温度必然是连续9字节
  114.                                                         crccount++;
  115.                                                 }while(!(crccount>4||crc_data==0));             //校验次数>4或校验正确立即退出循环
  116.                                                 ES=1;                 // 开串口中断
  117.                                                 REN=1;                // 允许串口接收                                                                                                
  118.                                                 send_buff[0]=MYID;
  119.                                                 send_buff[1]=MAINID;
  120.                                                 send_buff[2]=TEMPDATA;        // 向主机发温度命令        0xbb
  121.                                                 if(crc_data==0)
  122.                                                 {
  123.                                                         send_buff[3]=temp_buff[0];        // 原始温度低字节
  124.                                                         send_buff[4]=temp_buff[1];        // 原始温度高字节
  125.                                                 }
  126.                                                 else
  127.                                                 {
  128.                                                         send_buff[3]=0xff;
  129.                                                         send_buff[4]=0xff;
  130.                                                 }
  131.                                                 for(i=0;i<8;i++)
  132.                                                 {
  133.                                                         send_buff[i+5]=ReceivdID_buff[i];       
  134.                                                 }                                                       
  135.                                                 crc_data=crc8_f_table(send_buff,13);
  136.                                                 send_buff[13]=crc_data;
  137.                                                 sendcombytes();
  138.                                                 break;
  139.                                         }
  140.                                         case GETSTATE:                           // 主机通信检测命令0x11,确认主机与分机通信是否正常  
  141.                                         {
  142.                                                 send_buff[0]=MYID;
  143.                                                 send_buff[1]=MAINID;
  144.                                                 send_buff[2]=CPUOK;           // CPUOK 0x22
  145.                                                 for(i=0;i<10;i++)
  146.                                                 {
  147.                                                         send_buff[i+3]=0x55;
  148.                                                 }
  149.                                                 crc_data=crc8_f_table(send_buff,13);
  150.                                                 send_buff[13]=crc_data;
  151.                                                 sendcombytes();
  152.                                                 break;
  153.                                         }
  154.                                         case GETHOUSE:                                  //仓库湿度命令 0xce
  155.                                         {
  156.                                                 ;       
  157.                                         }
  158.                                         case GETAREA:                              // 库区湿度命令 0xd6
  159.                                         {
  160.                                                 ;
  161.                                         }
  162.                                         default:break;
  163.                                 }                                
  164.                         }                        
  165.                 }
  166.         }
  167. }
复制代码

usart.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 "usart.h"
  11. extern unsigned char send_buff[14];            // 发送缓冲区14字节,加帧头帧尾共16字节每帧
  12. extern unsigned char ReceivdID_buff[8]; // 存储主机发来的rom ID为8字节
  13. extern unsigned char receivedcmd[16];   // 存放接收到的命令 1:帧头,2发送ID,3本机ID,4命令,5port,6pin,7-14ID,15CRC,16帧尾
  14. extern unsigned char count;                                // 主程序中的全局变量

  15. //初始串口(晶振频率 11.0592M)
  16. void com_init()
  17. {
  18.   SCON = 0x50; //01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接受)
  19.   TMOD = 0x20; //0010 0000 定时器1工作于方式2(8位自动重装方式)
  20.   TR1=1;                  // 定时器1开始运行
  21.   PCON=PCON&0x7f;              // SMOD=0,波特率不倍增。
  22.   switch(BAUDRATE)        //波特率设置
  23.   {
  24.     case 1200:TL1=0xe8;
  25.               TH1=0Xe8;
  26.               break;
  27.     case 2400:TL1=0xf3;   
  28.               TH1=0xf3;   
  29.               break;
  30.     case 4800:TL1=0xfa;
  31.               TH1=0Xfa;
  32.               break;
  33.     case 9600:TL1=0xfd;
  34.               TH1=0Xfd;
  35.               break;
  36.     case 19200:PCON=PCON|0x80;
  37.               TL1=0xfd;
  38.               TH1=0Xfd;
  39.               break;
  40.     case 38400:PCON=PCON|0x80;
  41.               TL1=0xfe;
  42.               TH1=0Xfe;
  43.               break;
  44.     default:  TL1=0xfd;
  45.               TH1=0Xfd;
  46.               break;
  47.   }
  48.   AUXR = 0x00;             // 很关键,使用定时器1作为波特率发生器,S1ST2=0
  49.   EA=1;
  50.   ES=1;
  51. }
  52. /**************************************/
  53. //发送一个字节数据
  54. void sendcombyte(unsigned char dat)
  55. {
  56.         SBUF=dat;
  57.         while(TI==0);
  58.         TI=0;
  59. }
  60. /*********************************************/
  61. //发送一帧完整数据
  62. void sendcombytes()
  63. {  
  64.         unsigned char i;
  65.         sendcombyte(FMBEGIN);
  66.         for(i=0;i<14;i++)
  67.         {
  68.                 sendcombyte(send_buff[i]);
  69.         }
  70.         sendcombyte(FMEND);
  71. }
  72. /***********************************************/
  73. //串口中断服务程序
  74. void serial_init () interrupt 4
  75. {
  76.         if(RI)                              // 只处理接收中断
  77.         {
  78.                 if(count==16)count=0; //如果已经接收了16个字符,主程序还没来得及处理又发来下一帧数据
  79.                                       //,则count清零,覆盖上一帧数据,保证数据接收不错位
  80.                 receivedcmd[count]=SBUF;
  81.                 RI=0;
  82.                
  83.                 switch(count)
  84.                 {
  85.                         case 0:                            // 判断帧头是否正确
  86.                         {
  87.                                 if(receivedcmd[count]==FMBEGIN)count++;
  88.                                 else count=0;
  89.                                 break;
  90.                         }
  91.                         case 1:                                // 判断是否是主机信息
  92.                         {
  93.                        
  94.                                 if(receivedcmd[count]==MAINID)count++;
  95.                                 else
  96.                                 {
  97.                                         count=0;
  98.                                 }       
  99.                                 break;
  100.                         }       
  101.                         case 2:
  102.                         {                       // 判断是否是本机信息
  103.                                 if(receivedcmd[count]==MYID)count++;                                
  104.                                 else count=0;
  105.                                 break;
  106.                         }
  107.                         default:count++;       
  108.                 }
  109.         }
  110. }
复制代码



回复

使用道具 举报

ID:190731 发表于 2017-4-29 17:29 | 显示全部楼层
请问这个是无线的吗
回复

使用道具 举报

ID:190731 发表于 2017-4-29 17:37 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:190731 发表于 2017-4-29 17:38 | 显示全部楼层
这些是不是完整的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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