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);}。
51单片机DS18B20温度测量制作(有程序电路)单总线温度传感器DS18B20简介DS18B20是DALLAS公司生产的单总线式数字温度传感器,它具有微型化、低功耗、高性能、搞干扰能力强、易配处理器等优点,特别适用于构成多点温度测控系统,可直接将温度转化成串行数字信号(提供9位二进制数字)给单片机处理,且在同一总线上可以挂接多个传感器芯片。
它具有3引脚TO-92小体积封装形式,温度测量范围为-55 ℃~+125 ℃,可编程为9位~12位A/D转换精度,测温分辨率可达0.0625 ℃,被测温度用符号扩展的16位数字量方式串行输出,其工作电源既可在远端引入,也可采用寄生电源方式产生,多个DS18B20可以并联到3根或2根线上,CPU只需一根端口线就能与多个DS18B20通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。
以上特点使DS18B20非常适用于远距离多点温度检测系统。
DS18B20外形及引脚说明外形及引脚如图2所示:图2 管脚排列图在TO-92和SO-8的封装中引脚有所不同,具体差别请查阅PDF手册,在TO-92封装中引脚分配如下:1(GND):地2(DQ):单线运用的数据输入输出引脚3(VDD):可选的电源引脚DS18B20工作过程及时序DS18B20内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器1提供一频率稳定的计数脉冲。
高温度系数振荡器是一个振荡频率对温度很敏感的振荡器,为计数器2提供一个频率随温度变化的计数脉冲。
初始时,温度寄存器被预置成 -55℃,每当计数器1从预置数开始减计数到0时,温度寄存器中寄存的温度值就增加1℃,这个过程重复进行,直到计数器2计数到0时便停止。
初始时,计数器1预置的是与-55℃相对应的一个预置值。
以后计数器1每一个循环的预置数都由斜率累加器提供。
为了补偿振荡器温度特性的非线性性,斜率累加器提供的预置数也随温度相应变化。
计数器1的预置数也就是在给定温度处使温度寄存器寄存值增加1℃计数器所需要的计数个数。
#include<reg52.h>sbit s2=P0^0;sbit led=P1^3;unsigned char wendushangxian=0;sbit DQ=P1^6;sbit wei1=P3^0;sbit wei2=P3^1;sbit wei3=P3^2;sbit wei4=P3^3;sbit key_Max_jia=P0^0;sbit key_Max_jian=P0^1;sbit key_Min_jia=P0^2;sbit key_Min_jian=P0^3;sbit dianji_jian=P1^2;sbit dianji_jia=P1^7;sbit Led_tempreture_Max=P1^3;sbit Led_tempreture_Min=P1^4;sbit Led_normal=P1^5;unsigned char num[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; int tempreture_Max=40;int tempreture_Min=-10;void delay_mylself(int temp){unsigned int i,j;for(i=0;i<temp;i++)for(j=0;j<1140;j++);}void delay(unsigned int i) //如果i是unsigend char类型,则会出现错误结果{while(i--);}void DS18B20_Init(void)//初始化{unsigned char flag=0;DQ = 1; //DQ复位delay(1);DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480us小于960usDQ = 1; //拉高总线delay(6);while(DQ);while(!DQ);//flag=DQ; //稍做延时后如果flag=0则初始化成功flag=1则初始化失败//delay(30);}unsigned char Read(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 Write(unsigned char dat)//写字节{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(5);DQ = 1;dat>>=1;}}void init(){wei1=0;wei2=0;wei3=0;wei4=0;}void Display(unsigned int temp){unsigned char one,two,three,four;int wendu=0;if(temp<=0xf000){ temp>>=4; //右移4位,相当于乘0.0625,将温度化为十进制//temp*=10; //扩大10倍,显示一位小数one=temp/1000; //千位two=temp%1000/100; //百位three=temp%1000%100/10; //十位four=temp%1000%100%10; //个位wendu=temp;}else{temp=~temp;temp+=1;temp>>=4;one=10; //负数two=temp%1000/100; //百位three=temp%1000%100/10; //十位four=temp%1000%100%10; //个位wendu=-temp;}if(wendu>tempreture_Max){Led_tempreture_Max=0;Led_tempreture_Min=1;Led_normal=1;dianji_jian=1;dianji_jia=0;}else if(wendu<tempreture_Min){Led_tempreture_Max=1;Led_tempreture_Min=0;Led_normal=1;dianji_jia=1;dianji_jian=0;}else{Led_tempreture_Max=1;Led_tempreture_Min=1;Led_normal=0;dianji_jian=0;dianji_jia=0;}//第1位wei1=1;wei2=0;wei3=0;wei4=0;P2=num[one];delay_mylself(1);//第2位wei1=0;wei2=1;wei3=0;wei4=0;P2=num[two];delay_mylself(1);//第3位wei1=0;wei2=0;wei3=1;wei4=0;P2=num[three];delay_mylself(1);//第4位wei1=0;wei2=0;wei3=0;wei4=1;P2=num[four];delay_mylself(10);}void common_display(int temp){unsigned char one,two,three,four;one=temp/1000; //千位two=temp%1000/100; //百位three=temp%1000%100/10; //十位four=temp%1000%100%10; //个位if(temp<0){temp=-temp;two=temp%1000/100; //百位three=temp%1000%100/10; //十位four=temp%1000%100%10; //个位//第1位wei1=1;wei2=0;wei3=0;wei4=0;P2=num[10];delay_mylself(50);}else{//第1位wei1=1;wei2=0;wei3=0;wei4=0;P2=num[one];delay_mylself(50);}//第2位wei1=0;wei2=1;wei3=0;wei4=0;P2=num[two];delay_mylself(50);//第3位wei1=0;wei2=0;wei3=1;wei4=0;P2=num[three];delay_mylself(50);//第4位wei1=0;wei2=0;wei3=0;wei4=1;P2=num[four];delay_mylself(60);}void key(){unsigned char flag=0;if(key_Max_jia==0){flag=1;tempreture_Max+=1;if(tempreture_Max>125){tempreture_Max=125;}while(!key_Max_jia); //按键松手检测}else if(key_Max_jian==0){flag=2;tempreture_Max-=1;if(tempreture_Max<tempreture_Min){tempreture_Max=tempreture_Min;}while(!key_Max_jian); //按键松手检测}else if(key_Min_jia==0){flag=3;tempreture_Min+=1;if(tempreture_Min>tempreture_Max){tempreture_Min=tempreture_Max;}while(!key_Min_jia); //按键松手检测}else if(key_Min_jian==0){flag=4;tempreture_Min-=1;if(tempreture_Min<-55){tempreture_Min=-55;}while(!key_Min_jian); //按键松手检测}if(flag==1||flag==2){common_display(tempreture_Max);delay_mylself(200);flag=0;}else if(flag==4||flag==3){common_display(tempreture_Min);delay_mylself(200);flag=0;}}void main(){unsigned int temp;unsigned char tl=0,th=0;while(1){DS18B20_Init();Write(0xCC); // 跳过读序号列号的操作Write(0x44); // 启动温度转换delay(100);DS18B20_Init();Write(0xCC); //跳过读序号列号的操作Write(0xBE); //读取温度寄存器等delay(100);tl=Read(); //读取温度值低位th=Read(); //读取温度值高位temp=th<<8;temp|=tl;Display(temp);key();}}。
基于STC89C52单片机的18b20测温程序主程序:/***************************************************************************** 使用单片机:STC89C52晶振频率:11.0592MHZ开发环境:Keil4.0功能简述:调试用12864LCD的显示功能,蜂鸣器报警装置******************************************************************************/ #include<reg52.h>#include<intrins.h>#include<stdio.h>#include <math.h>#define uchar unsigned char#define uint unsigned int#define lcd_data P0#include "lcd.h"#include "ds18b20.h"code uchar Display1[8]={"实际温度"};code uchar Display2[8]={"报警温度"};sbit sl=P0^3;sbit sr=P0^4;sbit su=P0^5;sbit sd=P0^6;char f=0; //定义标志位sbit beep=P1^7; //蜂鸣器uint temp,templa; //定义整形温度数据float f_temp; //定义浮点型得温度数据int Actual_Temp;int Alarm_Temp;unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint z) //延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void Key_Scan() //键盘扫描程序{if(sl==0) //实现光标的左移{delay(5); //消抖if(sl==0){while(!sl); //按键松手检测等待按键释放if(f==0)f=4;else f--; // 按键自减1}}if(sr==0) //实现光标的右移{delay(5); //消抖if(sr==0){while(!sr); //按键松手检测f++;if(f==4)f=0;}}if(su==0) //实现按键加的功能{delay(5); //消抖if(su==0){while(!su); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp+100;}if(f==2){Alarm_Temp=Alarm_Temp+10;}if(f==3){Alarm_Temp=Alarm_Temp+1;}}}if(sd==0) // 实现按键减的功能{delay(5); //消抖if(sd==0){while(!sd); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp-100;}if(f==2){Alarm_Temp=Alarm_Temp-10;}if(f==3){Alarm_Temp=Alarm_Temp-1;}}}Alarm_Temp= Alarm_Temp;}void LCD_Display(int value,char x,char y){uint abs_value;code uchar Display_Dot[1]={"."};code uchar Display_Unit[1]={"C"};if(value<0){LCD_Pos(x,y-1);LCD_SendData("-",1);}else{LCD_Pos(x,y-1);LCD_SendData("+",1);}abs_value=abs(value);LCD_Pos(x,y);LCD_Write(abs_value/100+0x30,1);LCD_Write(abs_value%100/10+0x30,1);LCD_SendData(Display_Dot,1); //显示小数点LCD_Write(abs_value%10+0x30,1);LCD_SendData(Display_Unit,1); //显示单位}void LCD_DisplayTemp() ////显示实际温度与报警温度值{LCD_Display(Actual_Temp ,0,5);LCD_Display(Alarm_Temp ,1,5);switch(f){case 0:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 1:LCD_Pos(2,5);LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 2: LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 3:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符case 4:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示向上指针LCD_Write(24,1); //显示空白字符}}void DS18B20_TempChange(void) //DS18B20 开始获取温度并转换{DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc); // 写跳过读ROM指令DS18B20_WriteByte(0x44); // 写温度转换指令}void DS18B20_GetTemp() // 从DS18B20读取寄存器中存储的温度数据{uchar a,b;DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc);DS18B20_WriteByte(0xbe);a=DS18B20_Read(); //读低8位b=DS18B20_Read(); //读高8位temp=b;temp<<=8; //两个字节组合为1个字temp=temp|a;if(temp&0x80==0x80) temp=-(~temp+1); //判断实测温度的正负f_temp=temp*0.0625; //温度在寄存器中为12位分辨率位0.0625°temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入 f_temp=f_temp+0.05;Actual_Temp=temp; //temp是整型}void Beep_Warn() //蜂鸣器报警{if(Actual_Temp>Alarm_Temp)beep=0; //蜂鸣器响elsebeep=1; //蜂鸣器不响}void main(){ uint i;LCD_init(); //初始化LCDLCD_Clear(); //LCD清屏LCD_Pos(0,0); //设置显示位置为第一行的第一个字符LCD_SendData(Display1,8); //显示:实际温度LCD_Pos(1,0); //设置显示位置为第二行的第一个字符LCD_SendData(Display2,8); //显示报警温度while(1){ DS18B20_TempChange( );for(i=0;i<10;i++){Beep_Warn ();DS18B20_GetTemp();LCD_DisplayTemp(); //调用显示函数}Key_Scan(); //调用键盘函数}}//程序很棒,仅供参考,不明白处可留言。
DS18B20温度测试程序(51单片机数码管显示)+电路图•下面是电路图采用4位数码管显示程序一共有2个文件:/****************************************************************************** *****************************************ds18b20.h 头文件******************************************************************************* ****************************************/#ifndef _DS18B20_H_#define _DS18B20_H_#include <reg51.h>#define led P1#define ledw P2extern unsigned char f;extern void ds18b20_reset();extern void dela(unsigned char i);extern void ds18b20_write(unsigned char dat);extern unsigned char ds18b20_read();extern unsigned char ds18b20_temp();extern unsigned char ledtab[];#endif/****************************************************************************** **************************************ds18b20.c 文件******************************************************************************* *************************************/#include"ds18b20.h"#define uchar unsigned char#define uint unsigned int#define led P1#define ledw P2uchar ledtab[]={0xc0,0xf9,0xa4, 0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};sbit dq=P3^7 ;uchar delay,f;//uchar f;void dela(uchar i) //5us t=5+i*2{while(--i);}void ds18b20_reset(){while(1){dq=1;dq=0;delay=250; //540us延时,当delay=1时延时为2us ,T=2*xwhile(--delay);dq=1;delay=25;while(--delay);while(dq==0){delay=220;while(--delay);if(dq==1)break;}delay=150;while(--delay);break;}}void ds18b20_write(uchar dat) {uchar i=0;for(i=0;i<8;i++){dq=1;dq=0;delay=3;while(--delay);dq=dat&0x01;delay=35;while(--delay);dq=1;dat=dat>>1;}}uchar ds18b20_read(){uchar i=0,m=0;for(i=0;i<8;i++){//m>>=1dq=1;dq=0;delay=4;while(--delay);dq=1;delay=4;while(--delay);if(dq==1)m|=0x01<<i;//m=m|0x80;delay=25;while(--delay);dq=1;delay=1;while(--delay);}return m;}uchar ds18b20_temp(){uchar temp=0,temph=0,templ=0,k=0; ds18b20_reset();ds18b20_write(0xcc);ds18b20_write(0x44);ds18b20_reset();ds18b20_write(0xcc);ds18b20_write(0xbe);templ=ds18b20_read();temph=ds18b20_read();if((temph&0xf80)!=0){f=1;templ=~templ;temph=~temph;k=templ+1;templ=k;if(templ>0xff){temph++;}}elsef=0;templ=templ>>4;temph=temph<<4;temp=templ|temph;return temp;}/****************************************************************************** ************************************main.c 主文件******************************************************************************* ************************************/#include<reg51.h>#include"ds18b20.h"#define uchar unsigned charvoid main(){uchar a=0,b=0,c=0,temp=0;while(1){temp=ds18b20_temp();a=temp/100;b=temp0/10;c=temp;if(f==1){led=0xbf;ledw=1;dela(5000);ledw=0;dela(600);}led=ledtab[c]; ledw=8;dela(5000); ledw=0;dela(600) ;led=ledtab[b]; ledw=4;dela(5000); ledw=0;dela(600) ;led=ledtab[a]; ledw=2;dela(5000);ledw=0;dela(600) ; }}。
基于51单片机DS18B20温度传感器的C 语言程序和电路DS18B2C 在外形上和三极管很像,有三只脚。
电压范围为 3.0 V 至5.5 V 无需备用电源 测量温度 位 温度转换为 12 位数字格式最大值为 750 毫秒 用户可定义的非易失性温度报警设置 应用范围包 敏感系统。
F 面是DS18B20勺子程序,本人用过完全可行的: #include<reg51.h> #include<intrins.h>#define uchar unsigned char #define uint unsigned int sbit DQ=P2A 0;void reset(); void write_byte(uchar val); uchar read_byte(void); void read_temp(); void work_temp(); uchar data temp_data[2]={0x00,0x00};uchar datadisplay[5]={0x00,0x00,0x00,0x00,0x00}; // 对于温度显示值值 uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x0 数部分查表 main() {while(1) {自己添加 ;void delay1(uint t) {for(;t>0;t--); }/////// 温度控制子函数 void reset(){uchar presence=1; while(presence){ while(presence){DQ=1;_nop_();_nop_(); DQ=0;delay1(50); DQ=1; delay1(6);presence=DQ;}delay1(45); presence=~DQ; }//DS18B20//DS18B20 写命令函数 //DS18B20 读 1 字节函数// 温度读取函数 // 温度数据处理函数DQ=1;}void write_byte(uchar val){uchar i;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();DQ=val&0x01;delay1(6);val=val/2;}DQ=1;_nop_();}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_(); DQ=1;_nop_();_nop_();_nop_();_nop_();if(DQ)value|=0x80;delay1(6);}DQ=1;return(value);void read_temp(){reset();write_byte(0xcc);write_byte(0xbe);temp_data[0]=read_byte();temp_data[1]=read_byte();reset();write_byte(0xcc);write_byte(0x44);}void work_temp(){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; // 低位的低4 位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;}电路:Bi -ij-F16欢迎您的下载,资料仅供参考!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求。
#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define display1 0xfe //数码管1从右至左#define display2 0xfd //数码管2从右至左#define display3 0xfb //数码管3从右至左#define display4 0xf7 //数码管4从右至左#define display5 0xef //数码管5从右至左#define display6 0xdf //数码管6从右至左//===以下IO定义请根据您硬件的连接修改===sbit dula=P2^6;sbit wela=P2^7;sbit led=P2^5;sbit TMDAT=P2^2; //根据实实际情况设定sbit set=P3^4;//设定sbit up=P3^5;//加sbit down=P3^6;//减sbit ld7=P2^4; //输出指示//负温度标志ledsbit point=P0^7; //小数点显示uchar tempint,f,bb,tempth,settemp;//温度整数部分和小数部分int tempdf,c;code unsigned char ledmap[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//7段数码管0~9数字的共阳显示代码和负号位代码(最后一位)void set_ds18b20(); //初始化DS18B20子程序void get_temperature(); //获得温度子程序void read_ds18b20(); //读DS18B20子程序void write_ds18b20(uchar command);//向DS18B20写1字节子程序void delayms(uchar count); //延时count毫秒子程序void disp_temp(); //显示温度子程序void keyscan();void main(){ set_ds18b20();write_ds18b20(0xcc); //发跳过ROM匹配命令write_ds18b20(0xbe); //发出读温度命令read_ds18b20(); //将读出的数据settemp=tempth; //将TH读到单片机SP=0x60; //设置堆栈指针bb=0;led=0;while(1){keyscan();if(bb==0){get_temperature(); //获得温度}disp_temp(); //显示温度}}//***********************初始化DS18B20子程序********************************** //**************************************************************************** void set_ds18b20(){while(1){uchar delay,flag;flag=0;TMDAT=1;delay=1;while(--delay);TMDAT=0; //数据线置低电平delay=250;while(--delay); //低电平保持500usTMDAT=1; //数据线置高电平delay=30;while(--delay); //高电平保持60uswhile(TMDA T==0) //判断DS18B20是否发出低电平信号{delay=210; //DS18B20响应,延时420uswhile(--delay);if(TMDA T) //DS18B20发出高电平初始化成功,返回{flag=1; //DS18B20初始化成功标志//初始化成功LED标志break;}}if(flag) //初始化成功,再延时480us,时序要求{delay=240;while(--delay);break;}}}//***********************获得温度子程序*************************************** //**************************************************************************** void get_temperature() //温度转换、获得温度子程序{set_ds18b20(); //初始化DS18B20write_ds18b20(0xcc); //发跳过ROM匹配命令write_ds18b20(0x44); //发温度转换命令disp_temp(); //显示温度,等待AD转换set_ds18b20();write_ds18b20(0xcc); //发跳过ROM匹配命令write_ds18b20(0xbe); //发出读温度命令read_ds18b20(); //将读出的温度数据保存到tempint和tempdf处}//***********************读DS18B20子程序***************************************//**************************************************************************** void read_ds18b20(){uchar delay,i,j,k,temp,temph,templ;j=3; //读2位字节数据do{for(i=8;i>0;i--) //一个字节分8位读取{temp>>=1; //读取1位右移1位TMDAT=0; //数据线置低电平delay=1;while(--delay);TMDAT=1; //数据线置高电平delay=4;while(--delay); //延时8usif(TMDA T) //读取1位数据temp|=0x80;delay=25; //读取1位数据后延时50uswhile(--delay);}if(j==3)templ=temp;//读取的第一字节存templif(j==2)temph=temp; //读取的第二字节存temphif(j==1)tempth=temp; //读取的第3字节存tempth TH的值}while(--j);f=0;if((temph & 0xf8)!=0x00) //若温度为负的处理,对二进制补码的处理{f=1; //为负温度f置1temph=~temph;templ=~templ;k=templ+1;templ=k;if(k>255){temph++;}}tempdf=templ & 0x0f; //将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdfc=(tempdf*625);tempdf=c;templ>>=4;temph<<=4;tempint=temph|templ;//两字节合并为一个字节}//***********************写DS18B20子程序***************************************//**************************************************************************** void write_ds18b20(uchar command){uchar delay,i;for(i=8;i>0;i--) //将一字节数据一位一位写入{TMDAT=0; //数据线置低电平delay=6; //延时12uswhile(--delay);TMDAT=command&0x01; //将数据放置在数据线上delay=25; //延时50uswhile(--delay);command=command>>1; //准备发送下一位数据TMDAT=1; //发送完一位数据,数据线置高电平}}//***********************显示子程序***************************************//**************************************************************************** void disp_temp(){uchar tempinth,tempintl,cnt,tempinbai,shifen,baifen,gefen,mi;if(bb!=0){tempint=settemp;tempdf=0;cnt=2;}else{cnt=100;}tempinbai=tempint/100;tempinth=tempint%100/10; //整数取模tempintl=tempint%10; //整数取模baifen =tempdf%10000/1000;shifen=tempdf%1000/100;gefen=tempdf%100/10; //小数取模mi=tempdf%10;while(--cnt){if(tempth>tempint)ld7=1;elseld7=1;while(f==1){dula=1;P0=ledmap[10];dula=0;if(tempinth==0){ wela=1;P0=display1;wela=0;delayms(1);goto loop;}else{P0=0xdf;}}delayms(1);P0=ledmap[tempinbai];dula=0;wela=1;P0=display1;//开百位wela=0;delayms(2);dula=1;P0=ledmap[tempinth];dula=0;wela=1;P0=display2;//开十位wela=0;delayms(2);loop:dula=1;P0=ledmap[tempintl];point=1;//小数点显示dula=0;wela=1;P0=display3; //开个位wela=0;delayms(2);dula=1;P0=ledmap[baifen];dula=0;wela=1;P0=display4; //开分位wela=0;delayms(2);dula=1;P0=ledmap[shifen];dula=0;wela=1;P0=display5; //开十分位wela=0;delayms(2);dula=1;P0=ledmap[gefen];dula=0;P0=display6; //开百分位wela=0;delayms(2);}}//***********************延时count ms子程序***************************************//**************************************************************************** void delayms(uchar count) //延时count ms子程序{uchar i,j;do{for(i=5;i>0;i--)for(j=98;j>0;j--);}while(--count);}//***********************键盘扫描子程序*************************************** //****************************************************************************void keyscan() //键盘扫描{if(set==0){delayms(1);}if(set==0){bb++;while(!set); //循环在此非0=1}if(bb==1){if(up==0){delayms(1);}if(up==0){disp_temp();if(settemp<125){settemp++;}while(!up)//非0=1{disp_temp();}}if(down==0){delayms(1);}if(down==0){disp_temp();if(settemp!=0) //不等于0为真执行{settemp--;while(!down) // down为(非0=1)循环执行{disp_temp();}}}}if(bb==2){bb=0;set_ds18b20(); //初始化DS18B20write_ds18b20(0xcc); //发跳过ROM匹配命令write_ds18b20(0x4e); //发温度转换命令write_ds18b20(settemp); //写TH 3//write_ds18b20(settemp); 写到TL 4// write_ds18b20(settemp); 写分辨率 5set_ds18b20(); //初始化DS18B20write_ds18b20(0xcc); //发跳过ROM匹配命令write_ds18b20(0x48);} }。
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);}}。