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无线多点测温的完整源码压缩包)
单片机下位机主程序如下(部分预览):
- /****************《51单片机轻松入门-基于STC15W4K系列》配套例程 *************
- ★★★★★★★★★★★★★★★★★★★★★★★★
- 《51单片机轻松入门-基于STC15W4K系列》 一书已经由北航出版社正式出版发行。
- 作者亲手创作的与教材配套的51双核实验板(2个MCU)对程序下载、调试、仿真方便,不需要外部
- 仿真器与编程器,这种设计方式彻底解决了系统中多个最高优先级谁也不能让谁的中断竞争问题。
- QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
- 验证信息:STC15单片机
- 邮箱:xgliyouquan@126.com
- ★★★★★★★★★★★★★★★★★★★★★★★★*/
- //18B20多点测温程序,11.0592M晶振
- #include "STC15W4K.H"
- #include "usart.h"
- #include "ds18b20.h"
- #define CONVERT 0x44 // 收主机转换温度命令
- #define GETTEMP 0xaa // 收主机读温度命令
- #define GETHOUSE 0xcc // 收主机读仓库湿度命令
- #define GETAREA 0xd6 // 收主机读库区湿度命令
- #define GETSTATE 0x11 // 收主机通信检测命令
- #define SENDAREA 0xdd // 向主机发库区湿度
- #define SENDHOUSE 0xce // 向主机发仓库湿度
- #define CVTOK 0x88 // 向主机发转换温度完毕命令
- #define CPUOK 0x22 // 向主机发通信正常命令
- #define TEMPDATA 0xbb // 向主机发温度命令
- unsigned char Port,Pin,count=0; //单片机端口P0、P1、P2、P3,端口具体引脚(1-8),接收计数器
-
- unsigned char send_buff[14]; // 发送缓冲区14字节,加帧头帧尾共16字节每帧
- unsigned char ReceivdID_buff[8]; // 存储主机发来的rom ID为8字节
- unsigned char receivedcmd[16]; // 存放接收到的命令 1:帧头,2发送机号,3本机ID,4命令,5port,6pin,7-14ID,15CRC,16帧尾
- unsigned char temp_buff[9]; // 存储读取的温度字节,读温度为9字节,读rom ID为8字节
- unsigned char code CrcTable [256]={
- 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
- 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
- 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
- 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
- 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
- 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
- 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
- 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
- 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
- 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
- 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
- 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
- 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
- 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
- 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
- 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
- //反序CRC查表校验
- unsigned char crc8_f_table (unsigned char *ptr, unsigned char len)
- {
- unsigned char i;
- unsigned char crc =0;
- for(i=0;i<len;i++) // 查表校验
- {
- crc= CrcTable[crc^ptr[i]]; // ^是按位异或运算符
- }
- return(crc);
- }
- void port_mode() // 端口模式
- {
- P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
- P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
- }
- void main()
- {
- unsigned char i;
- unsigned char crccount; // crc校验次数
- unsigned char crc_data; // crc校验结果
- port_mode(); // 所有IO口设为准双向弱上拉方式。
- com_init(); // 串口初始化
- while(1)
- {
- if(count==16) //count是全局变量,表示串口已收到的字节数
- {
- count=0;
-
- for(i=0;i<14;i++)
- {
- send_buff[i]=receivedcmd[i+1]; //取出接收帧2——15字节(舍弃帧头帧尾),准备CRC校验
- }
- crc_data=crc8_f_table(send_buff,14); //发送缓冲区14字节全部参与CRC校验
- if(crc_data==0&&receivedcmd[15]==FMEND)//如果CRC正确且帧尾有效
- {
- switch(send_buff[2])
- {
- case CONVERT: // 温度转换命令 0x44
- {
- REN=0; // 禁止串口接收
- ES=0; // 关串口中断
- TempConvertAll();
- ES=1; //开串口中断
- REN=1;
- send_buff[0]=MYID; // 本分机ID
- send_buff[1]=MAINID; // 主机ID=0x00
- send_buff[2]=CVTOK; // 温度转换完毕命令0x88
- crc_data=crc8_f_table(send_buff,13);
- send_buff[13]=crc_data;
- sendcombytes(); // 发送一帧完整数据
- break;
- }
- case GETTEMP: // 读取温度命令 0xaa
- {
- Port=send_buff[3]; // 确定端口(P0、P1、P2、P3)
- Pin=send_buff[4]; // 确定端口具体引脚(数据0x80、0x40、0x20、0x010、0x08、0x04、0x02、0x01)
- for(i=0;i<8;i++)
- {
- ReceivdID_buff[i]=send_buff[i+5]; // 匹配ROM命令必须用ReceivdID_buff[i]
- }
- REN=0; // 禁止串口接收
- ES=0; // 关串口中断
- crccount=0;
- do //同一ID传感器允许读4次温度,4次失败则退出。
- {
- GetTemp();
- crc_data=crc8_f_table(temp_buff,9); //要使用校验码,读温度必然是连续9字节
- crccount++;
- }while(!(crccount>4||crc_data==0)); //校验次数>4或校验正确立即退出循环
- ES=1; // 开串口中断
- REN=1; // 允许串口接收
- send_buff[0]=MYID;
- send_buff[1]=MAINID;
- send_buff[2]=TEMPDATA; // 向主机发温度命令 0xbb
- if(crc_data==0)
- {
- send_buff[3]=temp_buff[0]; // 原始温度低字节
- send_buff[4]=temp_buff[1]; // 原始温度高字节
- }
- else
- {
- send_buff[3]=0xff;
- send_buff[4]=0xff;
- }
- for(i=0;i<8;i++)
- {
- send_buff[i+5]=ReceivdID_buff[i];
- }
- crc_data=crc8_f_table(send_buff,13);
- send_buff[13]=crc_data;
- sendcombytes();
- break;
- }
- case GETSTATE: // 主机通信检测命令0x11,确认主机与分机通信是否正常
- {
- send_buff[0]=MYID;
- send_buff[1]=MAINID;
- send_buff[2]=CPUOK; // CPUOK 0x22
- for(i=0;i<10;i++)
- {
- send_buff[i+3]=0x55;
- }
- crc_data=crc8_f_table(send_buff,13);
- send_buff[13]=crc_data;
- sendcombytes();
- break;
- }
- case GETHOUSE: //仓库湿度命令 0xce
- {
- ;
- }
- case GETAREA: // 库区湿度命令 0xd6
- {
- ;
- }
- default:break;
- }
- }
- }
- }
- }
复制代码
usart.c文件:
|