DS18B20的C语言编程与PROTEUS仿真
以51单片机为核心的DS18B20的数码管显示温度程序Proteus仿真

<TEXr>严********************************************************************文件名:温度采集DS1SB20.C*描述 :该文件实现了用温度传感器件DS18B2O 对温度的采集,并在数码管上显示出 来。
*创建人:谢宜腾,2011年4月6 口 *版本号:1.0***********************************************************************/ /*#iiiclude <reg52.h> #inc lude <intrins.h> #define uchai unsigned char #define umt unsigned mt #define jump_ROM OxCC #define start 0x44 #define read_EEROM OxBE unsigned char TMPHHMPL;uchai code table[10] = {0x3f 、0x06・0x5b 、0x4f,0x66,0x6d,0x7d,0x07,0x7f 、0x6f}; sbit DQ = P2A 3; //OS 18B20 数据口sbit P30=P3A0; sbit P31=P3A 1;*/ /riiic lude<reg52.h> ^include <intriiis.h> #define uchar unsigned char #define uiiit unsisned intsbit DATA = P2A3; /.DS18B20 接入 I 丨uchai codevTExT-I |S-:X1> .・一 一Ml昭TT.I 「勺.丄卫; -- 丄閔:ia<AC4 4P !Of. 士土丄土一f y i XTAL2KUUIAUU P0.VAD1 P02^AD2 P03AD3 RSIPO 4JAD4 POS 认 D5 POS^ADB P0.7/AD7 P2.0/A8 P2.1/ASP22ZA1O PSHMP2 3/A11 ALE P2QM2P2.WM3 cAP26/A14 P1.0/T2 P1.1/T2EXPl.2P2 7/A1S P3.0.RBD P3.1HXD卜y iiPI .3IT Pi .4 PI .5 P3.4/T0 P35/T1 Pl .6P3.6A/<Jr?PI .7 P3.7W"U1189lfi 30 3? 3321丄1314 运至35迫_7i12 ■ ■ ■ .■*f U2DS1333J <TEXT>GND • •table[]={0x3f0x06,0x5b,0x4f,0x66.0x6d.0x7d.0x07.0x7f,0x6f,0x77.0x7c.0x39.0x5e.0x790x71}; char5bai,shi,ge; 〃定义变量/*延时子函数*/void delay(uint num){while(num-);}Iiut.DS 18B20(void) 〃传感器初始化{uchar x=0;DATA= 1; //DQ 复位delay(lO); 〃稍做延时DATA= 0; 〃单片机将DQ拉低delay(80); //精确延时人于480us //450DATA=1; 〃拉高总线delay(20);x=DATA; 〃稍做延时后如果x=0则初始化成功x=l则初始化失败delay(30);}〃读一个字节ReadOneChai(void){uchar 1=0;uchar dat = 0;for (i=8;i>0;i~){DATA = 0; //给脉冲信号dat»=l;DATA=1;//给脉冲信号if(DATA)dat|=0x80; delav(8);}retuin(dat);}〃写一个字节WnteOneChai(unsigned chai dat) uchar 1=0; for (i=8; i>0; i—)DATA=O;DATA= dat&OxOl; delay(lO);DATA= 1;dat»=l;} delay(8);}〃读取温度mt ReadTemperature(void)uchar a=0;uchar b=0;mt t=0;float tt=O;Ink_DS18E20();WnteOneCliai-(OxCC); U跳过读序号列号的操作WnteOneCliai(Ox44); 〃启动温度转换Iiut_DS18B20();WnteOneCliai-(OxCC); 〃跳过读序号列号的操作WiiteOneCliaf(OxBE); 〃读取温度寄存器等(共可读9个寄存器)前两个就是温度a=ReadOneChai();// 低位b=ReadOneChai();//高位t=b;t«=8;t=t|a;tt=t*0.0625;t= tt*10+0.5;retuin(t);}/*显示子函数*/void display(int bai,int shi,mt ge)PO=table[bai];〃显示T•位delay(5O);//—小段延时动态显示P3=table[slu];〃显示百位delay(5O);void maiiiQint temp;while(l){temp=ReadTemperature();// 读温度bai=temp% 1000/100;// 显示百位slii=temp% 100/10;//显示十位ge=temp% 10;//显示个位display(bai,shi,ge);// 显示函数}}。
DS18B20原理及应用实例(源程序+原理图+Proteus仿真)

2、DS18B20 结构:如右图所示,DS18B20 有三只引脚,
VCC、DQ 和 GND。DQ 为数字信号输入/输出端(DQ 一般接控制器(单片机)的一个 I/O 口上,由于单总线为开漏所以需要外接一个 4.7K 的上拉电阻) ;GND 为电源地;VDD 为外 接供电电源输入端 (在寄生电源接线方式时接地) 。 DS18B20 内部结构主要由四部分组成: 64 位光刻 ROM、温度传感器、非挥发的温度报警触发器 TH 和 TL、配置寄存器。 光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列 码。64位光刻ROM的排列是:开始8位是产品类型标号,接着的48位是该DS18B20自身的序 列号,最后8位是前面56位的CRC校验码(循环冗余校验码)。光刻ROM的作用是使每一个 DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。 温度传感器可完成对温度的测量,以12位转化为例,用16位符号扩展的二进制补码读 数形式提供。 RAM数据暂存器,数据在掉电后丢失,DS18B20共9个字节RAM,每个字节为8位。如 下图所示, 当温度转换命令发布后, 经转换所得的温度值以二字节补码形式存放在暂存器的 第0和第1个字节。单片机可通过单线接口读到该数据,读取时低位在前,高位在后,第2、3 字节是用户EEPROM(常用于温度报警值储存)的镜像,用户用来设置最高报警和最低报 警值,在上电复位时其值将被刷新。第4个字节则是用户第3个EEPROM的镜像,用来配置 9~12位的转换精度(即分辨率) 。第5、6、7个字节为计算机自身使用。第8个字节为前8个字 节的CRC码。EEPROM 非易失性记忆体,用于存放长期需要保存的数据,上下限温度报警 值和校验数据,DS18B20共3位EEPROM,并在RAM都存在镜像,以方便用户操作。
多个DS18B20测温的proteus仿真电路及C语言程序设计

多个DS18B20测温的proteus仿真电路及C语言程序设计proteus仿真电路元器件组成C语言程序:#include<reg51.h>sbit DQ=P1^2;sbit DQ1=P1^1;sbit DQ2=P1^0;sbit DQ3=P1^3;#define uchar unsigned char#define uint unsigned intuchar temp_value,temp_value1,temp_value2;uchar code table[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40};void delay_18B20(uint i){while(i--);}void Init_DS18B20(void){uchar x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(60); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}uchar ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}void WriteOneChar(uchar dat){uchar i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;}}void Init_DS18B201(void){uchar x=0;DQ1 = 1; //DQ复位delay_18B20(8); //稍做延时DQ1 = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ1 = 1; //拉高总线delay_18B20(14);x=DQ1; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}uchar ReadOneChar1(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ1 = 0; // 给脉冲信号dat>>=1;DQ1 = 1; // 给脉冲信号if(DQ1)dat|=0x80;delay_18B20(4);}return(dat);}void WriteOneChar1(uchar dat){uchar i=0;for (i=8; i>0; i--){DQ1 = 0;DQ1 = dat&0x01;delay_18B20(5);DQ1 = 1;dat>>=1;}}void Init_DS18B202(void){uchar x=0;DQ2 = 1; //DQ复位delay_18B20(8); //稍做延时DQ2 = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ2 = 1; //拉高总线delay_18B20(14);//x=DQ1; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}uchar ReadOneChar2(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ2 = 0; // 给脉冲信号dat>>=1;DQ2 = 1; // 给脉冲信号if(DQ2)dat|=0x80;delay_18B20(4);}return(dat);}void WriteOneChar2(uchar dat){uchar i=0;for (i=8; i>0; i--){DQ2 = 0;DQ2 = dat&0x01;delay_18B20(5);DQ2 = 1;dat>>=1;}}void ReadTemp(void){uchar a=0;uchar b=0;uchar t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;}void ReadTemp1(void){uchar c=0;uchar d=0;uchar t=0;Init_DS18B201();WriteOneChar1(0xCC); // 跳过读序号列号的操作WriteOneChar1(0x44); // 启动温度转换delay_18B20(100); // this message is wery importantInit_DS18B201();WriteOneChar1(0xCC); //跳过读序号列号的操作WriteOneChar1(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);c=ReadOneChar1(); //读取温度值低位d=ReadOneChar1(); //读取温度值高位temp_value1=d<<4;temp_value1+=(c&0xf0)>>4;}void ReadTemp2(void){uchar e=0;uchar f=0;uchar t=0;Init_DS18B202();WriteOneChar2(0xCC); // 跳过读序号列号的操作WriteOneChar2(0x44); // 启动温度转换delay_18B20(100); // this message is wery importantInit_DS18B202();WriteOneChar2(0xCC); //跳过读序号列号的操作WriteOneChar2(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);e=ReadOneChar2(); //读取温度值低位f=ReadOneChar2(); //读取温度值高位temp_value2=f<<4;temp_value2+=(e&0xf0)>>4;}//显示延时函数void delay(unsigned int z){unsigned int x;unsigned char y;for(x=z;x>0;x--)for(y=200;y>0;y--);}void display (uchar num0,uchar num1,uchar num2,uchar num3,uchar num4,uchar num5) { P2=0XFE;P0=0x00;P0=table[num1];delay(6);P2=0XFD;P0=0x00;P0=table[num0];delay(6);P2=0XFB;P0=0x00;P0=table[10];delay(6);P2=0XF7;P0=0x00;P0=table[num3];delay(6);P2=0XEF;P0=0x00;P0=table[num2];delay(6);P2=0XDF;P0=0x00;P0=table[10];delay(6);P2=0XBF;P0=0x00;P0=table[num5];delay(6);P2=0X7F;P0=0x00;P0=table[num4];delay(6);}main(){ unsigned int i=0;uchar a ,b,c,d,e,f ;while(1){ReadTemp();ReadTemp1();ReadTemp2();b=temp_value/10; //十位a=temp_value%10; //个位d=temp_value1/10; //十位c=temp_value1%10; //个位f=temp_value2/10; //十位e=temp_value2%10; //个位display(b,a,d,c,f,e);}}。
protues DS18B20仿真

程序代码#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define nops(); {_nop_();_nop_();_nop_();_nop_();} sbit DQ=P3^0;uchar code led []={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar code leddg []={ 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc} ;void display (double x);void delayms(uint z);void delay1(uint z);uint ds18b20();uchar reset18b20();void main (){double a;while(1){a=ds18b20();display(a);}}/////////////////////////////////////////////////////void delayms(uint z) //延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}///////////////////////////////void delay1(uint z){while(--z);}/////////////////////////////////////////////////void display (double x) //显示函数{ uint a,b,d,e;int c;double g,h;if (x<=128){ c=(int)x;//45 10.12a=c/100; //提取个位,百位b=c%100/10;d=c%100%10;g=x-c;//0.119999 有误差/* if((((int)(g*100)+1)-g*100)<=0.0001 ) //判断下消除误差g=g+0.01;d=(int)(g*10);h=10*g-d;e=(int)(h*10);*/e=(int)(10*g);P2=0xfe;P0=led[a];delayms(10);P2=0xfd;P0=led[b];delayms(10);P2=0xfb;P0=leddg[d];delayms(10);P2=0xf7;P0=led[e];delayms(10);}else{c=(int)(256-x);b=c/10;d=c%10;e=0;P2=0xfe;P0=0x40;delayms(10);P2=0xfd;P0=led[b];delayms(10);P2=0xfb;P0=leddg[d];delayms(10);P2=0xf7;P0=led[e];delayms(10);}}////////////////////////////////////////////////////uchar reset18b20() //复位18B20{uchar a;DQ=1;_nop_();_nop_();DQ=0;delay1(80);DQ=1;nops();a=DQ;delay1(20);return a ;}////////////////////////////////////////void write (uchar dat) //向18B20里写{uchar i;DQ=1;_nop_();for(i=0;i<8;i++){DQ=0;DQ=dat&0x01;delay1(51);DQ=1;dat>>=1;}}/////////////////////////////////////uchar read() //读取18b20{uchar i,dat=0;DQ=1;_nop_();for(i=0;i<8;i++){DQ=0;nops();dat>>=1;DQ=1;nops();if(DQ){dat|=0x80;}delay1(30);DQ=1;}return dat;}/////////////////////////////////////////////uint ds18b20() //启动18B20温度传感器{uint a,b;reset18b20();write(0xcc); //跳过ID地址write(0x44); //启动温度转换reset18b20();write(0xcc);write(0xbe); //读取温度a=read();b=read();b=b&0x0f;b<<=4;b+=(a&0xf0)>>4 ; //取出A的低4位在和B相加刚好B中存的温度的高低值return b;}。
温度传感器DS18B20在Proteus中的仿真

际需 要 通 过 软 件 设 置 选 择 9 1 位 分 辨 率 ; 户 设 置 的 报 ~ 2 用
警 温 度 存 储 在 芯 片 内 部 EE ROM 中 , 掉 电 保 持 ; 个 P 可 每
且 数 据 的传 输 时 双 向 的 , 有 线 路 简 单 、 件 开 销 少 、 本 具 硬 成 低 、 于 总线 扩 展 和 维 护 等 优 点 。 便 ] D 1B 0是典 型 的 单 总 线 数 字 式 温 度 传 感 器 , 作 电 S8 2 工
压 为 3 5V, 量 温 度 范 围 为 一 5 ~ + 1 5℃ , 根 据 实 ~ 测 5 2 可
Ch n F n e a g,J a g He in
( z o i e st Fu h u 3 0 0 Fu h u Un v r i y, z o 5 1 8,Ch n ) ia
Ab ta t s r c :The pa e n r du e he wor ng p i il c m u c ton p o oc d us ge of1 wie diia t r o e e p r it o c s t ki rncp e, om nia i r t olan a - r g t l he m m t r DS1 8B20 .T h e s fw a e pr e soft m p r t e r a n a he Pr t us sm u a in a egie o t r oc s e e a ur e dig nd t o e i l to r v n. Co p rs t e n sm ulto e u t nd e e i e a m a ion be w e i a i n r s lsa xp rm nt l r s lsa e s w n. e u t r ho
基于DS18B20的数字温度监控系统的Proteus设计

基于DS18B20的数字温度监控系统的Proteus设计学院:电子信息与电气工程学院设计任务书题目基于DS18B20的数字温度监控系统Proteus设计一、设计的目的1.将理论知识运用于实践当中,掌握模拟电路设计的基本方法、基本步骤以及基本要求。
在实践中了解电子器件的功能与作用。
2.学会信号发生器的设计方法,完成要求的性能和指标。
3.锻炼、提高在电子设计中发现问题、分析问题、解决问题的能力。
二、设计的内容及要求1. 测量温度值精度为±1℃;2. 系统允许的误差范围为1℃以内;3. 系统可由用户预设温度值,测温范围为-55℃~+125℃;4. 通过DS18B20传感器和系统连接,能实时准确检测到现场温度;5. 把现场实时检测到的温度通过LCD1602液晶显示出来;6. 报警温度设定和报警:根据需要可以设置报警温度,并且当达到报警温度时会发出报警提示;三、指导教师评语四、成绩指导教师(签章)年月日目录摘要..................................................... - 3 - 1.绪论................................................... - 4 -1.1 课题研究背景....................................... - 4 -1.2 课题内容及要求..................................... - 5 -2.温度测控方案论证........................................ - 6 -2.1 热敏电阻测温...................................... - 6 -2.2 数字温度传感器测温................................ - 6 -3.系统方案概述............................................ - 7 -4.硬件部分................................................ - 8 -4.1 单片机最小系统设计................................ - 8 -4.1.1 AT89C52单片机简介........................... - 8 -4.1.2 晶振电路.................................... - 13 -4.1.3 复位电路.................................... - 14 -4.1.4 排阻电路.................................... - 14 -4.2 DS18B20温度传感器................................ - 15 -4.2.1 DS18B20简介................................ - 15 -4.2.2 DS18B20内部结构............................ - 17 -4.2.3 DS18B20电路................................ - 21 -4.3 LCD1602液晶显示电路.............................. - 22 -4.4按键模块.......................................... - 24 -4.5报警模块.......................................... - 26 -4.5.1蜂鸣器报警模块.............................. - 26 -4.5.2 LED报警模块................................ - 27 -5.软件部分............................................... - 28 -5.1 软件开发平台..................................... - 28 -5.2 主程序设计....................................... - 28 -5.3 DS18B20程序设计.................................. - 29 -5.3.1 初始化...................................... - 29 -5.3.2 ROM操作命令................................ - 30 -5.3.3 数据处理.................................... - 30 -5.3.4 程序流程图.................................. - 32 -5.4 LCD1602程序流程图设计............................ - 32 -5.5 报警模块程序设计................................. - 33 -6.仿真与测试............................................. - 34 -6.1 仿真设计平台..................................... - 34 -6.2 仿真结果分析..................................... - 35 - 结论.................................................... - 36 - 致谢.................................................... - 37 -摘要在日常生活及工业生产过程中,经常要用到温度的检测及控制,温度是生产过程和科学实验中普遍而且重要的物理参数之一。
基于DSB温度传感器温控系统的Proteus仿真

基于DS18B20 温度传感器温控系统的Pr o t eu s 仿真DS18B20温度传感器是美国DALLAS^导体公司推出的支持“一线总线”接口的传感器。
具有功耗低、性能高、抗干扰能力强的特点,可以直接将温度转化为串行数字信号供处理器处理。
DS18B2C传感器具有以下一些特性:(1)测温范围-55 C至+ 125C,在-10 C至+85C时的精度为正负0.5 C;(2)适应电压的范围在 3.0 至 5.5V;(3)单线接口,只用一条口线就可以与微处理器的双向通信;(4)支持多点组网,多个DS18B2C并接在一根口线上就可实现多点测温;(5)测量结果直接输出数字温度信号,通过单线串行传输给微处理器;(6)具有负压特性,电源极性接反芯片不会烧坏,只是不能正常工作;(7)可编程分辨率为9至12位,对应的分辨温度分别是0.5 °C,0.25 C, 0.125C, 0.0625 C,能够实现高精度测温。
(8)在9位分辨率时可在93.75ms内把温度值转换为数字;在12位分辨率时可在750us内把温度值转换为数字;(9)传送数据时可传送CRC校验码,抗干扰纠错能力强。
DS18B20勺引脚封装图如下:各引脚定义如下:GND电源地DQ信号输入输出V DD:电源正极NC空DS18B20单总线技术:DS18B20采用单条信号线,既可以传输数据,也可以传输时钟。
其数据传输是双向的,这种单总线技术线路简单,硬件开销小,成本低廉,便于总线扩展与维护。
单总线通常需要外接一个4.7K 的上拉电阻。
它与处理器的连接非常简单,通常连接方式如下图:DQ端外接一个上拉电阻,与处理器的任一端口连接。
DS18B20工作原理1. ROM功能命令(1)[33H] Read ROM读ROM把DS18B20传感器的ROM中编码读出来。
(2)[55H] Match ROM匹配ROM发出该命令接着会发送64位包含具体DS18B2C序列号的ROM®码,与该编码序列号相同的DS18B2C就会做出响应,序列号不匹配的DS18B20继续等待,不做响应。
单片机 ds18b20温度测量 proteus仿真

#include<reg51.h>sbit DQ=P3^0;unsigned int temp;unsigned char dis[4]={0,0,0,0};unsigned charled[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0xff,0xbf};//分别为0-9,不显示,负号Unsigned charled1[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//带小数点显示void delay(unsigned int i) //如果i是unsigend char类型,则会出现错误结果{while(i--);}void Init(void)//初始化{//unsigned char flag=0;DQ = 0; //单片机将DQ拉低delay(100); //精确延时大于480us小于960usDQ = 1; //拉高总线delay(30);//flag=DQ; //稍做延时后如果flag=0则初始化成功flag=1则初始化失败//delay(20);}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 Display(unsigned int temp) //显示程序{if(temp<=0x0800){ temp>>=4; //右移4位,相当于乘0.0625,将温度化为十进制temp*=10; //扩大10倍,显示一位小数dis[0]=temp/1000; //千位dis[1]=temp%1000/100; //百位dis[2]=temp%1000%100/10; //十位dis[3]=temp%1000%100%10; //个位}else{temp=~temp;temp+=1;temp>>=4;dis[0]=0x0c; //负数dis[1]=temp%100/10; //百位dis[2]=temp%100%10; //十位dis[3]=0; //个位}P2=0x01; //先片选,在段选,反过来就不能正常显示P0=led[dis[0]];delay(200);delay(200);P2=0x02;P0=led[dis[1]];delay(200);delay(200);P2=0x04;P0=led1[dis[2]];delay(200);delay(200);P2=0x08;P0=led[dis[3]];delay(200);delay(200);}main(){unsigned char tl=0,th=0;while(1){Init();Write(0xCC); // 跳过读序号列号的操作Write(0x44); // 启动温度转换delay(100);Init();Write(0xCC); //跳过读序号列号的操作Write(0xBE); //读取温度寄存器等delay(100);tl=Read(); //读取温度值低位th=Read(); //读取温度值高位temp=th<<8;temp|=tl;Display(temp);}}。
DS18B20原理及应用实例(源程序+原理图+Proteus仿真)

2 / 13
2012 年 8 月 13 日星期一
举例如下:
4ቤተ መጻሕፍቲ ባይዱDS18B20 的初始化:
根据 DS18B20 的通讯协议,主机(单片机)控制 DS18B20 完成温度转换必须经过三个 步骤:每一次读写之前都要对 DS18B20 进行复位操作,复位成功后发送一条 ROM 指令, 最后发送 RAM 指令,这样才能对 DS18B20 进行预定的操作。复位要求主 CPU 将数据线下 拉 500 微秒,然后释放,当 DS18B20 收到信号后等待 16~60 微秒左右,后发出 60~240 微秒的存在低脉冲,主 CPU 收到此信号表示复位成功。 (1) 先将数据线 DQ 置高电平“1”。 (2) 延时(该时间要求的不是很严格,但是尽可能的短一点) (3) 数据线拉到低电平“0”。 (4) 延时 750 微秒(该时间的时间范围可以从 480 到 960 微秒) 。 (5) 数据线拉到高电平“1”。 (6) 延时等待(如果初始化成功则在 15 到 60 微妙时间之内产生一个由 DS18B20 所返回 的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使 程序进入死循环,所以要进行超时控制) 。 (7) 若 CPU 读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平 算起(第(5)步的时间算起)最少要 480 微秒。 (8) 将数据线再次拉高到高电平“1”后结束。 初始化程序如下: uchar Init_DS18B20() { uchar status; //status 为 DS18B20 返回的状态 DQ = 1; Delay(8); DQ = 0; Delay(90); DQ = 1;
8、DS18B20 应用举例(一)
如下图所示:DQ 通过 4.7K 上拉电阻外接正电源(由于单总线为开漏所以需要外接一 个 4.7K 的上拉电阻),并连接单片机 P3.3 口。 本例中,1602LCD 显示 DS18B20 所测量的外部温度,调节 DS18B20 模拟改变外界 温度时,新的温度将刷新显示在 LCD 上。
以51单片机为核心的DS18B20的数码管显示温度程序+Proteus仿真

//DS18B20的读写程序,数据脚P3.3 ////温度传感器18B20汇编程序,采用器件默认的12位转化////最大转化时间750微秒,显示温度-55到+125度,显示精度////为0.1度,显示采用4位LED共阳显示测温值////P0口为段码输入,P24~P27为位选///***************************************************/#include "reg51.h"#include "intrins.h" //_nop_();延时函数用#define Disdata P0 //段码输出口#define discan P2 //扫描口#define uchar unsigned char#define uint unsigned intsbit DQ=P3^3; //温度输入口sbit DIN=P0^7; //LED小数点控制uint h;uchar flag;//**************温度小数部分用查表法***********//uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};//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]={0x7f,0xbf,0xdf,0xef}; //列扫描控制字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=0xff;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_(); //4us if(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); // 发转换命令}///***********温度数据处理函数**********/ void work_temp(){uchar n=0;uchar doth,dotl;uchar flag3=1,flag2=1; //数字显示修正标记if((temp_data[1]&0xf8)!=0x00){temp_data[1]=~(temp_data[1]);temp_data[0]=~(temp_data[0])+1;n=1;flag=1;}//负温度求补码if(temp_data[0]>255){temp_data[1]++;}display[4]=temp_data[0]&0x0f;display[0]=ditab[display[4]];doth=display[0]/10;dotl=display[0]%10;display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4); display[3]=display[4]/100;display[2]=display[4]/10%10;display[1]=display[4]%10;if(!display[3]){display[3]=0x0a;flag3=0;if(!display[2]){display[2]=0x0a;flag2=0;}}//最高位为0时都不显示if(n){display[3]=0x0b;//负温度时最高位显示"-"flag3=0;}}/////**************主函数****************/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(); //处理温度数据scan(); //显示温度值2秒}}////*********************结束**************************//。
基于Proteus仿真实例DS18B20

DS18B20之Proteus仿真使用分类:传感器AVR与C2010-05-22 12:20 886人阅读评论(0) 收藏举报对于数字单线温度传感器DS18B20可谓是久仰大名,但是一直都没有认真的去弄过。
曾经看过网络上流传的中文PDF文档,感到其对时序要求比较严格,其他倒无所谓。
这几天感到有必要把曾经弄过的以及没有弄过但是比较常用的传感器写个范例,以便于以后的工作。
就从这个18B20开始了。
结果。
第一天没搞定!第二天。
又没搞定!这下怒了,虽说不是什么高手,但是搞个温度传感器都要2天那还了得!于是在周末决定好好研究一下。
先来看18B20的时序。
-----K,竟然不能插入图片!好吧,口述。
一般要求DS18B20数据总线使用4.7K左右的电阻上拉,所以在MCU或者DS18B20没有强制将总线拉低的情况下,总线应该是高电平的。
复位的要求是持续拉低总线480us以上(小于960us),然后释放总线。
对于AVR之类的有数据方向存储器的MCU,将数据方向设置为输入即可。
这个时候总线应该会被上拉电阻拉高。
然后静静等待,如果DS18B20正常,那它应该会在15-60us之后将总线拉低60-240us。
我对这两个数据感到非常的不爽。
MCU什么时候采样电平最合适呢?只能在MCU释放总线60us后,才能保证此时DS18B20如果存在肯定是将总线拉低的,但是也不能再后了,因为DS18B20将总线拉低最短只有60us。
万一DS18B20在MCU释放总线后15us后就拉低了总线,且又仅拉低60us。
留给MCU采样的时间只有15us了!郁闷!这里要注意一条C的语句可能执行N多个机器周期,所以还要注意指令执行时间,如果你的MCU时钟比较慢,那就等死吧。
恩还有,从释放总线开始到开始执行其他操作这段时间最短也要480us。
(其实我没这么干也成功了)写时序:DS18B20以下降沿开始表示一次操作开始。
无论读写都是如此。
写操作有写“1”与写“0”(二进制就是好啊)。
DS18B20用LCD1602显示Proteus仿真

/******************************DIY-18B20-LCD1602******************************/#include<pic.h>__CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡#define uchar unsigned char //给unsigned char起别名uchar#define uint unsigned int#define DQ RA4 //定义18B20数据端口#define DQ_DIR TRISA4 //定义18B20D口方向寄存器#define DQ_HIGH() DQ_DIR =1 //设置数据口为输入#define DQ_LOW() DQ = 0; DQ_DIR = 0 //设置数据口为输出unsigned char temp1 = 0 ; //采集到的温度高8位unsigned char temp2 = 0; //采集到的温度低8位unsigned char D[]={"DS18B20 TEMP:"};unsigned char T[10];/*********************函数延时部分********************************/void delayms(uint ms){uchar i;while(ms--){for(i=0;i<87;i++);}}/*延时时间为:(10个固定周期2.5US)+(次数*【1.5US(5+1个周期)】=总延时时间)即就是(10+6N)*T=time */void delay(unsigned char t) //跳入这个循环需要3个指令周期{ //跳出这个循环需要3个指令周期while(t>0) //while第一次判断语句要消耗3个指令周期,之后需要5个t--; //t=t-1,消耗1个指令周期} //也就是说t=0时需要10个指令周期void delay10us(void) //4Mhz下一个指令周期NOP为1Us{NOP();NOP();NOP();NOP();NOP();NOP();}void delay40us(void) //延时42us{delay10us();delay10us();delay10us();delay10us();}/*******************18B20部分********************************/void reset(void){char presence = 1;DQ_HIGH();NOP();NOP();while (presence){DQ_LOW() ; //主机拉至低电平delay(100); //延时610usDQ_HIGH(); //释放总线等电阻拉高总线,并保持15~60usdelay40us(); //延时42usif (DQ == 1) presence = 1; //没有接收到应答信号,继续复位else presence = 0; //接收到应答信号delay(100); //延时610us}}void write_byte(uchar data){uchar i;uchar temp;DQ_HIGH();NOP();NOP();for (i = 8;i > 0;i--){temp = data & 0x01; //最低位移出DQ_LOW();NOP();NOP();NOP();NOP();NOP();//从高拉至低电平,产生写时间隙5usif (temp == 1)DQ_HIGH(); //如果写1,拉高电平delay40us(); //延时42usDQ_HIGH();NOP();NOP();data = data >> 1; //右移一位}}uchar read_byte(void){uchar i;uchar data = 0; //读出温度uchar j;for (i = 8;i > 0;i--){data >>= 1;DQ_HIGH();NOP();NOP();DQ_LOW();NOP();NOP();NOP();NOP();NOP();NOP(); //6usDQ_HIGH(); //拉至高电平NOP();NOP();NOP();NOP();NOP(); //4usj = DQ;if (j)data=data |0x80;delay(10); //延时70us}return (data);}void get_temp(void){float temp,m=0,n=0;unsigned char x;// m=0;// unsigned long temper1;unsigned char temper;unsigned char lsb,msb;reset();write_byte(0xCC);write_byte(0x44);delayms(100);reset();write_byte(0xCC);write_byte(0xBE);temp1=read_byte();temp2=read_byte();lsb=temp1&0x0f; //temp1的低4位为小数部分msb=(temp1>>4)|(temp2<<4);//temp1的高4位和temp2拼成整数部分T[0]=msb/10+0x30;T[1]=msb%10+0x30;T[2]='.';// temp=(temp2*256+temp1)*0.0625*10000;// temper=(unsigned char)temp;// T[0]=temper/100000+0x30;;// T[1]=temper%100000/10000+0x30;// T[2]='.';// T[3]=temper%10000/1000+0x30;// T[4]=temper%1000/100+0x30;// T[5]=temper%100/10+0x30;// T[6]=temper%10+0x30;if(lsb&0x08) m=m+0.5;if(lsb&0x04) m=m+0.25;if(lsb&0x02) m=m+0.125;if(lsb&0x01) m=m+0.0625;n=m*10000;x=(unsigned char)n;T[3]=x/1000+0x30;T[4]=x%1000/100+0x30;T[5]=x%100/10+0x30;T[6]=x%10+0x30;T[7]=0xdf;T[8]=0x43;T[9]='\0';}/******************************LCD1602部分**********************************/ #define rs RC0#define rw RC1#define ep RC2#define LCD PORTDvoid Busy_Check(void) //测试忙碌状态{uchar LCD_Status;rs=0;rw=1;ep=1;NOP();NOP();NOP();NOP();while(1){LCD_Status=PORTD;LCD_Status&=0x80;if(LCD_Status==0);break;}ep=0;}void lcd_wcmd(uchar cmd) //写入指令数据到lcd {Busy_Check();TRISD=0x00;rs=0;rw=0;ep=0;NOP();NOP();LCD=cmd;NOP();NOP();NOP();NOP();ep=1;NOP();NOP();NOP();NOP();ep=0;}void lcd_wdat(uchar dat) //写入字符显示数据到lcd {Busy_Check();TRISD=0x00;rs=1;rw=0;ep=0;LCD=dat;NOP();NOP();NOP();NOP();ep=1;NOP();NOP();NOP();NOP();ep=0;}void lcd_pos(uchar pos) //设定显示位置{lcd_wcmd(pos|0x80); //设定lcd当前光标的位置}void LCD_disp(void){uchar i=0;lcd_pos(0x00);while(D[i]!='\0'){lcd_wdat(D[i]);i++;}lcd_pos(0x40); //设置显示位置为第2行的的二个位置i=0;while(T[i]!='\0'){lcd_wdat(T[i]);i++;}}void lcd_init(void) //lcd初始化设定{lcd_wcmd(0x38);delayms(1);lcd_wcmd(0x0F);delayms(1);lcd_wcmd(0x06);delayms(1);lcd_wcmd(0x01);delayms(1);}/****************************主函数部分***********************************/void main(void){TRISA=0xff; //初始化RA5-RA0的输入输出方向PORTA=0x00; //初始化RA5-RA0数值TRISC=0x00;//初始化对RC口的初始方向进行设置设置为输出TRISD=0x00;//初始化RD口的初始方向进行设置,设置为输出PORTC=0xFF; //初始化RC口的数值PORTD=0x00; //初始化RD口的数值lcd_init();delayms(10);while(1){get_temp();LCD_disp();}}。
DS18B20_proteus仿真(BCD数码管显示测试)

TEMP_ZH EQU 24H ;实测温度值存放单元TEMPL EQU 25HTEMPH EQU 26HTEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU 28H ;低温报警值存放单元TEMPHC EQU 29H ;正、负温度值标记TEMPLC EQU 2AHTEMPFC EQU 2BHFLAG1 EQU 20H.0 ;DS18B20是否存在标志DQ EQU P3.3 ;DS18B20数据信号ORG 0000H;*************************** 主程序开始 ******************************;*************************** 主循环开始 ****************************** START: LCALL RST ;调用DS18B20复位子程序JNB FLAG1,START ;DS18B20不存在MOV A,#0CCH ;跳过ROM匹配命令LCALL WRITEMOV A,#44H ;温度转换命令LCALL WRITELCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0BEH ;读温度命令LCALL WRITELCALL READ ;调用DS18B20数据读取操作子程序LCALL CONVTEMP ;调用温度数据BCD 码处理子程序;MOV P1,70H ;小数位;MOV P1,71H ;个位;MOV P1,72H ;十位;MOV P1,73H ;百位(正温度大于或等于100=1,小于100=A,负温度=B)MOV P2,TEMPLC ;个位+小数位MOV P1,TEMPHC ;百位+十位SJMP START ;循环;*************************** 主循环结束 ******************************;****************************DS18B20复位子程序 ***************************** RST: SETB DQNOPCLR DQMOV R0,#6BH ;主机发出延时复位低脉冲MOV R1,#04HTSR1: DJNZ R0,$MOV R0,#6BHDJNZ R1,TSR1SETB DQ ;拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3 ;等待DS18B20回应DJNZ R0,TSR2JMP TSR4 ; 延时TSR3: SETB FLAG1 ; 置1标志位,表示DS1820存在JMP TSR5TSR4: CLR FLAG1 ; 清0标志位,表示DS1820不存在JMP TSR7TSR5: MOV R0,#06BHTSR6: DJNZ R0,$ ; 时序要求延时一段时间;************************ DS18B20暂存器操作子程序 *************************** RE_18B20:JB FLAG1,RE_18B20ARETRE_18B20A:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEWR_SCRAPD:MOV A,#4EH ;写暂器LCALL WRITEMOV A,TEMP_TH ;TH(报警上限)LCALL WRITEMOV A,TEMP_TL ;TL(报警下限)LCALL WRITEMOV A,#7FH ;12位精度LCALL WRITERET;*********************** DS18B20数据写入操作子程序 ************************ WRITE: MOV R2,#8 ;一共8位数据CLR CWR1: CLR DQ ;开始写入DS18B20总线要处于复位(低)状态MOV R3,#07DJNZ R3,$ ;总线复位保持16微妙以上RRC A ;把一个字节DATA 分成8个BIT环移给CMOV DQ,C ;写入一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙SETB DQ ;重新释放总线NOPDJNZ R2,WR1 ;写入下一位SETB DQRET;********************** DS18B20数据读取操作子程序 ************************** READ: MOV R4,#4 ;将温度低位、高位、TH、TL从DS18B20中读出MOV R1,#TEMPL ;存入25H、26H、27H、28H单元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQ ;读前总线保持为低NOPNOPNOPSETB DQ ;开始读总线释放MOV R3,#09 ;延时18微妙DJNZ R3,$MOV C,DQ ;从DS18B20总线读得一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙RRC A ;把读得的位值环移给ADJNZ R2,RE01 ;读下一位MOV @R1,AINC R1DJNZ R4,RE00RET;************************ 温度值 BCD 码处理子程序 ************************* CONVTEMP: MOV A,TEMPH ;判温度是否零下ANL A,#08HJZ TEMPC1 ;温度零上转CLR CMOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,AMOV TEMPHC,#0BH ;负温度标志MOV TEMPFC,#0BHSJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ;正温度标志MOV TEMPFC,#0AHTEMPC11: MOV A,TEMPHCSWAP AMOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;乘0.0625MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分 BCDMOV A,TEMPL ;整数部分ANL A,#0F0H ;取出高四位SWAP AMOV TEMPL,AMOV A,TEMPH ;取出低四位ANL A,#0FHSWAP AORL A,TEMPL ;重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0HSWAP AORL A,TEMPHC ;TEMPHC LOW = 十位数 BCDMOV TEMPHC,AMOV A,TEMPLANL A,#0FHSWAP A ;TEMPLC HI = 个位数 BCDORL A,TEMPLCMOV TEMPLC,AMOV A,R4JZ TEMPC12ANL A,#0FHSWAP AMOV R4,AMOV A,TEMPHC ;TEMPHC HI = 百位数 BCDANL A,#0FHORL A,R4MOV TEMPHC,ATEMPC12: RET;************************ 二-十进制转换子程序 ***************************** HEX2BCD1: MOV B,#064HDIV ABMOV R4,AMOV A,#0AHXCH A,BDIV AB;************************ 显示区 BCD 码温度值刷新子程序 ********************** DISPBCD: MOV A,TEMPLCANL A,#0FHMOV 70H,A ;小数位MOV A,TEMPLCSWAP AANL A,#0FHMOV 71H,A ;个位MOV A,TEMPHCANL A,#0FHMOV 72H,A ;十位MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,A ;百位RETEND。
多路DS18B20温度传感器-protues仿真

//编程:武汉理工大学XP//时间2012/5/25//版本:V1.0//DS18B20设置为12位精度//#include"reg51.h"unsigned char code table1[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09};//不带小数点断码unsigned char code table2[]={0x02,0x9e,0x24,0x0c,0x98,0x48,0x40,0x1e,0x00,0x08}; //带小数点断码unsigned char code string[]="temperature";unsigned char code numtable[]="0123456789ABCDEF"; //液晶显示的字符unsigned char code txttable[]="-. "; //液晶显示的符号,负号,小数点,以及空格unsigned char code ROM_1[]={0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0x8e}; //U1 ROM值unsigned char code ROM_2[]={0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9}; //U2 ROM值unsigned char code ROM_3[]={0x28,0x32,0xc5,0xb8,0x00,0x00,0x00,0xe0}; //U3 ROM值unsigned char code ROM_4[]={0x28,0x33,0xc5,0xb8,0x00,0x00,0x00,0xd7}; //U4 ROM值unsigned char ROM[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //初始化的ROM值,//用于装载读取的DS18B20的ROM值sbit ds=P3^0; //总线//定义的数码管接口sbit qian=P2^0; //数码管千位sbit bai=P2^1; //数码管百位sbit shi=P2^2; //数码管十位sbit ge=P2^3; //数码管个位sbit E=P2^4; //液晶使能端口sbit CONTROL_DA TE=P2^5; //液晶写数据与写控制命令控制端int temp,shuju[5]={0}; //存放温度和温度数据处理后得到的液晶要显示的数int flag=1; //温度正负标志位//延时函数//void Delay(int z){ int x;for(;z>0;z--)for(x=110;x>0;x--);}//写入对液晶的控制命令//void Lcd_write_control(char date){CONTROL_DA TE=0;P1=date;Delay(50);E=1;Delay(50);E=0;}//写入要显示的数据//void Lcd_write_date(char date){CONTROL_DA TE=1;P1=date;Delay(10);E=1;Delay(10);E=0;}//液晶初始化//void LCD_INIT(void){E=0;Lcd_write_control(0x38); //设置16*2显示,5*7点阵,8为数据接口Lcd_write_control(0x0c); //设置开显示,不显示光标Lcd_write_control(0x06); //写一个字符后地址指针加一Lcd_write_control(0x01); //显示清零,数据指针清零}//DS18B20初始化//void DS_rest(void){int i;ds=0;i=103;while(i>0) i--;ds=1;i=4;while(i>0) i--;}//读一位数据//bit Temp_read_bit(void){int i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return dat;}//读取一个字节的温度数据// unsigned char Temp_read(void){unsigned char i,j,dat;dat=0;for(i=1;i<=8;i++){j=Temp_read_bit();dat=(j<<7)|(dat>>1);}return dat;}//向DS18B20写入一位数据//void DS_writebyte(unsigned char dat) {int i;unsigned char j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){ds=0;i++;i++;ds=1;i=8;while(i>0) i--;}else{ds=0;i=8;while(i>0) i--;ds=1;i++;i++;}}}//匹配DS18B20的ROM//void MATCH_ROM(unsigned char *ROM_X) { int i;DS_rest();Delay(1);DS_writebyte(0x55);for(i=0;i<8;i++){DS_writebyte(*(ROM_X+i));}}//开始温度转换//void Temp_change(void){DS_rest();Delay(1);DS_writebyte(0xcc);//MATCH_ROM();DS_writebyte(0x44);}//获取温度数据//int Get_temp(){unsigned char a,b;static int i=1;DS_rest();Delay(1);//tempwritebyte(0xcc);//MATCH_ROM(ROM_1);switch(i){case 1: MA TCH_ROM(ROM_1); i++; break;case 2: MA TCH_ROM(ROM_2); i++; break;case 3: MA TCH_ROM(ROM_3); i++; break;case 4: MA TCH_ROM(ROM_4); i=1; break;}DS_writebyte(0xbe);a=Temp_read();b=Temp_read();if(b>=90){temp=~(a+b*256+1); flag=0;}else{temp=a+b*256; flag=1;}temp=temp*6.25;return temp;}//液晶显示//void Lcd_display(int t){int n=1,weishu1=0;static weishu2=0;Lcd_write_control(0x80+0x40);while(t>0){shuju[n++]=t%10;t/=10;}weishu1=n-1;if(flag==0)Lcd_write_date(txttable[0]);if(weishu1<=2)Lcd_write_date('0');for(n=weishu1;n>2;n--)Lcd_write_date(numtable[shuju[n]]);Lcd_write_date(txttable[1]);while(n>0){Lcd_write_date(numtable[shuju[n]]);n--;}if(weishu1<weishu2)Lcd_write_date(txttable[2]);weishu2=weishu1;}//读取DS18B20的ROM数据//void READ_ROM(void){ int i=0;DS_rest();Delay(1);DS_writebyte(0x33);for(i=0;i<8;i++)ROM[i]=Temp_read();}//显示DS18B20的ROM数据//void DISPLAY_ROM(void){int i;unsigned char t;Lcd_write_control(0x80);for(i=0;i<4;i++){ t=ROM[i];Lcd_write_date(numtable[t/16]);Lcd_write_date(numtable[ROM[i]%16]);Lcd_write_date(0x20);}Lcd_write_control(0x80+0x40);for(;i<8;i++){ t=ROM[i];Lcd_write_date(numtable[t/16]);Lcd_write_date(numtable[ROM[i]%16]);Lcd_write_date(0x20);}}main(){ int t,i;LCD_INIT();Lcd_write_control(0x80);for(i=0;i<11;i++)Lcd_write_date(string[i]);//循环显示温度while(1){Temp_change();t=Get_temp();Lcd_display(t);Delay(1000);}//显示DS18B20的ROM值//首先要用这个函数读取DS18B20的ROM值//然后将ROM值写到ROM[]数组中//最后注释掉ROM[]的显示,改为显示循环显示温度/* while(1){READ_ROM();DISPLAY_ROM();} */}。
利用单片机控制18B20温度控制Proteus仿真

仿真图:程序:#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned char#define NOP() {_nop_();_nop_();_nop_();_nop_();}//------LCD引脚-----sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_EN=P2^2;sbit DQ=P3^3;uchar code table[]={"Temperature:"}; //LCD第一行显示uchar temp_dis[]={" C"}; //LCD第二行//-----温度字符-----uchar code Temperature[]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};/* ************* 温度小数部分表********** */uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};uchar Temp_value[]={0x00,0x00}; //从DS18B20读取的温度值uchar digital[]={0,0,0,0}; //各温度数位uchar Current_T=0; //当前温度的整数部分//--------延时-------void delay(uint ms){uint t;while(ms--)for(t=0;t<120;t++);}void Delayus(uint m){while(m--);}//-------读LCD状态-------uchar read_lcd_state(){uchar state;LCD_RS=0;LCD_RW=1;LCD_EN=1;_nop_();state=P0;LCD_EN=0;_nop_();return state;}//-------忙等待------void lcd_busy_wait(){while((read_lcd_state() & 0x80)==0x80);NOP();}//----------LCD写指令----------void lcd_write_com(uchar com){lcd_busy_wait();LCD_RS=0; //RS为0时,写指令,RS为1时,写数据LCD_RW=0;P0=com;NOP();LCD_EN=1;NOP();LCD_EN=0;}//----------LCD写数据----------void lcd_write_data(uchar dat){lcd_busy_wait();LCD_RS=1;LCD_RW=0;P0=dat;NOP(); //如果用delay()延时函数时,延时时间较长,导致LCD显示与电压表示数不同步LCD_EN=1;NOP();LCD_EN=0;}//-------LCD初始化-------void lcd_init(){LCD_EN=0;lcd_write_com(0x38); //LCD显示模式设置lcd_write_com(0x0c); //LCD显示开/关及光标设置lcd_write_com(0x06); //当写一个字符后地址指针加1,且光标加1lcd_write_com(0x01); //显示清屏}//---------设置液晶显示位置-----------void set_lcd_pos(uchar p){lcd_write_com(p | 0x80);}//---------液晶显示程序----------void lcd_print(uchar p,uchar *s,uint low){uint num;set_lcd_pos(p);for(num=0;num<low;num++){lcd_write_data(s[num]);delay(1);}}/* ******初始化DS18B20********/void Init_DS18B20(){uchar status=0;DQ=1; //DQ复位Delayus(8); //稍作延时DQ=0; //单片机将DQ拉低Delayus(80); //精确延时大于480usDQ=1; //拉高总线Delayus(8);status=DQ;Delayus(20);}/* ******* 从DS18B20读入数据******* */uchar ReadOneChar(){uchar i,dat = 0;for(i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;Delayus(4);}return(dat);}/* ******** 向DS18B20写命令******** */void WriteOneChar(uchar dat){uchar i=0;for(i=8;i>0;i--){DQ = 0;DQ = dat&0x01;Delayus(5);DQ = 1;dat>>=1;}}/* ******DS18B20程序读取温度********* */ void ReadTemperature(){Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x44); //启动温度转换Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等,前两个就是温度Temp_value[0]=ReadOneChar(); //低八位Temp_value[1]=ReadOneChar(); //高八位}//--------显示当前温度值-------void display_temp(){uchar ng=0; //负数标志// 高5位全为1则为负数,为负数时取反加1,并设置负数标志if((Temp_value[1] & 0xf8)==0xf8){Temp_value[1]=~Temp_value[1];Temp_value[0]=~Temp_value[0]+1;if(Temp_value[0]==0x00)Temp_value[1]++;ng=1;}digital[0]=ditab[Temp_value[0] & 0x0f]; //温度小数部分// 获取温度整数部分(高字节中的低3位和低字节中的高4位)Current_T=((Temp_value[0] & 0xf0)>>4)|((Temp_value[1] & 0x07)<<4);digital[3]=Current_T/100; //分解digital[2]=Current_T%100/10;digital[1]=Current_T%10;// LCD显示temp_dis[7]=digital[0]+'0';temp_dis[6]='.';temp_dis[5]=digital[1]+'0';temp_dis[4]=digital[2]+'0';temp_dis[3]=digital[3]+'0';if(digital[3]==0) //高位为0时不显示temp_dis[3]=' ';if(digital[2]==0&&digital[3]==0)temp_dis[4]=' ';if(ng){if(temp_dis[4]==' ')temp_dis[4]='-';else if(temp_dis[3]==' ')temp_dis[3]='-';elsetemp_dis[2]='-';}lcd_print(0x02,table,12);lcd_print(0x41,temp_dis,16); }//------------主程序----------- void main(){lcd_init();ReadTemperature();delay(20);while(1){ReadTemperature();display_temp();delay(20);}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
sbit dq=P3^4;//ds18b20
uchar n,flag=0;//n温度,flag标志
//微秒级延时
void delayus(int i)
{
while(i--)
;
}
//初始化
void initial()
{
dq=0;
delayus(70);
dq=1;
delayus(10);
while(1)
{
if(dq) break;
}
dq=1;
delayus(11);
}
//写ds18b20
initial();
write(0xcc);
write(0x44);
dq=1;
initial();
write(0xcc);
write(0xbe); Leabharlann temp1=read();
temp2=read(); if(temp2<8)
0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
n1=n/1000;n2=n%1000/100;n3=n%100/10;n4=n%10;
s1=s2=s3=s4=1;
switch(i++)
}
{
int j;
while(i--)
{
for(j=255;j>0;j--)
;
}
}
//LED显示
void led()
{
static int i=1,n1,n2,n3,n4;
int num[]={0x3f,0x06,0x5b,0x4f,
if(dq==1)temp=temp|0x80;
delayus(4);
}
return(temp);
}
//读ds18b20
void ds18b20()
{
int temp1,temp2;uchar m;
dq=1;
case 4:P2=num[n4];s4=0;break;
default:break;
}
if(i==5)i=1; delayms(2);
}
//主程序
void main()
{ int i;
n=1234;
while(1) {for(i=10;i>0;i--)led(); ds18b20();}
{
case 1:if(n1){P2=num[n1];s1=0;}break;
case 2:if(n1||n2){P2=num[n2];s2=0;}if(flag==1){P2=0x40;s2=0;}break;
case 3:if(n1||n2||n3){P2=num[n3];s3=0;}break;
dat=dat>>1;
}
}
//读取
int read()
{
int i,temp=0;
for(i=0;i<8;i++)
{
dq=0;
dq=1;
delayus(1);
temp=temp>>1;
第八章
第八章第八章
第八章 DS18B20 C程序:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
void write(int dat)
{
int i;
for(i=0;i<8;i++)
{ dq=0;
_nop_();_nop_();_nop_();_nop_();
dq=dat&0x01;
delayus(5);
dq=1;
{n=(temp1>>4)|(temp2<<4);flag=0;}
if(temp2>8)
{m=(temp1>>4)|(temp2<<4);n=~m;n++;flag=1;} //P1=m;n=P1;
}
//毫秒级延时
void delayms(int i)