DS18B20多点测温(51C程序)
- 格式:doc
- 大小:66.50 KB
- 文档页数:11
C51--DS18B20数字温度计--C语言#include;#include;#define uint unsigned int#define uchar unsigned charsbit DQ=P2^6;sbit lcdrs=P1^0;sbit lcdrw=P1^1;sbit lcden=P1^2;void disp(uint a);void init(void);void delay(uint i);uchar ds18b20_init(void);void write_byte(uchar byte);uchar read_byte(void);uint read_ds18b20(void);void delay50us(void);void delayms(uint a);void lcd1602_wr_com(uchar com);void lcd1602_wr_data(uchar dat);void lcd_init(void);uchar code str[]="temperature"; void main(void){init();while(1){disp(read_ds18b20());delayms(50);}}void init(void)uchar i;lcd_init();lcd1602_wr_com(0x80+0x02); //显示的地址for(i=0;i;>;=1; //右移一位DQ=1;}delay(4);}uchar read_byte(void){uchar i,temp;for(i=0;i;>;=1; //右移一位DQ=1; //主机释放信号线_nop_();if(DQ)temp|=0x80; //将读出数据放在最高位,如果是0,信号线会设备继续拉低,1则为高delay(4);}return temp; //返回读出的一字节数据}uint read_ds18b20(void)uchar numh,numl;uint value;if(ds18b20_init()==0) //判断设置是否正常,0为正常{write_byte(0xcc); //跳过ROM序列号读取write_byte(0x44); //启动温度转换if(ds18b20_init()==0) //再次初始化{write_byte(0xcc);//跳过ROM序列号读取write_byte(0xbe);//读温度寄存器numl=read_byte();//读低位数据numh=read_byte();//读高位数据value=numh;value=value;0;i--)for(j=122;j>;0;j--);}void lcd1602_wr_com(uchar com){lcdrs=0;P0=com;delayms(2);lcden=1;delay50us();lcden=0;}void lcd1602_wr_data(uchar dat){lcdrs=1;P0=dat;delayms(2);lcden=1;delay50us();lcden=0;}void lcd_init(void){lcden=0;lcdrw=0;lcd1602_wr_com(0x38); //显示模式设置lcd1602_wr_com(0x0c); //开显示,不显示光标lcd1602_wr_com(0x06); //写字符后地址指针加1,整屏显示不移动lcd1602_wr_com(0x01); //清屏}。
DS18B20多点测温<读序列,匹配序列,51 C程序,1602显示)因为本人在前两天找DS18B20多点测温<51C程序),网上下载了很多,但是都不是很理想,后来,自己总结前人的知识,重新写了这个程序。
其中包括程序一:单个读序列号。
程序二,匹配并且读两个DS18B20,当然,读多个与读两个基本原理一样,只要加上其序列号等即可。
本程序所有显示都是用LCD160 2显示。
程序一:度序列号,并用1602显示,1602从左到右分别是低到高位。
#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7。
//ds18b20与单片机连接口sbit RS=P3^0。
sbit RW=P3^1。
sbit EN=P3^2。
unsigned char code str1[]={""}。
unsigned char code str2[]={" "}。
uchar fCode[8]。
uchar data disdata[5]。
uint tvalue。
//温度值uchar tflag。
//温度正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms>//延时1毫秒<不够精确的){unsigned int i,j。
for(i=0。
i<ms。
i++>for(j=0。
j<100。
j++>。
}void wr_com(unsigned char com>//写指令//{ delay1ms(1>。
RS=0。
RW=0。
EN=0。
P2=com。
delay1ms(1>。
EN=1。
delay1ms(1>。
ds18b20的C语言完整程序(c51)(可组网数字式温度传感器)发布日期:[2005-05-10]作者:(sparkstar)//DS1820 C51 子程序//这里以11.0592M晶体为例,不同的晶体速度可能需要调整延时的时间//sbit DQ =P2^1;//根据实际情况定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ = 0; //pull DQ line lowdelay(29); // leave it low for 480usDQ = 1; // allow line to return highdelay(3); // wait for presencepresence = DQ; // get presence signaldelay(25); // wait for end of timeslotreturn(presence); // presence signal returned} // 0=presence, 1 = no part//从 1-wire 总线上读取一个字节byte read_byte(void){byte i;byte value = 0;for (i=8;i>0;i--){value>>=1;DQ = 0; // pull DQ low to start timeslotDQ = 1; // then return highdelay(1); //for (i=0; i<3; i++);if(DQ)value|=0x80;delay(6); // wait for rest of timeslot}return(value);}//向 1-WIRE 总线上写一个字节void write_byte(char val){byte i;for (i=8; i>0; i--) // writes byte, one bit at a time {DQ = 0; // pull DQ low to start timeslotDQ = val&0x01;delay(5); // hold value for remainder of timeslotDQ = 1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0xBE); // Read Scratch Padtemp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC); //Skip ROMwrite_byte(0x44); // Start Conversionreturn temp.x/2;}。
/*********************************************************************///// DS18B20温度计C程序/*********************************************************************///使用AT89C2051单片机,12MHZ晶振,用共阳LED数码管//P1口输出段码,P3口扫描//#pragma src(d:\aa.asm)#include "reg51.h"#include "intrins.h" //_nop_();延时函数用#define Disdata P1 //段码输出口#define discan P3 //扫描口#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7; //温度输入口sbit DIN=P1^7; //LED小数点控制uint h;//////*******温度小数部分用查表法**********//uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x 09};//uchar code dis_7[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xbf};/* 共阳LED段码表"0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-" */ uchar code scan_con[4]={0xfe,0xfd,0xfb,0xf7}; // 列扫描控制字uchar data temp_data[2]={0x00,0x00}; // 读出温度暂放uchar data display[5]={0x00,0x00,0x00,0x00,0x00};//显示单元数据,共4个数据,一个运算暂存用///////***********11微秒延时函数**********///void delay(uint t){for(;t>0;t--);}///***********显示扫描函数**********/scan(){char k;for(k=0;k<4;k++) //四位LED扫描控制{Disdata=dis_7[display[k]];if(k==1){DIN=0;}discan=scan_con[k];delay(90);discan=0xff;}}/////***********18B20复位函数**********/ow_reset(void){char presence=1;while(presence){while(presence){DQ=1;_nop_();_nop_();DQ=0; //delay(50); // 550usDQ=1; //delay(6); // 66uspresence=DQ; // presence=0继续下一步}delay(45); //延时500uspresence = ~DQ;}DQ=1;}/////**********18B20写命令函数*********///向1-WIRE 总线上写一个字节void write_byte(uchar val){uchar i;for (i=8; i>0; i--) //{DQ=1;_nop_();_nop_();DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us DQ = val&0x01; //最低位移出delay(6); //66usval=val/2; //右移一位}DQ = 1;delay(1);}///*********18B20读1个字节函数********///从总线上读取一个字节uchar read_byte(void){uchar i;uchar value = 0;for (i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ = 0; //_nop_();_nop_();_nop_();_nop_(); //4usDQ = 1;_nop_();_nop_();_nop_();_nop_(); //4usif(DQ)value|=0x80;delay(6); //66us}DQ=1;return(value);}///***********读出温度函数**********///read_temp(){ow_reset(); //总线复位write_byte(0xCC); // 发Skip ROM命令write_byte(0xBE); // 发读命令temp_data[0]=read_byte(); //温度低8位temp_data[1]=read_byte(); //温度高8位ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令}///***********温度数据处理函数**********/work_temp(){uchar n=0; //if(temp_data[1]>127){temp_data[1]=(256-temp_data[1]);temp_data[0]=(256-temp_data[0]);n=1;}//负温度求补码display[4]=temp_data[0]&0x0f;display[0]=ditab[display[4]];display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//display[3]=display[4]/100;display[1]=display[4]%100;display[2]=display[1]/10;display[1]=display[1]%10;if(!display[3]){display[3]=0x0A;if(!display[2]){display[2]=0x0A;}}//最高位为0时都不显示if(n){display[3]=0x0B;}//负温度时最高位显示"-"}/////**************主函数****************/main(){Disdata=0xff; //初始化端口discan=0xff;for(h=0;h<4;h++){display[h]=8;}//开机显示8888ow_reset(); // 开机先转换一次write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令for(h=0;h<500;h++){scan();} //开机显示"8888"2秒while(1){read_temp(); //读出18B20温度数据work_temp(); //处理温度数据for(h=0;h<500;h++){scan();} //显示温度值2秒}}////*********************结束**************************//。
基于C51的DS18B20多点测温体系2013-07-22目次摘要3第一章绪论41.1 开宣布景及意义4第二章体系硬件设计52.1 单片机52.2 DS18B20温度测量模块52.3 液晶显示模块8第三章体系软件设计103. 1体系初始化103.2 温度测量程序11第四章体系仿真调试124.1 体系仿真调试12附录14摘要本文介绍了基于温度传感器DS18b20与AT89C52单片机构成的多点温度散布式测温体系.设计了其体系构成和软件计划.该体系面向现实需求,设定DS18b20温度规模为-55℃~+125℃,采取LCD1602液晶显示屏,显示两路温度传感器的测量温度值.同时经由过程串口通信与PC机进行通信.传输收集到的温度值.现实运用标明.该体系构造简略,抗干扰才能强,合适于良好情形下现场温度的测量,可运用于仓库测温.楼宇空调掌握和临盆进程监控等范畴.症结词:DS18b20,散布式,1602 串口通第一章绪论1.1 开宣布景及意义温度的测量和掌握在储粮仓库.智能楼宇空调掌握及其他的工农业临盆和科学研讨中运用普遍.传统的温度检测是运用诸如热电偶.热电阻.半导体pn结之类的模仿传感器,经旌旗灯号取样电路.放大电路和模数转换电路处理,获取暗示温度值的数字旌旗灯号,再交由微处理器.因为检测情形庞杂,测量点多,旌旗灯号传输距离远及各类干扰的影响,使得传统测量体系的稳固性和靠得住性降低.近年来跟着单片机的成长和传感器技巧的改革,温度检测范畴也完成了从模仿旌旗灯号到数字旌旗灯号的改变.DS18b20温度传感器的普遍运用更是推进了这一范畴的成长.别的液晶显示模块具有体积小.功耗低.显示内容丰硕.超薄轻盈等长处在各类内心和显示体系中得到越来越多的运用,如今也是单片机运用设计中最经常运用的信息显示模块.分解以上产品的成长特色,愿望温度检测体系在将来的成长中有更辽阔的运用空间并且具有更好的现场测量优胜性.第二章体系硬件设计本体系经由过程DS18B20温度传感器收集温度值,经由单片机处来由液晶显示模块显示当前温度值,并经由串口通信将温度传送到PC上2.1 单片机本体系采取AT89C52单片机作为微处理器.AT89C52单片机是ATMEL公司89系列单片机的一种8位Flash单片机.它最大的特色是片内含有8k可反复编程的Flash存储器,可进行1000次的擦写操纵.别的AT89c52单片机采取ATMEL高密度非易掉存储器制作技巧制作,与工业尺度的MCS-51指令集和输出管脚相兼容,并且其兼具省电耐用.机能稳固的特色,是以成为单片机市场的主流产品.本体系采取晶振依据须要肯定体系工作频率为11.0592Mhz.2.2 DS18B20温度测量模块DS18b20是美国DALLAS公司推出的单总线数字化测温集成电路,它具有奇特的单线接口方法,将非电模仿量温度值转换为数字旌旗灯号串行输出仅需占用1位I/O端口,可以或许直接读取被测现场的温度值.它体积小,电压实用规模宽(3v~5v),且可经由过程编程实现9~12位的温度读数,即具有可调的温度分辩率,是以实用性和靠得住性较高,运用普遍.以下是DS18b20的内部构造图.1DS18b20的内部构造图DS18B20有4个重要的数据部件:① 64位激光ROM.64位激光ROM从高位到低位依次为8位CRC.48位序列号和8位家族代码(28H)构成.②温度敏锐元件.③非易掉性温度报警触发器TH和TL.可经由过程软件写入用户报警高低限值.④设置装备摆设存放器.设置装备摆设存放器为高速暂存存储器中的第五个字节.DS18B20在0工作时按此存放器中的分辩率将温度转换成响应精度的数值.DS18B20的测温规模为-55℃~+125℃,在-10℃~+85℃规模内,精度为±℃.在电压低于3.4v时精度误差较大.依据当时序特色以下是DS18B20与AT89C52单片机构成的温度监测体系如下图2.温度监测体系DS18b20的典范运用在本体系中两个温度传感器与单片机衔接方法如下:图2.2.3 传感器与单片机衔接本体系为多点温度测试.DS18B20采取外部供电方法,理论上可以在一根数据总线上挂256个DS18B20,但现实运用中发明,假如挂接20个以上的DS18B20就会产生功耗问题.别的单总线长度也不宜超出0.5M,不然会影响到数据的传输.在本电路板的设计中斟酌到初步实践的精确性,暂运用2个DS18B20分离衔接单片机的p2.6口.对DS18B20的设计,须要留意以下问题(1)对硬件构造简略的单线数字温度传感器DS18B20 进行操纵,须要用较为庞杂的程序完成.编制程序时必须严厉按芯片数据手册供给的有关操纵次序进行,读.写时光片程序要严厉按请求编写.尤其在运用DS18B20 的高测温分辩力时,对时序及电气特征参数请求更高.(2)现实运用时,要留意单线的驱动才能,不克不及挂接过多的DS18B20,同时还应留意最远接线距离.别的还应依据现实情形选择其接线拓扑构造.2.3 液晶显示模块本体系运用的是1602液晶显示模块.1602液晶显示器以其微功耗.体积小.显示内容丰硕.超薄轻盈.位数多.程序简略的诸多长处,在各类内心和低功耗体系中得到普遍的运用.依据显示内容可以分为字符型液晶,图形液晶.依据显示容量又可以分为单行16字,2行16字,两行20字等等.在本体系中运用的是字符型两行16字液晶显示器.在与单片机衔接时运用接口电路(排针)相连,为并行通信.以下是1602液晶显示器外型图和液晶显示的典范运用.图2 液晶显示器外形图1602液晶显示采取尺度的16脚接口,个中:(模块不和有标注)图2.3.2 串口通信第1脚:VSS为地电源第2脚:VDD接5V正电源第3脚:V0为液晶显示器比较度调剂端,接正电源时比较度最弱,接地电源时比较度最高,比较渡过高时会产生“鬼影”,运用时可以经由过程一个10K的电位器调剂比较度第4脚:RS为存放器选择,高电日常平凡选择数据存放器.低电日常平凡选择指令存放器.第5脚:RW为读写旌旗灯号线,高电日常平凡进行读操纵,低电日常平凡进行写操纵.当RS和RW合营为低电日常平凡可以写入指令或者显示地址;当RS为高电平.RW为低电日常平凡可以写入数据.第6脚:E端为使能端,当E端由高电平跳变成低电日常平凡,液晶模块履行敕令.第7~14脚:D0~D7为8位双向数据线.第15~16脚:空脚1602液晶模块内部的字符产生计储器(CGROM)已经存储了不合的点阵字符图形,这些字符有,阿拉伯数字.英文字母的大小写.经常运用的符号.和日文化名等,每一个字符都有一个固定的代码,个中数字与字母同ASCII码兼容.UART是一种通用串行数据总线,用于异步通信.该总线双向通信,可以实现全双工传输和吸收.实现单片机和PC机的通信工作,接一个MAX232 实现电平转化.电路图如下:第三章体系软件设计图3 体系流程图全部体系的功效是由硬件电路合营软件来实现的,当硬件根本定型后,软件的功效也就根本定下来了.本体系主程序重要包含三个子程序,分离为液晶显示子程序,温度测量子程序,串口通信子程序.主体软件架构如左图:3. 1体系初始化体系初始化重要包含UART初始化,液晶显示初始化,温度传感器初始化.UART初始化包含界说准时器/计数器和串行口的工作方法,界说T1为主动重装8位计数器.液晶显示初始化主如果肯定液晶显示器的工作方法.显示开关.光标开关等.温度传感器初始化包含一个由总线掌握器发出的复位脉冲和跟有厥后由传感器发出的消失脉冲.消失脉冲是让总线掌握器知道DS18b20在总线上且已预备好操纵.一个复位脉冲跟着一个消失脉冲标明DS18b20已经预备好发送和吸收数据.以下是初始化序列图.图3.1.1 初始化序列图3.2 温度测量程序温度测量程序主如果DS18b20与单片机之间的ROM操纵敕令和DS18b20的数据读写操纵敕令.当单片机对DS18B20进行初始化,检测到一个消失脉冲后,发出匹配ROM敕令,然后发送ROM码.图3.2.1 DS18b20根本工作流程第四章体系仿真调试4.1 体系仿真调试在keil开辟情形下不克不及进行有用的仿真调试,所以在体系中采取protues单片机仿真对象进行仿真调试.下图为protues仿真读取温度后在LCD1602液晶屏上的显示成果.图4.1..1protues仿真图上位机用串口调试软件来仿真,装配了虚拟串口驱动软件和PROTEUS进行调试仿真.虚拟串口驱动软件用了VSPD 软件.VSPD软件在Window操纵体系上增长了一对在逻辑上交叉互相的虚拟串口,使串口调试助手可以或许和PROTEUS中的单片机串口相连.VSPD软件界面如下:串口仿真成果如下:在串口调试助手上显示两个温度传感器收集到的温度附录温度收集体统道理图PCB图源代码1602函数部分:#define Port P1sbit RS = P2^0; //界说端口sbit RW = P2^1;sbit E = P2^2;/**************************************************************** 微秒延时函数****************************************************************/ void delay_us(unsigned int n) //延时假如须要高精度延时{if (n == 0){return ;}while (--n);}/****************************************************************/ /* 毫秒函数声明 *//****************************************************************/ void delay_ms(unsigned char i){unsigned int b;while(i--)for (b = 1; b < 1000 ; b++) ;}/****************************************************************/ /* 写入敕令函数 *//***************************************************************/ void LCD_write_com(unsigned char com){RS = 0;E = 1;Port = com;delay_us(10);E = 0;}/****************************************************************/ /* 写入数据函数 *//****************************************************************/ void LCD_write_Data(unsigned char Data){RS = 1 ;RW = 0 ;E = 1 ;Port = Data;delay_us(10);E = 0;}/****************************************************************/ /* 写入字符串函数 *//****************************************************************/ void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s){if (y == 0){LCD_write_com(0x80 + x);}else{LCD_write_com(0xc0 + x);while (*s){LCD_write_Data( *s);s++;}}/****************************************************************/ /* 初始化函数 *//****************************************************************/ void LCD_init(void){delay_ms(40);LCD_write_com(0x38); /*显示模式设置*/delay_ms(5);LCD_write_com(0x38);delay_ms(5);LCD_write_com(0x38);delay_ms(5);LCD_write_com(0x38);LCD_write_com(0x08); /*显示封闭*/LCD_write_com(0x01); /*显示清屏*/LCD_write_com(0x06); /*显示光标移动设置*/delay_ms(5);LCD_write_com(0x0C); /*显示开及光标设置*/}/***********************************************************函数名: Display_F函数解释:打印整数型数据,没有地址传入参数:用于Display_float运用传出参数:无返回值:无**********************************************************/void Display_F(unsigned int num){unsigned char sever_num[6],i = 0;if(num == 0)LCD_write_Data(0x30);else{while(num != 0){sever_num[i++] = num % 10 + 0x30 ;num /= 10 ;}while(i--){LCD_write_Data(sever_num[i]);delay_us(500);}}}/***********************************************************函数名: Display_float函数解释:打印浮点型数据,传入参数:打印地址x,y,数据num,小数点后面打印length位传出参数:无返回值:无**********************************************************/void Display_float(unsigned char x,unsigned char y,float numf,unsigned char length){unsigned long Int_num;unsigned int temp = 1;unsigned char i = 0;for (i = 0 ; i < length ; i++){numf *= 10 ;temp *= 10 ;}if (y == 0)LCD_write_com(0x80 + x);elseLCD_write_com(0xc0 + x);Int_num = (long)numf;Display_F(Int_num / temp);LCD_write_Data('.');Display_F(Int_num % temp);}DS18B20函数部分:bit flag = 0;sbit dat=P2^6;uchar xl[2][8] = {{0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0x8e},{0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9}}; //两路DS18B20 ROM码void dsdelay(uchar z) //误差 0us{unsigned char a,b;for(z;z>0;z--)for(b=1;b>0;b--)for(a=2;a>0;a--);}void delay(unsigned int z)//延时函数{uchar x,y;for(x=z;x>0;x--)for(y=101;y>0;y--);}///////////////////////////////////////////////DS18B20函数部分////////////void dsinit()//DS18B20初始化{dat=1;dsdelay(4);dat=0; //给一个脉冲旌旗灯号dsdelay(50);//低脉冲旌旗灯号要保持480us——960usdat=1;//拉高dsdelay(9);//略微延时delay(1);}uchar read()//DS18B20 读一个字节{uchar i,k;for (i=8;i>0;i--){dat = 0; // 给脉冲旌旗灯号k>>=1;//将读到的一位数向后移一位dat = 1; // 给脉冲旌旗灯号if(dat) k|=0x80;//假如读到的是1,则,k和0x80进行或运算,首位变成1dsdelay(4);//每位读取中央距离大于1us}return(k);}void write(uchar date)//DS18B20 写一个字节{uchar i,k;k=date;for(i=0;i<8;i++){dat = 0;dat = k&0x01;dsdelay(7);dat = 1;k>>=1;dsdelay(1);}}float read_tempe(uchar num)//从DS18B20存储器中念书温度{int t;float tt;uchar a,b,i;dsinit();//每次对DS18B20输入指令都要先辈行初始化操纵write(0x55);//写序号列号for (i = 0 ; i < 8 ; i++){write(xl[num][i]) ;}write(0x44); // 启动温度转换dsinit();write(0x55);//写序号列号for (i = 0 ; i < 8 ; i++){write(xl[num][i]) ;}write(0xBE); //读取温度存放器等(共可读9个存放器)前两个就是温度a=read();//读出温度的低八位b=read();//读出温度的高八位t=b;t<<=8;//t是int,16位,讲高八位移到前面t=t|a;//将温度的高位与低位归并if ((b & 0x80 )== 0)//断定正负温度{tt=t*0.0625;//将带有小数点位的十六进制数化为十进制flag = 0;}else{tt=(~t + 1 )* 0.0625;flag = 1;}return(tt);}UART函数部分:void InitUART(void)//UART 初始化{TMOD = 0X20; //11.0592M 9600SCON = 0X50;TH1 = 0xfd;TL1 = 0xfd;PCON = 0X00;EA = 1;ES = 1;TR1 = 1;}void Send(unsigned char C)//UART 发送{SBUF = C;while(TI == 0);TI = 0;}主函数部分:uchar lable[]="TEMPE: 'C";//初始显示void Send_Tempe( float tempe,unsigned char num)//串口发送收集到的温度{unsigned long t ;unsigned char i ;unsigned char tt[]="NUM 0 TEMPE 12.50'C\n";tt[4] = num +0x30;tempe = tempe * 100 ;t = (unsigned int) tempe;tt[17] = t%10+0x30;t = t/10 ;tt[16] = t%10+0x30;t = t/10 ;tt[14] =t%10+0x30;t = t/10 ;tt[13] =t%10 +0x30;if(flag == 1)tt[12] = '-';for(i = 0 ; i < 22 ; i++)Send(tt[i]);}void main(){float tempe;unsigned char i;InitUART() ;LCD_init() ;LCD_write_str(0,0, lable);LCD_write_str(0,1, lable);while(1){for (i = 0; i < 2;i++ ){tempe = read_tempe(i);if(flag == 1)LCD_write_str(6,i, "-");elseLCD_write_str(6,i, " ");Display_float(7,i,tempe,2);Send_Tempe(tempe,i) ;delay(10000);}}。
1.DS18B20基本知识DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。
1、DS18B20产品的特点(1)、只要求一个端口即可实现通信。
(2)、在DS18B20中的每个器件上都有独一无二的序列号。
(3)、实际应用中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55。
C到+125。
C之间。
(5)、数字温度计的分辨率用户可以从9位到12位选择。
(6)、内部有温度上、下限告警设置。
2、DS18B20的引脚介绍TO-92封装的DS18B20的引脚排列见图1,其引脚功能描述见表1。
(底视图)图1表1 DS18B20详细引脚功能描述3.DS18B20的使用方法由于DS18B20采用的是1-Wire总线协议方式,即在一根数据线实现数据的双向传输,而对AT89S51单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。
由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。
DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。
该协议定义了几种信号的时序:初始化时序、读时序、写时序。
所有时序都是将主机作为主设备,单总线器件作为从设备。
而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。
数据和命令的传输都是低位在先。
DS18B20的复位时序DS18B20的读时序对于DS18B20的读时序分为读0时序和读1时序两个过程。
对于DS18B20的读时序是从主机把单总线拉低之后,在15us之内就得释放单总线,以让DS18B20把数据传输到单总线上。
DS18B20在完成一个读时序过程,至少需要60us才能完成。
/*-----------------------------------------------名称:18B20温度传感器修改:无内容:18B20单线温度检测的应用样例程序,请将18b20插紧,然后在数码管可以显示XX.XC,C表示摄氏度,如显示25.3C表示当前温度25.3度------------------------------------------------*/#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include<math.h>#include<INTRINS.H>#define uchar unsigned char#define uint unsigned int/******************************************************************//* 定义端口*//******************************************************************/sbit seg1=P2^0;sbit seg2=P2^1;sbit seg3=P2^2;sbit DQ=P1^3;//ds18b20 端口sfr dataled=0x80;//显示数据端口/******************************************************************//* 全局变量*//******************************************************************/uint temp;uchar flag_get,count,num,minute,second;uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段数码管段码表共阳uchar str[6];/******************************************************************//* 函数声明*//******************************************************************/void delay1(uchar MS);unsigned int ReadTemperature(void);void Init_DS18B20(void);unsigned char ReadOneChar(void);void WriteOneChar(unsigned char dat);void delay(unsigned int i);/******************************************************************//* 主函数*//******************************************************************/main(){unsigned char TempH,TempL;TMOD|=0x01;//定时器设置TH0=0xef;P2=0x00;count=0;while(1){str[5]=0x39; //显示C符号str[1]=tab[TempH/100]; //十位温度str[2]=tab[(TempH%100)/10]; //十位温度str[3]=tab[(TempH%100)%10]|0x80; //个位温度,带小数点str[4]=tab[TempL];if(flag_get==1) //定时读取当前温度{temp=ReadTemperature();if(temp&0x8000){str[0]=0x40;//负号标志temp=~temp; // 取反加1temp +=1;}elsestr[0]=0;TempH=temp>>4;TempL=temp&0x0F;TempL=TempL*6/10;//小数近似处理flag_get=0;}}}/******************************************************************/ /* 定时器中断*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描和温度检测间隔{TH0=0xef;//定时器重装值TL0=0xf0;num++;if (num==50){num=0;flag_get=1;//标志位有效second++;if(second>=60){second=0;minute++;if(count==1){P2=0;dataled=str[0];}//数码管扫描if(count==2){P2=1;dataled=str[1];}if(count==3){ P2=2;dataled=str[2];}if(count==4){ P2=3;dataled=str[3];}if(count==5){ P2=4;dataled=str[4];}if(count==6){ P2=5;dataled=str[5];count=0;}}/******************************************************************/ /* 延时函数*/ /******************************************************************/ void delay(unsigned int i)//延时函数{while(i--);}/******************************************************************/ /* 初始化*/ /******************************************************************/ void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay(8); //稍做延时DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480usDQ = 1; //拉高总线delay(10);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay(5);/******************************************************************/ /* 读一个字节*/ /******************************************************************/ unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay(5);}return(dat);}/******************************************************************/ /* 写一个字节*/ /******************************************************************/ void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(5);DQ = 1;dat>>=1;}delay(5);}/******************************************************************/ /* 读取温度*/ /******************************************************************/ unsigned int ReadTemperature(void){unsigned char a=0;unsigned int b=0;unsigned int t=0;Init_DS18B20();WriteOneChar(0x44); // 启动温度转换delay(200);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度a=ReadOneChar(); //低位b=ReadOneChar(); //高位b<<=8;t=a+b;return(t);}。
DS18B20多点测温由于本人在前两天找DS18B20多点测温(51 C程序),网上下载了很多,但是都不是很理想,后来,自己总结前人的知识,重新写了这个程序。
其中包括程序一:单个读序列号。
程序二,匹配并且读两个DS18B20,当然,读多个与读两个基本原理一样,只要加上其序列号等即可。
本程序所有显示都是用LCD1602显示。
程序一:度序列号,并用1602显示,1602从左到右分别是低到高位。
#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7;//ds18b20与单片机连接口sbit RS=P3^0;sbit RW=P3^1;sbit EN=P3^2;unsigned char code str1[]={" "};unsigned char code str2[]={" "};uchar fCode[8];uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void wr_com(unsigned char com)//写指令//{ delay1ms(1);RS=0;RW=0;EN=0;P2=com;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(unsigned char dat)//写数据//{ delay1ms(1);;RS=1;RW=0;EN=0;P2=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void lcd_init()//初始化设置//{delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);}void display(unsigned char *p)//显示//{while(*p!='\0'){wr_dat(*p);p++;delay1ms(1);}}void init_play()//初始化显示{ lcd_init();wr_com(0x80);display(str1);wr_com(0xc0);display(str2);}/******************************ds1820 *********************/ void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{ uchar x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480us DQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{ uchar i=0;uchar dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/ {uchar i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()/*读取温度值并转换*/ {uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}/*******************************************************************/ void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}wr_com(0xc0);wr_dat(flagdat);//显示符号位wr_com(0xc1);wr_dat(disdata[0]);//显示百位wr_com(0xc2);wr_dat(disdata[1]);//显示十位wr_com(0xc3);wr_dat(disdata[2]);//显示个位wr_com(0xc4);wr_dat(0x2e);//显示小数点wr_com(0xc5);wr_dat(disdata[3]);//显示小数位}void DispCode(){unsigned char i,temp;ds1820rst();ds1820wr(0x33);for (i=0;i<8;i++){fCode[i]=ds1820rd();}wr_com(0x80+0x40);for (i=0;i<8;i++){temp = fCode[i]>>4; //显示高四位if (temp<10)wr_dat(temp + 0x30);elsewr_dat(temp + 0x37);temp = fCode[i]&0x0f;//显示低四位if (temp<10)wr_dat(temp+ 0x30);elsewr_dat(temp + 0x37);}}/********************主程序***********************************/ void main(){init_play();//初始化显示DispCode(); //系列号显示delay1ms(1000);while(1){//read_temp();//读取温度// ds1820disp();//显示;}}程序二:匹配序列号,并读温度。
#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit RS=P3^0;sbit RW=P3^1;sbit EN=P3^2;sbit DQ=P3^7;uchar code str1[]={0x28,0x08,0xA7,0xBA,0x02,0x00,0x00,0x18}; //ROM 1uchar code str2[]={0x28,0x0C,0xBA,0xBA,0x02,0x00,0x00,0x54}; //ROM2uchar code table[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00}; // 摄氏温度符号uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志/*************************lcd1602程序**************************/void delay1ms(uint ms)//延时1毫秒(不够精确的){ uint i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void wr_com(uchar com)//写指令//{ delay1ms(1);RS=0;RW=0;EN=0;P2=com;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(uchar dat)//写数据//{ delay1ms(1);;RS=1;RW=0;EN=0;P2=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_new() 、//写新字符{uchar i;wr_com(0x40);for(i=0;i<8;i++){wr_dat(table[i]);}}void lcd_init()//初始化设置//{ delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);wr_new();wr_com(0x80);wr_dat('A');wr_com(0x81);wr_dat(':');wr_com(0x89);wr_dat(0x00);wr_com(0x8a);wr_dat('C');wr_com(0xc9);wr_dat(0x00); 、、//摄氏温度字符wr_com(0xca);wr_dat('C');wr_com(0xc0);wr_dat('B');wr_com(0xc1);wr_dat(':');}/******************************ds1820程序***************************************/ void delay_18B20(uint i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{ uchar x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{ uchar i=0;uchar dat = 0;for (i=0;i<8;i++){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar dat)/*写数据*/{ uchar i=0;for (i=0; i<8; i++){ DQ = 0;DQ = dat&0x01;delay_18B20(10);DQ = 1;dat>>=1;}}void b20_Matchrom(uchar a) //匹配ROM{char j;ds1820wr(0x55); //发送匹配ROM命令if(a==1){for(j=0;j<8;j++)ds1820wr(str1[j]); //发送18B20的序列号,先发送低字节}if(a==2){for(j=0;j<8;j++)ds1820wr(str2[j]); //发送18B20的序列号,先发送低字节}}read_temp(uchar z)/*读取温度值并转换*/{ uchar a,b;float tt;ds1820rst();ds1820wr(0xcc); 、//读序列号ds1820rst();if(z==1){b20_Matchrom(1); //匹配ROM 1}if(z==2){b20_Matchrom(2); //匹配ROM 2 }ds1820wr(0x44);//*启动温度转换*/delay1ms(5);ds1820rst();ds1820wr(0xcc); //读序列号ds1820rst();if(z==1){b20_Matchrom(1); //匹配ROM 1 }if(z==2){b20_Matchrom(2); //匹配ROM 2 }ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{ tvalue=~tvalue+1;tflag=1;}tt=tvalue*0.0625;tvalue=tt*10;return(tvalue);}/*****************显示函数******************************/ void ds1820disp(uchar z)//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}if(z==1){wr_com(0x82);wr_dat(flagdat);//显示符号位wr_com(0x83);wr_dat(disdata[0]);//显示百位wr_com(0x84);wr_dat(disdata[1]);//显示十位wr_com(0x85);wr_dat(disdata[2]);//显示个位wr_com(0x86);wr_dat(0x2e);//显示小数点wr_com(0x87);wr_dat(disdata[3]);//显示小数位}if(z==2){wr_com(0xc2);wr_dat(flagdat);//显示符号位wr_com(0xc3);wr_dat(disdata[0]);//显示百位wr_com(0xc4);wr_dat(disdata[1]);//显示十位wr_com(0xc5);wr_dat(disdata[2]);//显示个位wr_com(0xc6);wr_dat(0x2e);//显示小数点wr_com(0xc7);wr_dat(disdata[3]);//显示小数位}}/********************主程序***********************************/ void main(){lcd_init();//初始化显示while(1){read_temp(1);//读取温度ds1820disp(1);//显示read_temp(2);//读取温度ds1820disp(2);//显示// delay1ms(10000);}}。