ds18b20多路温度采集程序
- 格式:doc
- 大小:88.00 KB
- 文档页数:23
(1)先将数据线置高电平“1”。
(2)延时(该时间要求的不是很严格,但是尽可能的短一点)(3)数据线拉到低电平“0”。
(4)延时750微秒(该时间的时间范围可以从480到960微秒)。
(5)数据线拉到高电平“1”。
(6)延时等待(如果初始化成功则在15到60毫秒时间之内产生一个由DS18B20所返回的低电平“0”。
据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7)若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
(8)将数据线再次拉高到高电平“1”后结束。
(1)数据线先置低电平“0”。
(2)延时确定的时间为15微秒。
(3)按从低位到高位的顺序发送字节(一次只发送一位)。
(4)延时时间为45微秒。
(5)将数据线拉到高电平。
(6)重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7)最后将数据线拉高。
DS18B20的写操作时序图如图DS18B20的读操作(1)将数据线拉高“1”。
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时15微秒。
(5)将数据线拉高“1”。
(6)延时15微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时30微秒。
DS18B20的读操作时序图如图所示。
DS18B20的Protues仿真图源程序代码:#include "reg51.h"#include "intrins.h" // 此头文件中有空操作语句NOP 几个微秒的延时可以用NOP 语句,但本人没用NOP,直接用了I++来延时#define uchar unsigned char#define uint unsigned intuchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};sbit ds18b20_io=P2^0; //单片机与DS18B20的连接口sbit lcdrs=P2^6; //1602与单片机的接口sbit lcden=P2^7;unsigned char flag,tflag,i;unsigned int temper0,temper1,tvalue;float temperature;void delay() //6us 在KEIL中仿真出来的时间,这是调用DELAY所用的时间{i++;i++;}void Delay_50us(unsigned char t) //50us延时程序{unsigned char j;for(;t>0;t--)for(j=20;j>0;j--);}void delay1(uint z) //这个延时主要用在1602中,1602的读写时序没有//DS18B20那么严格{uint x,y;for(x=0;x<z;x++){ for(y=0;y<121;y++){;};};}uchar ds18b20_rst(){unsigned char j;ds18b20_io=1;i++; //1usds18b20_io=0;for(j=0;j<60;j++) //543us{delay();}ds18b20_io=1;for( j=0;j<7;j++) //65us{delay();}if(!ds18b20_io) //如果读到低电平,即复位成功{flag=1;}else flag=0; //如果没有读到低电平,则复位失败Delay_50us(9); //450usds18b20_io=1;return flag;}void ds18b20_writebyte(unsigned char byte){unsigned char j;for(j=0;j<8;j++){ds18b20_io=1;i++;ds18b20_io=0;delay(); //15usdelay();i++;i++;i++;ds18b20_io=byte&0x01;delay(); delay();delay();delay(); //48usdelay(); delay();delay();byte>>=1;ds18b20_io=1;delay();}ds18b20_io=1;}unsigned char ds18b20_readbyte() {unsigned char k,jj,i;jj=0;for(k=0;k<8;k++){ds18b20_io=1;i++; i++;ds18b20_io=0;delay(); //15usdelay(); i++;i++;i++;ds18b20_io=1;delay(); //15usdelay(); i++; i++;i++;if(ds18b20_io) //17us jj=(jj>>1)|0x80;elsejj>>=1;delay();delay(); delay(); //18us }return jj;}void write_com(uchar com){lcdrs=0;P1=com;delay1(5);lcden=1;delay1(5);lcden=0;}void write_data(uchar date){lcdrs=1;P1=date;delay1(5);lcden=1;delay1(5);lcden=0;}void init(){lcden=0;write_com(0x38);write_com(0x0C);write_com(0x06);write_com(0x01);}float read_temp()/*读取温度值并转换*/{if(ds18b20_rst()==1);{ds18b20_writebyte(0xcc);//*跳过读序列号*/ ds18b20_writebyte(0x44);//*启动温度转换*/ Delay_50us(30);}if(ds18b20_rst()==1);{ds18b20_writebyte(0xcc);//*跳过读序列号*/ds18b20_writebyte(0xbe);//*读取温度*/temper0 =ds18b20_readbyte();temper1 =ds18b20_readbyte();Delay_50us(20);}if(temper1&0xf8) //判断是正温度还是负温度{ //如果是高5位是0 为正温度,反则为负温度tflag=1;tvalue=(temper1<<8)|temper0;tvalue=((~tvalue)+1);temperature=tvalue*(0.0625);}else{tflag=0;tvalue=(temper1<<8)|temper0;temperature=tvalue*0.0625; //不用把tvalue进行转换,直接乘0.0625//的精度}return(temperature);}void write_xian(float date){uint bai,shi,ge,xiaozheng,xqian,xbai,xshi,xge;float k,m; //把浮点的DATA转换为整数,得到浮点娄的整数部分bai=(int)(date)/100; //把得到的整数部分拆开分别存在BAI SHI GE 中shi=((int)(date)%100)/10;ge=(int)(date)%10;if (bai!=0) //如果百不为0 则把整数部分全部显示{write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);}else if (shi!=0) //如果十不为0 则把十位和个位显示{write_data(0x30+shi);write_data(0x30+ge);}else write_data(0x30+ge);//如果百和十位都为0 ,则只显示个位数write_data(0x2e);k=date-(int)date; //取浮点娄的小数部分m=k*10000; //把得到的小数变为整数并显示xiaozheng=(int)m;xqian=(xiaozheng)/1000;xbai=((xiaozheng)%1000)/100;xshi=((xiaozheng)%100)/10;xge=(xiaozheng)%10;write_data(0x30+xqian);write_data(0x30+xbai);write_data(0x30+xshi);write_data(0x30+xge);}void main(){temperature=0.0;flag=0;tflag=0;tvalue=0;init();while(1){read_temp();if(tflag==0){write_xian(temperature); write_data(' '); write_data(' '); }if(tflag==1){write_data('-');write_xian(temperature); write_data(' '); write_data(' '); }write_com(0x80);}}。
18B20温度传感器温度计程序作者:周国磊1.实验任务本实验实现的是通过18B20温度传感器读回温度并在2位数码管上显示。
精度为一度,测温范围为0-99度。
2.实验目的学会使用单片机控制18B20此类单总线器件。
3.DS18B20原理及引脚介绍DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。
DS18B20产品的特点(1)、只要求一个端口即可实现通信。
(2)、在DS18B20中的每个器件上都有独一无二的序列号。
(3)、实际应用中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55。
C到+125。
C之间。
(5)、数字温度计的分辨率用户可以从9位到12位选择。
(6)、内部有温度上、下限告警设置。
TO-92封装的DS18B20的引脚排列见上图,其引脚功能描述见下:1.GND 地信号2.DQ 数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也可以向器件提供电源。
3.VDD 可选择的VDD引脚。
当工作于寄生电源时,此引脚必须接地。
4.实验原理图5.实验源程序TEMPER_L EQU 36HTEMPER_H EQU 35HTEMPER_NUM EQU 60Hjishu EQU 37HFLAG1 BIT 00HDQ BIT P3.5AAA:SETB P2.0CLR P2.1MOV SP,#70HLCALL GET_TEMPERLCALL TEMPER_COVloop4:mov r5,#20loop3:mov 38H,#0ffhLOOP2:mov A,TEMPER_NUMMOV B,#10;MOV B,R5DIV ABSETB P2.2CLR P2.3MOV DPTR,#TABLE1MOVC A,@A+DPTRMOV P0,ALCALL DELySETB P2.3CLR P2.2MOV A,BMOV DPTR,#TABLE2MOVC A,@A+DPTRMOV P0,ALCALL DELydjnz 38H,loop2djnz r5, loop3sjmp aaaNOP;------------------读出转换后的温度值GET_TEMPER:SETB DQ ; 定时入口BCD:LCALL INIT_1820JB FLAG1,S22LJMP BCD ; 若DS18B20不存在则返回S22:LCALL DELAY1 MOV A,#0CCH ; 跳过ROM匹配------0CCLCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820NOPLCALL DELAYLCALL DELAYCBA:LCALL INIT_1820JB FLAG1,ABCLJMP CBAABC:LCALL DELAY1MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_18200 ;READ_1820RET;------------------读DS18B20的程序,从DS18B20中读出一个字节的数据READ_1820:MOV R2,#8RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE1RET;-------------------写DS18B20的程序WRITE_1820:MOV R2,#8CLR CWR1:CLR DQMOV R3,#6DJNZ R3,$RRC AMOV DQ,CMOV R3,#23DJNZ R3,$SETB DQNOPDJNZ R2,WR1SETB DQRET;-------------------读DS18B20的程序,从DS18B20中读出两个字节的温度数据READ_18200:MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_H) RE00:MOV R2,#8RE01:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;-------------------将从DS18B20中读出的温度数据进行转换TEMPER_COV:MOV A,#0F0HANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值SWAP AMOV TEMPER_NUM,AMOV A,TEMPER_LJNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值INC TEMPER_NUMTEMPER_COV1:MOV A,TEMPER_HANL A,#07HSWAP AORL A,TEMPER_NUMMOV TEMPER_NUM,A ; 保存变换后的温度数据RET;-------------------将16进制的温度数据转换成压缩BCD码;-------------------DS18B20初始化程序INIT_1820:SETB DQNOPCLR DQMOV R0,#80HTSR1:DJNZ R0,TSR1 ; 延时SETB DQMOV R0,#25H ;96US-25HTSR2:DJNZ R0,TSR2JNB DQ,TSR3LJMP TSR4 ; 延时TSR3:SETB FLAG1 ; 置标志位,表示DS1820存在LJMP TSR5TSR4:CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP TSR7TSR5:MOV R0,#06BH ;200USTSR6:DJNZ R0,TSR6 ; 延时TSR7:SETB DQRET;------------------重新写DS18B20暂存存储器设定值RE_CONFIG:JB FLAG1,RE_CONFIG1 ; 若DS18B20存在,转RE_CONFIG1RETRE_CONFIG1:MOV A,#0CCH ; 发SKIP ROM命令LCALL WRITE_1820MOV A,#4EH ; 发写暂存存储器命令LCALL WRITE_1820MOV A,#00H ; TH(报警上限)中写入00HLCALL WRITE_1820MOV A,#00H ; TL(报警下限)中写入00HLCALL WRITE_1820MOV A,#7FH ; 选择12位温度分辨率LCALL WRITE_1820RET;------------------延时子程序DELAY:MOV R7,#00HMIN:DJNZ R7,YS500RETYS500:LCALL YS500USLJMP MINYS500US:MOV R6,#00HDJNZ R6,$RETDELAY1:MOV R7,#20HDJNZ R7,$RETdely: mov r3,#100djnz r3,$retTABLE1: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H TABLE2: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H。
本程序为ds18b20的多路温度采集程序,是我自己参考其他程序后改写而成,可显示4路正负温度值,并有上下限温度报警(声音、灯光报警)。
亲测,更改端口即可使用。
(主要器件:51单片机,ds18b20,lcd显示器)附有proteus仿真图,及序列号采集程序/****上限62度下限-20度****/#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit ds=P1^1;sbit rs=P1^4;sbit e=P1^6;sbit sp=P1^0;sbit d1=P1^2;sbit d2=P1^3;ucharlcdrom[4][8]={{0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0x8e} ,{0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9},{0x28,0x32,0xc5,0xb8,0x00,0x00,0x00,0xe0},{0x28,0x33,0xc5,0xb8,0x00,0x00,0x00,0xd7}};unsigned char code table0[]={"TEMPERARTURE:U "}; unsigned char code table1[]={"0123456789ABCDEF"};int f[4];int tvalue;float ftvalue;uint warnl=320;uint warnh=992;/****lcd程序****/void delayms(uint ms)//延时{uint i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);}void wrcom(uchar com)//写指令{delayms(1);rs=0;P3=com;delayms(1);e=1;delayms(1);e=0;}void wrdat(uchar dat)//写数据{rs=1;e=0;P3=dat;delayms(5);e=1;delayms(5);e=0;}void lcdinit()//初始化lcd {delayms(15);wrcom(0x38);delayms(5);wrcom(0x0c);delayms(5);wrcom(0x06);delayms(5);wrcom(0x01);delayms(5); }void display(uchar *p)//显示{while(*p!='\0'){wrdat(*p);p++;delayms(1);}}displayinit()//初始化显示{lcdinit();wrcom(0x80);display(table0);}/****ds18b20程序****/ void dsrst()//ds18b20复位{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit dsrd0()//读一位数据{uint i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return(dat);}uchar dsrd()//读1个字节数据{uchar i,j,dat;dat=0;for(i=8;i>0;i--){j=dsrd0();dat=(j<<7)|(dat>>1);}return(dat);}void dswr(uchar dat)//写数据{uint i;uchar j;bit testb;for(j=8;j>0;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++;}}}void tmstart()//初始化ds18b20{sp=1;d1=1;d2=1;dsrst();delayms(1);dswr(0xcc);dswr(0x44);}void read_dealtemp()//读取并处理温度{uchar i,j,t;uchar a,b;for(j=0;j<4;j++){dsrst();delayms(1);dswr(0x55);for(i=0;i<8;i++){dswr(lcdrom[j][i]);//发送64位序列号}dswr(0xbe);a=dsrd();b=dsrd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0){d1=1;tvalue=~tvalue+1;wrcom(0xc0);wrdat(0x2d);if(tvalue>warnl){d2=0;sp=0;}else{d2=1;sp=1;}}else{d2=1;wrcom(0xc0);wrdat(' ');if(tvalue>warnh){d1=0;sp=0;}else{d1=1;sp=1;}}if(j==0){wrcom(0x8e); wrdat('2');}if(j==1){wrcom(0x8e);wrdat('3');}if(j==2){wrcom(0x8e);wrdat('4');}if(j==3){wrcom(0x8e);wrdat('5');}ftvalue=tvalue*0.0625;tvalue=ftvalue*10+0.5;ftvalue=ftvalue+0.05;f[j]=tvalue;//温度扩大十倍,精确到一位小数tvalue=f[j];t=tvalue/1000;wrcom(0x80+0x41);wrdat(table1[t]);//显示百位t=tvalue%1000/100;wrdat(table1[t]);//显示十位t=tvalue%100/10;wrdat(table1[t]);//显示个位wrdat(0x2e); //显示小数点儿t=tvalue%10/1;wrdat(table1[t]);//显示小数位delayms(5000);}}/****主函数****/void main(){d1=1;d2=1;sp=1;displayinit();//初始化显示while(1){tmstart();//初始化read_dealtemp();//读取温度}}/****序列号读取程序****/#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P1^1; //温度传感器信号线sbit rs = P1^4; //LCD数据/命令选择端(H/L)位声明sbit lcden = P1^6; //LCD使能信号端位声明void delay(uint z); //延时函数void DS18B20_Reset(void); //DQ18B20复位,初始化函数bit DS18B20_Readbit(void); //读1位数据函数uchar DS18B20_ReadByte(void); //读1个字节数据函数void DS18B20_WriteByte(uchar dat); //向DQ18B20写一个字节数据函数void LCD_WriteCom(uchar com); //1602液晶命令写入函数void LCD_WriteData(uchar dat); //1602液晶数据写入函数void LCD_Init();//LCD初始化函数void Display18B20Rom(char Rom); //显示18B20序列号函数/**********************************************//* 主函数*//**********************************************/void main(){ uchar a,b,c,d,e,f,g,h;LCD_Init();DS18B20_Reset();delay(1);DS18B20_WriteByte(0x33);delay(1);a = DS18B20_ReadByte();b = DS18B20_ReadByte();c = DS18B20_ReadByte();d = DS18B20_ReadByte();e = DS18B20_ReadByte();f = DS18B20_ReadByte();g = DS18B20_ReadByte();h = DS18B20_ReadByte();LCD_WriteCom(0x80+0x40);Display18B20Rom(h);Display18B20Rom(g);Display18B20Rom(f);Display18B20Rom(e);Display18B20Rom(d);Display18B20Rom(c);Display18B20Rom(b);Display18B20Rom(a);while(1);}/***************************************************//* 延时函数:void delay() *//* 功能:延时函数*//***************************************************/void delay(uint z)//延时函数{uint x,y;for( x = z; x > 0; x-- )for( y = 110; y > 0; y-- );}/***************************************************//* DS18B20函数:void DS18B20_Reset() *//* 功能:复位18B20 *//***************************************************/void DS18B20_Reset(void)//DQ18B20复位,初始化函数{uint i;DQ = 0;i = 103;while( i > 0 ) i--;DQ = 1;i = 4;while( i > 0 ) i--;}/***************************************************//* DS18B20函数:void DS18B20_Readbit() *//* 功能:读1个字节数据函数*//***************************************************/bit DS18B20_Readbit(void) //读1位数据函数{uint i;bit dat;DQ = 0;i++; //i++起延时作用DQ = 1;i++;i++;dat = DQ;i = 8;while( i > 0 )i--;return( dat );}/***************************************************//* DS18B20函数:void DS18B20_ReadByte() *//* 功能:读1个字节数据函数*//***************************************************/uchar DS18B20_ReadByte(void) //读1个字节数据函数{uchar i,j,dat;dat = 0;for( i = 1; i <= 8; i++ ){j = DS18B20_Readbit();dat = ( j << 7 ) | ( dat >> 1 );}return(dat);}/***************************************************//* DS18B20函数:void DS18B20_WriteByte() *//* 功能:向DQ18B20写一个字节数据函数*//***************************************************/void DS18B20_WriteByte(uchar dat) //向DQ18B20写一个字节数据函数{uint i;uchar j;bit testb;for( j=1; j<=8; j++){testb = dat&0x01;dat= dat>>1;if(testb) //写1{DQ = 0;i++;i++;DQ = 1;i = 8;while(i>0)i--; }else{DQ = 0; //写0 i = 8;while(i>0)i--; DQ = 1;i++;i++;}}}/* LCD函数:void LCD_WriteCom() *//* 功能:向LCD写入命令*//***********************************************/void LCD_WriteCom(uchar com){rs = 0;P3= com;delay(5);lcden = 0;delay(5);lcden = 1;delay(5);lcden = 0;}/***********************************************//* LCD函数:void LCD_WriteData(uchar dat) *//* 功能:向LCD写入数据*/void LCD_WriteData(uchar dat){rs = 1; //选择LCD为写入数据状态lcden = 0;P3= dat; //将待写入数据放到总线上delay(5);lcden = 1; //给LCD使能端一个脉冲delay(5); //信号将之前放到总线上lcden = 0; //的数据写入LCDdelay(5);}/***********************************************//* LCD函数:void LCD_Init() *//* 功能:初始化LCD,设定LCD的初始状态*/void LCD_Init(){LCD_WriteCom(0x38); //LCD显示模式设定delay(15);LCD_WriteCom(0x08); //关闭LCD显示delay(3);LCD_WriteCom(0x01); //LCD显示清屏delay(3);LCD_WriteCom(0x06); //设定光标地址指针为自动加1delay(3);LCD_WriteCom(0x0c); //打开LCD显示,但不显示光标}/**********************************************//* *//* 显示18B20序列号*//* *//**********************************************/void Display18B20Rom(char Rom){uchar h,l;l = Rom & 0x0f; //取低4位h = Rom & 0xf0; //取高4位h >>= 4;if( ( h >= 0x00 )&&( h <= 0x09 ) )LCD_WriteData(h+0x30);//取ASCII码elseLCD_WriteData(h+0x37);//取ASCII码if( ( l >= 0x00 )&&( l <= 0x09 ) )LCD_WriteData(l+0x30);//取ASCII码elseLCD_WriteData(l+0x37);//取ASCII码}。
这个是我自己制作的51单片机板上的DS18B20温度采集和显示程序,你如果有现成的51板稍微修改一下可以用,在我这里是可以用没问题的。
环境是KEIL。
我这个51板也完全符合你的要求。
#pragma db code#include<AT89X52.H>//#include "reg52.h"#include "INTRINS.H"// 此实验是使用18B20检测温度,然后在数码管上显示#define uchar unsigned char#define uint unsigned int#define BUSY1 (DQ1==0)sbit LED_0=P1^0;sbit LED_1=P1^1;sbit LED_2=P1^2;sbit LED_3=P1^3;sbit DQ1=P1^6;//void delay(uint x);void display(unsigned char d1,unsigned char d2,unsigned char d3,unsigned char d4);void ds_reset_1(void);void wr_ds18_1(char dat);void time_delay(unsigned char time);int get_temp_1(void);void delay(unsigned int x);void read_ROM(void);int get_temp_d(void);/*=====0-9=====A-G=====*/uchar a[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0x86,0x8e,0x82}; unsigned char ResultSignal;int ResultTemperatureLH,ResultT emperatureLL,ResultTemperatureH; unsigned char ROM[8];unsigned char idata TMP;unsigned char idata TMP_d;unsigned char f;unsigned char rd_ds18_1();unsigned int TemH,TemL;void main(){unsigned int TemH,TemL,k=0;ds_reset_1();ds_reset_1(); //resetwr_ds18_1(0xcc); //skip rom_nop_();wr_ds18_1(0x7f);ds_reset_1();wr_ds18_1(0xcc);_nop_();wr_ds18_1(0x44);for(k=0;k<11000;k++)time_delay(255);ds_reset_1();while(1){wr_ds18_1(0xcc);wr_ds18_1(0xbe);TemH=get_temp_1();TemL=get_temp_d();TemH&=0x00ff;TemL&=0x00ff;display((TemH/10),(T emH%10),(TemL/10),(TemL%10));}}/***************延时程序,单位us,大于10us*************/ void time_delay(unsigned char time){time=time-10;time=time/6;while(time!=0)time--;}/*****************************************************//* reset ds18b20 */ /*****************************************************/void ds_reset_1(void){unsigned char idata count=0;DQ1=0;time_delay(240);time_delay(240);DQ1=1;return;}void check_pre_1(void){while(DQ1);while(~DQ1);time_delay(30);}void read_ROM(void){int n;check_pre_1();wr_ds18_1(0x33);for(n=0;n<8;n++){ROM[n]=rd_ds18_1();}}/*****************************************************//* Read a bit from 1820 位读取*/ /*****************************************************/bit tmrbit_1(void){idata char i=0;bit dat;DQ1=0;_nop_();DQ1=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();dat = DQ1;time_delay(50);return dat;}/*****************************************************//* read a bety from ds18b20 字节读取*/ /*****************************************************/unsigned char rd_ds18_1(){unsigned char idata i,j,dat=0;for(i=1;i<=8;i++){j=tmrbit_1();dat=(j<<(i-1))|dat;}return dat;}/*****************************************************//* write a bety from ds18b20 写字节*/ /****************************************************/void wr_ds18_1(char dat){signed char idata i=0;unsigned char idata j;bit testb;for(j=1;j<=8;j++){testb=dat & 0x01;dat = dat>>1;if(testb){DQ1=0;_nop_();_nop_();DQ1=1;time_delay(60);}else{DQ1=0;time_delay(50);DQ1=1;_nop_();_nop_();}}}int get_temp_1(void){unsigned char idata a=0,b=0; unsigned char idata i;EA=0;ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0x44);while(BUSY1);ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0xbe);a=rd_ds18_1();b=rd_ds18_1();i=b; /*若b为1则为负温*/ i=(i>>4);if(i==0){f=0;TMP=((a>>4)|(b<<4));a=(a&0x0f);if (a>8){TMP=(TMP+1);}}else{f=1;a=a>>4;b=b<<4;TMP=(a|b);TMP=~TMP;TMP=(TMP+1);}EA=1;return(TMP);}int get_temp_d(void){unsigned char idata a=0,b=0; unsigned char idata i,m;EA=0;ds_reset_1();//复位check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0x44);while(BUSY1);ds_reset_1();check_pre_1();wr_ds18_1(0xcc);wr_ds18_1(0xbe);a=rd_ds18_1();b=rd_ds18_1();i=b; /*若b为1则为负温*/ i=(i>>4);if(i==0){f=0;TMP=((a>>4)|(b<<4)); a=(a&0x0f);TMP_d=a;}else{f=1;a=~a;a=(a+1);b=~b;b=(b+1);m=a;a=a>>4;b=b<<4;TMP=(a|b);m=(m&0x0f);TMP_d=m;}EA=1;return(TMP_d);}void delay(unsigned int x) {unsigned int i;for(i=0;i<x;i++);}void display(unsigned char d1,unsigned char d2,unsigned char d3,unsigned char d4) {P2=a[d1];LED_0=0;delay(100);LED_0=1;P2=a[d2];LED_1=0;delay(100);LED_1=1;P2=a[d3];LED_2=0;delay(100);LED_2=1;P2=a[d4];LED_3=0;delay(100);LED_3=1;}。
4路DS18B20温度显示汇编程序(可设置上下限和分路查看)作者蔡雄略;操作说明:;------------------------------------------;功能说明:模式选择键按下后,选择循环显示、分路查看,上限设置,下限设置功能;每按一次模式键,对应的模式指示灯会亮起。
;循环显示模式时候,每秒显示一下各路温度状况;分路查看时界面冻结每按一次+或-键进行各路切换;上限设置时每按一次+或-键对各路上限报警进行设置;下限设置时每按一次+或-键对各路下限报警进行设置;------------------------------------------仿真效果图:程序如下:;------------------------------------------;功能说明:模式选择键按下后,选择循环显示、分路查看,上限设置,下限设置功能;循环显示模式时候,每秒显示一下各路温度状况;分路查看时界面冻结每按一次+或-键进行各路切换;上限设置时每按一次+或-键对各路上限报警进行设置;下限设置时每按一次+或-键对各路下限报警进行设置;------------------------------------------;主程序S0EQU30H;50ms计数寄存器MODE_CONT EQU S0+1;模式计数器DS18B20_CONT EQU S0+2HI_TMP_SET_IN EQU S0+3;进水口LOW_TMP_SET_IN EQU S0+4HI_TMP_SET_OUT EQU S0+5;出水口LOW_TMP_SET_OUT EQU S0+6HI_TMP_SET_FRONT EQU S0+7;前后点HI_TMP_SET_BACK EQU S0+8TMP_IN EQU S0+12TMP_OUT EQU S0+13TMP_FRONT EQU S0+14TMP_BACK EQU S0+15DISPLAY_DATA EQU P0;LED数据口KEY_PORT EQU P3;按键口COM_TEMPERL_L BIT P2.7COM_TEMPERL_H BIT P2.6COM_TEMPERH_L BIT P2.5COM_TEMPERH_H BIT P2.4COM_DS18B20_NUM BIT P2.2LED_LOW_SET BIT P3.0LED_HI_SET BIT P3.1LED_CHECK BIT P3.2LED_NORMAL BIT P3.3IN_LED_ALARM_HI BIT P1.1;ININ_LED_ALARM_LOW BIT P1.3OUT_LED_ALARM_HI BIT P1.0;INOUT_LED_ALARM_LOW BIT P1.2FRONT_LED_ALARM_HI BIT P2.0BACK_LED_ALARM_HI BIT P2.1FLAG1BIT20H.5;DS18B20存在标志位DQ1BIT P1.7DQ2BIT P1.6DQ3BIT P1.5DQ4BIT P1.4TEMPER_L EQU28HTEMPER_H EQU27H;------------------------------------------ORG0000HAJMP STARTORG000BH;T0入口LJMP T_INT;------------------------------------------;START初始化;------------------------------------------ORG100HSTART:MOV TEMPER_L,#00HMOV TEMPER_H,#00HMOV MODE_CONT,#00HMOV DS18B20_CONT,#00HMOV HI_TMP_SET_IN,#100;进水口MOV LOW_TMP_SET_IN,#10MOV HI_TMP_SET_OUT,#100;出水口MOV LOW_TMP_SET_OUT,#10MOV HI_TMP_SET_FRONT,#100MOV HI_TMP_SET_BACK,#100CLR TMP_INCLR TMP_OUTCLR TMP_FRONTCLR TMP_BACKMOV S0,#00HMOV TMOD,#01HMOV TH0,#3CH;定时器0,模式1,定时时常50mS MOV TL0,#0B0HMOV IE,#82HMOV KEY_PORT,#0F8HSETB TR0;运行T0LCALL INIT_18B20;------------------------------------------;主函数;------------------------------------------MAIN:LCALL KEYLCALL GET_TEMPER;获取各路温度LCALL DISPLAY;调用显示程序LJMP MAIN;------------------------------------------;T0中服程序,实现1秒一次切换,同时1秒一次的比较各路温度是否超标;------------------------------------------;T0中服程序T_INT:PUSH ACCPUSH PSWMOV TH0,#3CH;定时器0,模式1,定时时常50mSMOV TL0,#0B0H;------------------------------NEXT:INC S0MOV A,S0CJNE A,#14H,ZDMOV S0,#00H;到1S后进行切换INC DS18B20_CONTMOV A,DS18B20_CONTCJNE A,#04H,ZDMOV DS18B20_CONT,#00HLCALL CHECK1;判断各路温度是否超标ZD:POP PSWPOP ACCRETI;-------------------------------------------;ALARM_CHECK;判断各路温度是否超标;-------------------------------------------CHECK1:MOV R0,TMP_INMOV R1,HI_TMP_SET_INLCALL ALARM_CALJZ ALARM_HI_NORMALSETB IN_LED_ALARM_HIJMP CHECK2ALARM_HI_NORMAL:CLR IN_LED_ALARM_HICHECK2:MOV R0,TMP_INMOV R1,LOW_TMP_SET_INLCALL ALARM_CALJNZ CCSETB IN_LED_ALARM_LOWJMP DDCC:CLR IN_LED_ALARM_LOW DD:MOV R0,TMP_OUTMOV R1,HI_TMP_SET_OUTLCALL ALARM_CALJZ EESETB OUT_LED_ALARM_HIJMP DDDEE:CLR OUT_LED_ALARM_HI DDD:MOV R0,TMP_OUTMOV R1,LOW_TMP_SET_OUTLCALL ALARM_CALJNZ FFSETB OUT_LED_ALARM_LOWJMP GGFF:CLR OUT_LED_ALARM_LOW GG:MOV R0,TMP_OUTMOV R1,HI_TMP_SET_FRONTLCALL ALARM_CALJZ HHSETB FRONT_LED_ALARM_HIJMP IIHH:CLR FRONT_LED_ALARM_HI II:MOV R0,TMP_OUTMOV R1,HI_TMP_SET_BACKLCALL ALARM_CALJZ JJSETB BACK_LED_ALARM_HIJMP ALARM_RET1JJ:CLR BACK_LED_ALARM_HI ALARM_RET1:RET;------------------------------------------;R0=R1A=2,R0<R1A=0,R0>R1A=1 ;比较大小;------------------------------------------ALARM_CAL:;R0,R1MOV A,R0SUBB A,R1JC SMALLMOV A,#01HJMP COMP_RETSMALL:MOV A,#0HCOMP_RET:RET;------------------------------------------;显示子程序;时分秒显示;------------------------------------------DISPLAY:MOV DPTR,#TABMOV A,TEMPER_LMOV B,#10DIV ABMOV R4,AMOV R5,BMOV A,R5;温度低位MOVC A,@A+DPTR;显示输出MOV DISPLAY_DATA,ASETB COM_TEMPERL_LLCALL DELAY5MSCLR COM_TEMPERL_LMOV A,R4MOVC A,@A+DPTR;显示输出MOV DISPLAY_DATA,ASETB COM_TEMPERL_HLCALL DELAY5MSCLR COM_TEMPERL_HMOV A,TEMPER_H;温度高位MOV B,#10DIV ABMOV R4,AMOV R5,BMOV A,R5MOVC A,@A+DPTR;显示输出ANL A,#7FH;MOV DISPLAY_DATA,ASETB COM_TEMPERH_LLCALL DELAY5MSCLR COM_TEMPERH_LMOV A,R4MOVC A,@A+DPTRMOV DISPLAY_DATA,ASETB COM_TEMPERH_HLCALL DELAY5MSCLR COM_TEMPERH_HMOV A,DS18B20_CONTINC AMOVC A,@A+DPTR;显示输出MOV DISPLAY_DATA,ASETB COM_DS18B20_NUMLCALL DELAY5MSCLR COM_DS18B20_NUMRET;------------------------------------------;键盘扫描程序;------------------------------------------KEY:;KEY_PORT,#0FFHMOV A,KEY_PORTCPL AANL A,#0F0HJZ RET1LCALL DELAY10MSMOV A,KEY_PORTCPL AANL A,#0F0HJZ RET1JB ACC.7,MODE_CHANGEJB ACC.6,MODE_DEC_JJB ACC.5,MODE_ADD_JJB ACC.4,NUM_ADD_JRET1:RETMODE_DEC_J:LJMP MODE_DECRETMODE_ADD_J:LJMP MODE_ADDRETNUM_ADD_J:LJMP NUM_ADDRETMODE_CHANGE:INC MODE_CONTMOV A,MODE_CONTCJNE A,#04H,MODE_RETMOV MODE_CONT,#00HSETB TR0MODE_RET:LCALL MODE_DEL WAIT:LCALL DISPLAYJNB P3.7,WAITRETMODE_DEL:MOV A,MODE_CONTCJNE A,#00H,MOD_1CLR LED_LOW_SETCLR LED_HI_SETCLR LED_CHECKSETB LED_NORMALRETMOD_1:CJNE A,#01H,MOD_2CLR LED_LOW_SETCLR LED_HI_SETSETB LED_CHECKCLR LED_NORMALCLR TR0RETMOD_2:CJNE A,#02H,MOD_3CLR LED_LOW_SETSETB LED_HI_SETCLR LED_CHECKCLR LED_NORMALCLR TR0RETMOD_3:SETB LED_LOW_SETCLR LED_HI_SETCLR LED_CHECKCLR LED_NORMALCLR TR0RET;-----------------------------------;----------------------------------MODE_DEC:;模式0MOV A,MODE_CONTCJNE A,#00H,MODE_DEC_1 WAIT1:LCALL DISPLAYJNB P3.6,WAIT1RETMODE_DEC_1:;模式1CJNE A,#01H,MODE_DEC_2MOV A,DS18B20_CONTCJNE A,#00H,MODE_DEC_11MOV DS18B20_CONT,#03H WAIT2:LCALL DISPLAYJNB P3.6,WAIT2RETMODE_DEC_11:DEC DS18B20_CONTWAIT3:LCALL DISPLAYJNB P3.6,WAIT3RETMODE_DEC_2:;模式2IN口CJNE A,#02H,MODE_DEC_3MOV A,DS18B20_CONTCJNE A,#00H,MODE_DEC_21DEC HI_TMP_SET_INMOV A,HI_TMP_SET_OUTJNZ MODE_DEC_DELMOV HI_TMP_SET_IN,#64H MODE_DEC_DEL:MOV TEMPER_H,HI_TMP_SET_INMOV TEMPER_L,#00HJMP MODE_DEC_RETMODE_DEC_21:;OUT口MOV A,DS18B20_CONTCJNE A,#01H,MODE_DEC_22DEC HI_TMP_SET_OUTMOV A,HI_TMP_SET_OUTJNZ MODE_DEC_RET1MOV HI_TMP_SET_OUT,#64H MODE_DEC_RET1:MOV TEMPER_H,HI_TMP_SET_OUTMOV TEMPER_L,#00HJMP MODE_DEC_RETMODE_DEC_22:;前点CJNE A,#02H,MODE_DEC_23DEC HI_TMP_SET_FRONTMOV A,HI_TMP_SET_FRONTJNZ MODE_DEC_RET2MOV HI_TMP_SET_FRONT,#64H MODE_DEC_RET2:MOV TEMPER_H,HI_TMP_SET_FRONT MOV TEMPER_L,#00HJMP MODE_DEC_RETMODE_DEC_23:;后点DEC HI_TMP_SET_BACKMOV A,HI_TMP_SET_BACKJNZ MODE_DEC_XMOV HI_TMP_SET_BACK,#64H MODE_DEC_X:MOV TEMPER_H,HI_TMP_SET_BACK MOV TEMPER_L,#00HMODE_DEC_RET:WAIT4:LCALL DISPLAYJNB P3.6,WAIT4RET;------------------------------------;-----------------------------------MODE_DEC_3:;模式3MOV A,DS18B20_CONTCJNE A,#00H,MODE_DEC_21BDEC LOW_TMP_SET_INMOV A,LOW_TMP_SET_INJNZ MODE_DEC_DELBMOV LOW_TMP_SET_IN,#64H MODE_DEC_DELB:MOV TEMPER_H,LOW_TMP_SET_IN MOV TEMPER_L,#00HJMP MODE_DEC_RETBMODE_DEC_21B:;OUT口MOV A,DS18B20_CONTCJNE A,#01H,MODE_DEC_RETBDEC LOW_TMP_SET_OUTMOV A,LOW_TMP_SET_OUTJNZ MODE_DEC_RET1BMOV LOW_TMP_SET_OUT,#64H MODE_DEC_RET1B:MOV TEMPER_H,LOW_TMP_SET_OUT MOV TEMPER_L,#00HMODE_DEC_RETB:WAIT5:LCALL DISPLAYJNB P3.6,WAIT5RET;-----------------------------------;----------------------------------MODE_ADD:MOV A,MODE_CONTCJNE A,#00H,MODE_ADD_1WAIT6:LCALL DISPLAYJNB P3.5,WAIT6RETMODE_ADD_1:;模式1CJNE A,#01H,MODE_ADD_2MOV A,DS18B20_CONTCJNE A,#03H,MODE_ADD_11MOV DS18B20_CONT,#00HWAIT7:LCALL DISPLAYJNB P3.5,WAIT7RETMODE_ADD_11:INC DS18B20_CONTWAIT8:LCALL DISPLAYJNB P3.5,WAIT8RETMODE_ADD_2:;模式2IN口CJNE A,#02H,MODE_ADD_3MOV A,DS18B20_CONTCJNE A,#00H,MODE_ADD_21INC HI_TMP_SET_INMOV A,HI_TMP_SET_OUTCJNE A,#64H,MODE_ADD_DELMOV HI_TMP_SET_IN,#00H MODE_ADD_DEL:MOV TEMPER_H,HI_TMP_SET_IN MOV TEMPER_L,#00HJMP MODE_ADD_RETMODE_ADD_21:;OUT口MOV A,DS18B20_CONTCJNE A,#01H,MODE_ADD_22INC HI_TMP_SET_OUTMOV A,HI_TMP_SET_OUTCJNE A,#64H,MODE_ADD_RET1MOV HI_TMP_SET_OUT,#00H MODE_ADD_RET1:MOV TEMPER_H,HI_TMP_SET_OUTMOV TEMPER_L,#00HJMP MODE_ADD_RETMODE_ADD_22:;前点CJNE A,#02H,MODE_ADD_23INC HI_TMP_SET_FRONTMOV A,HI_TMP_SET_FRONTCJNE A,#64H,MODE_ADD_RET2MOV HI_TMP_SET_FRONT,#00H MODE_ADD_RET2:MOV TEMPER_H,HI_TMP_SET_FRONT MOV TEMPER_L,#00HJMP MODE_ADD_RETMODE_ADD_23:;后点INC HI_TMP_SET_BACKMOV A,HI_TMP_SET_BACKCJNE A,#64H,MODE_ADD_XMOV HI_TMP_SET_BACK,#00HMODE_ADD_X:MOV TEMPER_H,HI_TMP_SET_BACKMOV TEMPER_L,#00HMODE_ADD_RET:WAIT9:LCALL DISPLAYJNB P3.5,WAIT9RET;------------------------------------;-----------------------------------MODE_ADD_3:;模式3MOV A,DS18B20_CONTCJNE A,#00H,MODE_ADD_21BINC LOW_TMP_SET_INMOV A,LOW_TMP_SET_INCJNE A,#64H,MODE_ADD_DELBMOV LOW_TMP_SET_IN,#00H MODE_ADD_DELB:MOV TEMPER_H,LOW_TMP_SET_IN MOV TEMPER_L,#00HJMP MODE_ADD_RETBMODE_ADD_21B:;OUT口MOV A,DS18B20_CONTCJNE A,#01H,MODE_ADD_RETBINC LOW_TMP_SET_OUTMOV A,LOW_TMP_SET_OUTCJNE A,#64H,MODE_ADD_RET1BMOV LOW_TMP_SET_OUT,#64H MODE_ADD_RET1B:MOV TEMPER_H,LOW_TMP_SET_OUT MOV TEMPER_L,#00HMODE_ADD_RETB:WAIT71:LCALL DISPLAYJNB P3.5,WAIT71RET;----------------------------------;----------------------------------NUM_ADD:INC DS18B20_CONTMOV A,DS18B20_CONTCJNE A,#04H,NUM_ADD_RETMOV DS18B20_CONT,#00HNUM_ADD_RET:WAIT81:LCALL DISPLAYJNB P3.5,WAIT81RET;--------------------------------DELAY;延时程序;----------------------------------DELAY5MS:MOV R1,#2;5mS延时#5D1:MOV R2,#248D2:DJNZ R2,D2DJNZ R1,D1RET;------------------------------------------10MS DELAY DELAY10MS:MOV R3,#25;10mS延时D4:MOV R4,#200D3:DJNZ R4,D3DJNZ R3,D4RET;**********DS18B20复位程序***************** INIT_18B20:SETB DQ1SETB DQ2SETB DQ3SETB DQ4NOPNOPNOPNOPCLR DQ1CLR DQ2CLR DQ3CLR DQ4MOV R0,#0FBHTSR1:DJNZ R0,TSR1;延时SETB DQ1SETB DQ2SETB DQ3SETB DQ4MOV R0,#25HTSR2:JNB DQ1,TSR3JNB DQ2,TSR3JNB DQ3,TSR3JNB DQ4,TSR3DJNZ R0,TSR2TSR3:SETB FLAG1;置标志位,表明DS18B20存在AJMP TSR5TSR4:CLR FLAG1LJMP TSR7TSR5:MOV R0,#06BHTSR6:DJNZ R0,TSR6TSR7:SETB DQ1;表明不存在RET;********************设定DS18B20暂存器设定值************** RE_CONFIG:JB FLAG1,RE_CONFIG1RETRE_CONFIG1:MOV A,#0CCH;放跳过ROM命令LCALL WRITE_18B20MOV A,#4EHLCALL WRITE_18B20;写暂存器命令MOV A,#00H;报警上限中写入00HLCALL WRITE_18B20MOV A,#00H;报警下限中写入00HLCALL WRITE_18B20MOV A,#7FH;选择12位温度分辨率LCALL WRITE_18B20RET;*****************读转换后的温度值**************** GET_TEMPER:MOV A,MODE_CONTJZ GET_NEXT;只有模式零才GETCJNE A,#02H,AARETAA:CJNE A,#03H,GET_NEXTRETGET_NEXT:SETB DQ1SETB DQ2SETB DQ3SETB DQ4LCALL INIT_18B20JB FLAG1,TSS2RET;若不存在则返回TSS2:MOV A,#0CCH;跳过ROMLCALL WRITE_18B20MOV A,#44H;发出温度转换命令LCALL WRITE_18B20LCALL INIT_18B20MOV A,#0CCH;跳过ROMLCALL WRITE_18B20MOV A,#0BEH;发出读温度换命令LCALL WRITE_18B20MOV A,DS18B20_CONTCJNE A,#00H,READ_1LCALL READ2_18B20LCALL CHANGE1MOV TMP_IN,TEMPER_HRETREAD_1:MOV A,DS18B20_CONTCJNE A,#01H,READ_2LCALL READ2_18B20_2LCALL CHANGE1MOV TMP_OUT,TEMPER_HRETREAD_2:MOV A,DS18B20_CONTCJNE A,#02H,READ_3LCALL READ2_18B20_3LCALL CHANGE1MOV TMP_FRONT,TEMPER_HRETREAD_3:LCALL READ2_18B20_4;读两个字节的温度LCALL CHANGE1MOV TMP_BACK,TEMPER_HRET;**************************************;***************写DS18B20程序************ WRITE_18B20:MOV R2,#8CLR CWR1:CLR DQ1CLR DQ2CLR DQ3CLR DQ4MOV R3,#6DJNZ R3,$RRC AMOV DQ1,CMOV DQ2,CMOV DQ3,CMOV DQ4,CMOV R3,#23DJNZ R3,$SETB DQ1SETB DQ2SETB DQ3SETB DQ4NOPDJNZ R2,WR1SETB DQ1SETB DQ2SETB DQ3SETB DQ4RET;***********读18B20程序,读出两个字节的温度*********READ2_18B20:MOV R4,#2;低位存在29H,高位存在TEMPER_H MOV R1,#TEMPER_LRE00:MOV R2,#8RE01:CLR CSETB CNOPNOPCLR DQ1NOPNOPSETB DQ1MOV R3,#7DJNZ R3,$MOV C,DQ1MOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV@R1,ADEC R1DJNZ R4,RE00RET;***********读18B20_2程序,读出两个字节的温度********* READ2_18B20_2:MOV R4,#2;低位存在29H,高位存在TEMPER_H MOV R1,#TEMPER_LRE001:MOV R2,#8RE012:CLR CSETB CNOPCLR DQ2NOPNOPNOPSETB DQ2MOV R3,#7DJNZ R3,$MOV C,DQ2MOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE012MOV@R1,ADEC R1DJNZ R4,RE001RET;***********读18B20_3程序,读出两个字节的温度********* READ2_18B20_3:MOV R4,#2;低位存在29H,高位存在TEMPER_H MOV R1,#TEMPER_LRE002:MOV R2,#8RE013:CLR CSETB CNOPNOPCLR DQ3NOPNOPNOPSETB DQ3MOV R3,#7DJNZ R3,$MOV C,DQ3MOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE013MOV@R1,ADEC R1DJNZ R4,RE002RET;***********读18B20_3程序,读出两个字节的温度********* READ2_18B20_4:MOV R4,#2;低位存在29H,高位存在TEMPER_H MOV R1,#TEMPER_LRE003:MOV R2,#8RE014:CLR CSETB CNOPNOPCLR DQ4NOPNOPNOPSETB DQ4MOV R3,#7DJNZ R3,$MOV C,DQ4MOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE014MOV@R1,ADEC R1DJNZ R4,RE003RET;************读出的温度进行数据转换**************CHANGE1:MOV A,MODE_CONTJZ CHANGE1_NEXT;只有模式零和1才GETCJNE A,#02H,BBRETBB:CJNE A,#03H,CHANGE1_NEXTRETCHANGE1_NEXT:MOV A,TEMPER_LANL A,#0FHMOV B,#6HMUL ABMOV R0,AMOV A,TEMPER_LMOV C,TEMPER_H.0;将TEMPER_H中的最低位移入C RRC AMOV C,TEMPER_H.1RRC AMOV C,TEMPER_H.2RRC AMOV C,TEMPER_H.3RRC AMOV TEMPER_H,AMOV TEMPER_L,R0RET;***********************************D1MS:MOV R7,#80;1MS延时(按12MHZ算)DJNZ R7,$RET;*************************TAB:DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90HEND;DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H,0H;共阴极LED;END。
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测温程序(数码显示)*;************************************************************************** ;*接线方法: *;* 1、用一8P的数据线,一头插在J1,另一头插在J5,接通数码管的段选*;* 2、用一8P的数据线,一头插在J4,另一头插在J6,接通数码管的位选*;* 3、将DS18B20插在主机上的测温部份 *;* 4、用一根单根的数据线,一头插在DS18B20所在数据插针,另一头插到P2.7 * ;**************************************************************************TEMPER_L EQU 36H ;从DS18B20中读回高位,低位暂存区TEMPER_H EQU 35H ;TEMPER_NUM EQU 60H;温度值存储TEMPER_GE EQU 61HTEMPER_SHI EQU 62HTEMPER_SAVE EQU 63HFLAG1 BIT 00HFLAG2 BIT 01HRS BIT p3.0;液晶控制接口RW BIT p3.1E BIT p3.2DQ BIT P2.7;单总线口ORG 0000HA JMP MAINORG 0030HMAIN: MOV SP,#70HLCALL GET_TEMPERLCALL TEMPER_COVLCALL DISPLAYLJMP MAINNOP;**************************************************;读出转换后的温度值;**************************************************GET_TEMPER:SETB DQ ; 定时入口BCD: LCALL INIT_1820JB FLAG1,S22LJMP BCD ;若DS18B20不存在则返回S22: LCALL DELAY1MO V A,#0CCH ; 跳过ROM匹配------0CC命令LCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820LCALL DELAYCBA CALL INIT_1820JB FLAG1,ABCLJMP CBAABC CALL DELA Y1MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_18200 ;READ_1820RET;************************************************************** ;读DS18B20的程序,从DS18B20中读出一个字节的数据;************************************************************** READ_1820:MOV R2,#8RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE1RET;******************************************************;写DS18B20的程序;******************************************************WRITE_1820:MOV R2,#8CLR CWR1:MOV R3,#6DJNZ R3,$RRC AMOV DQ,CMOV R3,#23DJNZ R3,$SETB DQNOPDJNZ R2,WR1SETB DQRET;****************************************************;读DS18B20的程序,从DS18B20中读出两个字节的温度数据;****************************************************READ_18200:MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_H) RE00:MOV R2,#8RE01:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;;****************************************************;将从DS18B20中读出的温度数据进行转换;;****************************************************TEMPER_COV:MOV A,#0F0HANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值SWAP AMOV TEMPER_NUM,A ;得到低四位MOV A,TEMPER_LJNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值INC TEMPER_NUMTEMPER_COV1:MOV A,TEMPER_HANL A,#07HSWAP AORL A,TEMPER_NUM ;得到高四位,再与低四位相或得到值MOV TEMPER_NUM,A ; 保存变换后的温度数据LCALL BIN_BCDRET;;**************************************************** ;将16进制的温度数据转换成压缩BCD码;;**************************************************** BIN_BCD:MOV A,TEMPER_NUMMOV B,#10DIV ABMOV TEMPER_SHI,AMOV TEMPER_GE,BMOV A,TEMPER_SAVECJNE A,TEMPER_GE,ZWFHRET:MOV TEMPER_SAVE,TEMPER_GERETZW:CALL LCDDISPAJMP FHRET;**************************************************** ;DS18B20初始化程序;;**************************************************** INIT_1820:SETB DQNOPCLR DQMOV R0,#250TSR1:DJNZ R0,TSR1 ; 延时520usSETB DQMOV R0,#25H ;96US-25HTSR2:DJNZ R0,TSR2JNB DQ,TSR3;如D0为低则复位成功,DS18B20存在LJMP TSR4 ; 延时TSR3:SETB FLAG1 ; 置标志位,表示DS1820存在LJMP TSR5TSR4:CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP TSR7TSR5:MOV R0,#06BH ;200USTSR6:DJNZ R0,TSR6 ; 延时TSR7:SETB DQ ;拉高总线RET;************************************************* ;数码显示程序;************************************************* Display:MOV DPTR,#disptabMOV A,TEMPER_GEMOVC A,@A+DPTRMOV P1,ACLR P2.2CALL DELAYCALL DELAYSETB P2.2MOV DPTR,#disptabMOV A,TEMPER_SHIMOVC A,@A+DPTRMOV P1,ACLR P2.3CALL DELAYCALL DELAYSETB P2.3RET;************************************************* ;液晶显示程序;*************************************************mov p0,#01h;清屏call enrwmov p0,#38h;设为8位,5*7字型两行 call enrwmov p0,#0Chcall enrwmov p0,#06hcall enrwmov p0,#80hcall enrwmov dptr,#yjtabcall rwrammov p0,#0C0hcall enrwmov dptr,#yjtab1call rwramW_TEM:mov p0,#0CChcall enrwMO V DPTR,#ASCIIMO V A,TEMPER_SHIMO VC A,@A+DPTRMO V P0,Asetb rsclr rwclr ecall delaysetb eMO V DPTR,#ASCIIMO V A,TEMPER_GEMO VC A,@A+DPTRMO V P0,Asetb rsclr rwclr ecall delaysetb eRE Tenrw:clr rsclr rwclr esetb eretrwram:mov r1,#00ha1: mov a,r1movc a,@a+dptrcall rwram2inc r1cjne a,#00h,a1retrwram2:mov p0,asetb rsclr rwclr ecall delaysetb eret;*************************************************;延时子程序;*************************************************DELAY:MOV R6,#250;延时500usDJNZ R6,$RETDELAY1:MOV R7,#20HDJNZ R7,$RETdisptab:db 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H;字形代码表 ;0 1 2 3 4 5 6 7 8 9yjtab: db 'HTTP// ',00hyjtab1:db 'CHENZHOU_TE:**`C',00hASCII: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39Hend。
ORG 0000HAJMP MAINORG 0030HMAIN: MOV R5,#0FFHMAIN1:MOV P0,#00H ;系统自检。
自高位向低位带小数点显示8扫描256次CLR P2.4LCALL DELAYSETB P2.4CLR P2.5LCALL DELAYSETB P2.5CLR P2.6LCALL DELAYSETB P2.6CLR P2.7LCALL DELAYSETB P2.7DJNZ R5,MAIN1SETB P2.4 ;关显示SETB P2.5SETB P2.6SETB P2.7SJMP MAIN2DELAY:MOV R7 ,#05H //;延时LP8: MOV R6,#19HLP7:DJNZ R6,LP7DJNZ R7,LP8RET; DS18B20初始化汇编程序;*****************************************//MAIN2:LCALL DISP //;主程序SETB P3.2 // ;18B20DQ置1拉高LCALL INIT // ;调初始化MOV A,#0CCH //;跳过ROM匹配------0CCLCALL WRITE // ;调写DS18B20的程序MOV A,#44H // ;发出温度转换命令LCALL WRITE // ;调写DS18B20的程序MOV R6,#34H //;延时136微秒转换时间,写一个字约需70微秒。
DJNZ R6,$LCALL DISPLCALL INITMOV A,#0CCHLCALL WRITEMOV A,#0BEH // ;发出读温度命令LCALL WRITELCALL READCLR CLCALL CONVTEMPLCALL DISPBCDLCALL DISPSJMP MAIN2WRITE:MOV R0,#8 // ;写子程序CLR CWR1: CLR P3.2MOV 20H,#3 // ;延时17微秒DJNZ 20H,$RRC AMOV P3.2,CMOV 21H,#10 // ;发送后延时45微秒DJNZ 21H,$SETB P3.2NOPDJNZ R0,WR1 // ;8位未发送完转SETB P3.2RETREAD: MOV R6,#2 // ;读子程序CLR PSW.5 // ;清清标志F0RE0:MOV R2,#8RE1:CLR CSETB P3.2 // ;拉高DQNOP // ;延时2微秒CLR P3.2 // ;拉低DQSETB P3.2MOV 22H,#3RE2:DJNZ 22H,RE2MOV C,P3.2MOV 23H,#10RE3:DJNZ 23H,RE3RRC ADJNZ R2,RE1 //;8位未读完继续读CPL PSW.5JNB PSW.5,RE4 // ;高8位保存至28HMOV 29H,A // ;低8位及小数保存至29HRE4:MOV 28H,ADJNZ R6,RE0 //;高8位未读继续RETINIT:SETB P3.2 // ;初始化开始DQ置1(整个时隙和理论值不是很准确)NOP //;延时L0:CLR P3.2 // ;DQ拉低MOV 24H,#100 // ;延时400微秒DJNZ 24H,$SETB P3.2 // ;DQ拉高MOV 25H,#10 // ;置40微秒延时常数L01:JNB P3.2,L2 // ;有18B20响应转L2DJNZ 25H,L01 // ;无18B20响应等待40微秒SJMP L0 // ;无18B20重新初始化L2:MOV R7,#60 // ,延时240微秒L3:DJNZ R7,L3SETB P3.2 //;DQ拉高、退出RETCONVTEMP:MOV A,28H //;温度转换ANL A,#80H //;温度正负判别JZ TEMPC1 //;温度为正转CLR C // ;温度为负调整MOV A,29HCPL AADD A,#01HMOV 29H,AMOV A,28HCPL AADDC A,#00HMOV 28H,AMOV 26H,#0BH // ;温度为负26H内送#0BHSJMP TEMPC11TEMPC1:MOV 26H,#0AH //;温度为正26H内送#0AHTEMPC11:MOV A,26HSWAP AMOV 26H,A // ;26H高4位为温度符号MOV A,29H // ;取温度小数部分ANL A,#0FH ;去整数个位MOV DPTR,#DOTTABMOVC A,@A+DPTRMOV 27H,A // ;查表得小数值,并保存至27H单元MOV A,29H // ;温度整数部分拼装后暂时存入AANL A,#0F0H // ;留下整数个位SWAP AMOV 29H,AMOV A,28HANL A,#0FHSWAP AHEX2BCD1:MOV B,#64H // ;温度整数部分除100得整数百位,并存入R7中DIV ABMOV R7,A // ;R7中为百位,B中为十位和个位MOV A,#0AH // ;温度整数部分除10得整数十位和个位XCH A,B // ;除数与被除数交换DIV ABSWAP AORL A,BTEMPC10:MOV 29H,A // ;温度十位和个位存入29H单元中,十位在高4位,个位在低4位ANL A,#0F0H // ;取温度十位SWAP AORL A,26H //;十位加温度符号存入26H单元;高4位为符号MOV 26H,AMOV A,29HANL A,#0FH // ;取温度个位SWAP AORL A,27HMOV 27H,A // ;27H单元中高4位为个位,低4位为小数MOV A,R7JZ TEMPC12 // ;百位为0退出ANL A,#0FH // ;百位不为0即温度为正和十位重新拼装后存入26H,高4位为百位SWAP A // ;MOV R7,AMOV A,26HANL A,#0FH ; // ;去除26H单元的符号ORL A,R7 //;百位和十位拼装,放入26H单元高4位为百位MOV 26H,A // ;低4位为十位TEMPC12:RETDOTTAB:DB 00H,01H,01H,02H,03HDB 03H,04H,04H,05H,06HDB 06H,07H,08H,08H,09H,09HDISPBCD:MOV A,27H // ;BCD码转换ANL A,#0FHMOV 70H,A // ;取小数,并保存在70H中SWAP AANL A,#0FHMOV 71H,A // ;取整数个位,并保存在71H中MOV A,26HANL A,#0FHMOV 72H,A //;取整数十位,并保存在72H中MOV A,26HSWAP AANL A,#0FHMOV 73H,A // ;取整数百位,并保存在73H中MOV A,72H //;取整数十位ANL A,#0F0HCJNE A,#00H,DISPBCD2SJMP DISPBCD2DISPBCD0:MOV A,26H // ;取整数百位ANL A,#0F0HCJNE A,#00H,DISPBCD2 //;百位不等于0退出MOV A,26HSW AP AANL A,#0FH //;十位保留符号MOV 73H,#0AHMOV 72H,ADISPBCD2:RETDISP:MOV R1,#70H // ;显示子程序MOV R5,#11101111B // ;送Y4位码PLAY:MOV P0,#0FFH // ;关段码MOV A,R5 // ;取Yn位码MOV P2,A // ;送位码MOV A,@R1 //;取段码MOV DPTR,#TABMOVC A,@A+DPTRMOV P0,A // ;送段码MOV A,R5JB ACC.5,LOOP1 // ;位码未指向Y2(整数个位)转CLR P0.7 ;;开小数点LOOP1:LCALL DL1MS //;调显示延时INC R1 // ;指向下一位显示段码MOV A,R5 ;取显示位码JNB ACC.7,ENDOUTRL A // ;向下一位位码MOV R5,AAJMP PLAYENDOUT:MOV P0,#0FFHMOV P3,#0FFHRETTAB: DB 0C0H,0F9H,0A4H,0B0HDB 99H,92H,82H,0F8HDB 80H,90H,0FFH,0BFHDL1MS:MOV R6,#14H // ;延时1mS DL1: MOV R7,#19HDL2: DJNZ R7,DL2DJNZ R6,DL1RETEND。
18B20温度传感器温度计程序2008-9-261.实验任务本实验实现的是通过18B20温度传感器读回温度并在6位数码管上显示。
精度为,范围为2.实验目的学会使用单片机控制18B20此类单总线器件。
原理及引脚介绍DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。
DS18B20产品的特点(1)、只要求一个端口即可实现通信。
(2)、在DS18B20中的每个器件上都有独一无二的序列号。
(3)、实际应用中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55。
C到+125。
C之间。
(5)、数字温度计的分辨率用户可以从9位到12位选择。
(6)、内部有温度上、下限告警设置。
TO-92封装的DS18B20的引脚排列见下图,其引脚功能描述见下:1.GND地信号2.DQ数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也能够向器件提供电源。
3.VDD可选择的VDD引脚。
当工作于寄生电源时,此引脚必需接地。
18B20管脚图4.实验原理图实验原理图5. 18B20操纵命令字指令说明读ROM(33H) 读18B20的序列号匹配ROM(55H) 继续读完64位序列号的命令,用于多个18B20时定位跳过ROM(CCH) 此命令执行后的在存储器打操作针对在线所有18B20 搜ROM(F0H) 识别总线上各器件的编码,为操作各器件做准备报警搜索(ECH) 公温度越限的器件对此命令作出响应指令说明温度转换(44H) 启动在线18B20做温度AD转换读数据(BEH) 从高速暂存器读9位温度值和CRC值写数据(4EH) 将数据写入高速暂存的第3和第4字节中复制(48H) 将高速暂存器中第3和第4字节复制到EERAM读EERAM(B8H) 将EERAM内容写入高速暂存器中第3和第4字节读电源供电方式(B4H) 了解18B20的供电方式6. 实验源程序WENDU_L EQU 29H;用于保留读出温度的低字节WENDU_H EQU 28H;用于保留读出温度的高字节XIAOSHU EQU 27H;用于保留温度的小数部份ZHENGSHU EQU 26H;用于保留整数部份BIAOZHI BIT 50H;18B20检查位1为存在,0为不存在ORG 0000HAJMP MAINORG 0030HMAIN:MOV SCON,#00HACALL DUWENACALL ZHENGHEACALL BCDACALL DISPACALL TIME1AJMP MAIN;---------------------------------------------------------------------------------------------------------------------------------------- ;读温度子程序;---------------------------------------------------------------------------------------------------------------------------------------- DUWEN:SETBACALL FUWEI ;读温度之前必需先复位JB BIAOZHI,CUNZAI;查看标志位看18B20是不是存在,1为存在,0为不存在RET ;不存在那么返回CUNZAI: ;存在那么开始读温度MOV A,#0CCH ;跳过ROM匹配ACALL XIE ;调写子程序MOV A,#44H ;发出温度转换命令ACALL XIE ;调写子程序ACALL TIME1 ;调1秒延时,等等AD转换完成,此刻分辨率为12位,温度最大转换时刻为750MSACALL FUWEI ;读温前需要复位MOV A,#0CCH ;跳过ROM匹配ACALL XIEMOV A,#0BEH ;发读温度命令ACALL XIEACALL DUSHU ;将闱出数据读回CLRRET;------------------------------------------------------------------------------------------------------------------------------;复位子程序;18B20复位需要将数据位拉低500us;18B20收到信号后要等待16-60us,然后发出60-240us的低脉冲;------------------------------------------------------------------------------------------------------------------------------- FUWEI:SETBNOPCLRMOV R0,#3INTE:MOV R1,#107 ;设一个537us延时KK1: DJNZ R1,KK1DJNZ R0,INTESETB ;拉高数据线,等待回应NOPNOPNOPMOV R0,#25 ;INTE1:JNB ,INTE2 ;延时延时50us等待18B20回应,假设返回低脉冲那么说明18B20存在DJNZ R0 ,INTE1AJMP INTE3 ;通过反映时刻而没检测到18B20的存在,那么跳转去清零标志位INTE2:SETB BIAOZHI ;检测到18B20存在,置1标志位CLRAJMP INTE4INTE3:CLR BIAOZHI ;没检测到18B20,清零标志位AJMP INTE5INTE4:MOV R0,#120 ;延时240us,确定回应信号已发完KK: DJNZ R0,KKINTE5:SETBRET;---------------------------------------------------------------------------------------------------------------------------------------- ;写18B20子程序;----------------------------------------------------------------------------------------------------------------------------------------- XIE:MOV R2,#8 ;写计数寄放器,一共有8位数据CLR CLP:CLRMOV R3,#6 ;设一个延时LL1:DJNZ R3,LL1RRC A ;右循环,先输出低位MOV ,CMOV R3,#23 ;设延时LL: DJNZ R3,LL ;SETBNOPNOPDJNZ R2,LP ;判定是不是完成数据传送SETB ;完成传送拉高数据位RET;----------------------------------------------------------------------------------------------------------------------------------------- ;从18B20中读出温度数据子程序;-----------------------------------------------------------------------------------------------------------------------------------------DUSHU:MOV R4,#2 ;设读回数据个数指针MOV R1,#WENDU_L ;把温度数据低位存入29HRE: MOV R2,#8 ;设数据长度指针RE1: CLR CSETBNOPNOP CLRNOPNOPNOPSETBMOV R3,#9 DJNZ R3,$ MOV C, MOV R3,#23NN: DJNZ R3,NNRRC ADJNZ R2,RE1MOV @R1,A DEC R1 ;高位存入28H DJNZ R4,RERET;---------------------------------------------------------------------------------------------------------------------------------;数据整合子程序;温度源数据的整合,读出数据的高字节的低四位决定温度的整数部份;低字节的低四位决定小数部份;----------------------------------------------------------------------------------------------------------------------------- ZHENGHE:MOV A,#0FHANL A,WENDU_L ;低字节的低四位就是小数部分MOV XIAOSHU,A ;取得小数部份MOV A,WENDU_L ;将高字节的低四位移入低字节的高4位,MOV C,40H ;获得的新字节就是整数部分的数据RRC AMOV C,41HRRC AMOV C,42HRRC AMOV C,43HRRC AMOV ZHENGSHU,ARET;----------------------------------------------------------------------------------------------------------------------------------------- ;显示数据拆解程序、显示程序、延时程序;----------------------------------------------------------------------------------------------------------------------------------------;数据拆解程序BCD:MOV A,ZHENGSHU MOV B,#10DIV ABMOV 50H,AMOV 51H,BMOV A,XIAOSHUMOV R0,#52HMOV R2,#4D0:MOV B,#10MUL ABMOV B,#16DIV ABMOV @R0,AINC R0MOV A,BDJNZ R2,D0RET ;----------------------------------- ;显示程序;---------------------------------- DISP:ACALL TIMEMOV R7,#6MOV DPTR,#TABMOV R0,#55HLP1:MOV A ,@R0;MOVC A,@A+DPTRCJNE R7,#2,NE1ANL A,#07FHNE1:MOV SBUF,AJNB TI ,$CLR TIDEC R0DJNZ R7,LP1RET;---------------------------------------- ;延时程序;---------------------------------------- TIME1:MOV R6,#4LOOP2:MOV R5,#250LOOP1:ACALL D1MSDJNZ R5,LOOP1DJNZ R6,LOOP2RETTIME:MOV R6,#200LOOP3:ACALL D1MSDJNZ R6,LOOP3RETD1MS:MOV R7,#250LOOP0:NOPNOPNOPDJNZ R7,LOOP0RETTAB:DB 0C0H,0F9H,0A4H,0B0H DB 99H, 92H, 82H, 0F8HDB 80H, 90H, 88H, 83HDB 0C6H,0A1H,86H, 8EHDB 0FFHEND。
DS18B20美国达拉斯公司生产的单总线协议的数字温度检测芯片,数据的写入与读取都在一根总线上进行操作,在总线上可以连接多个DS18B20,因为每个DS18B20都有唯一的光刻ROM序列号,所以可以进行ROM匹配,搜索指令进行选择相应的从机序列号。
编写DS18B20的检测程序主要包括:初始化函数(复位脉冲+存在脉冲),写数据函数,读取数据的函数。
对DS18B20的操作包括:初始化函数,ROM指令,RAM指令这三个部分。
接下来我先说一下这三个部分所对应的时序图的理解吧。
初始化:由于上拉电阻的存在,总线默认状态是高电平,接着主机将总线拉低,维持480us 到960us的时间,再接着就是释放总线,维持时间为15us到60us,接着就由从机发出一个低电平信号,将总线拉低,表示该DS18B20是正常地,或者说是存在的,其维持时间为60us 到240us。
上面一图是写入数据的时序图。
写时序:默认状态为高电平,先将总线拉低,至少维持1us 的延时时间,接着就往总线上进行写数据操作,接着DS18B20就开始采样数据了,整个过程时间为60us到120us。
下面一图是读取数据的时序图。
读时序:默认状态为高电平,先将总线拉低,接着在15us 之前,主机进行数据采样,其维持时间也为60us到120us。
下面是我在理解了DS18B20的原理之后所写的程序,调试成功了,且能实时读取外界温度的功能,这里是不读取小数部分的温度,只读取温度的正数值。
#include<reg52.h>#define uint unsigned int#define uchar unsigned charuchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};sbit DQ=P2^2;sbit duan=P2^6;sbit wei=P2^7;//是在11.0592M赫兹的频率下void delay_ms(uint t){uint i;for(;t>0;t--)for(i=110;i>0;i--);} //约为tms的延时程序void delay(uint x){while(x--);}void init_ds18b20(){uchar n;DQ=1;delay(2); //约为38usDQ=0;delay(80); //约为800usDQ=1;delay(4); //约为58usn=DQ;delay(10); //约为110us}void write_byte(uchar dat){uchar i;for(i=0;i<8;i++){DQ=0; //无论是写0或写1都要有至少1us的低电平DQ=dat&0x01;//总线直接等于写入的数据(低位在前,高位在后)delay(4); //约为58usDQ=1; //释放总线,为下一步的数据变换做准备dat>>=1;//数据进行移位操作}delay(4);}uchar read_byte(){uchar i,value;for(i=0;i<8;i++){DQ=0;value>>=1; //移位7次DQ=1; //先要释放总线,那样才能采样到有效数据if(DQ) //判断8次{value|=0x80;}delay(6); //约为78us}return value;}uchar read_temperature(){uchar a,b;init_ds18b20(); //每次操作指令前,都必须进行初始化设置write_byte(0xcc);//跳过ROM指令write_byte(0x44);//进行温度转换处理delay(300);//进行一定地延时约为3ms左右init_ds18b20();write_byte(0xcc);//跳过ROM操作write_byte(0xbe);//读取温度a=read_byte();//温度低字节b=read_byte();//温度高字节b<<=4;//b左移四位,低四位为0000b=b+(a&0xf0)>>4;//将a的低四位屏蔽,不取小数点,进行右移四位,合并成一个字节的数据return b;}void display(uchar aa,uchar bb) {duan=1;P0=table[aa];duan=0;P0=0xff;wei=1;P0=0xfe;wei=0;delay_ms(5);duan=1;P0=table[bb];duan=0;P0=0xff;wei=1;P0=0xfd;wei=0;delay_ms(5);}void main(){uchar num,shi,ge;while(1){num=read_temperature();shi=num/10; //分离出十位ge=num%10; //分离出个位display(shi,ge);}}。
本程序为ds18b20的多路温度收集程序,是我自己参考其他程序后改写而成,可显示4路正负温度值,并有上下限温度报警(声音、灯光报警).之青柳念文创作亲测,更改端口即可以使用.(主要器件:51单片机,ds18b20,lcd显示器)附有proteus仿真图,及序列号收集程序/****上限62度下限-20度****/#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit ds=P1^1;sbit rs=P1^4;sbit e=P1^6;sbit sp=P1^0;sbit d1=P1^2;sbit d2=P1^3;ucharlcdrom[4][8]={{0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0 x8e},{0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9},{0x28,0x32,0xc5,0xb8,0x00,0x00,0x00,0xe0},{0x28,0x33,0xc5,0xb8,0x00,0x00,0x00,0xd7}}; unsigned char code table0[]={"TEMPERARTURE:U "}; unsigned char code table1[]={"0123456789ABCDEF"}; int f[4];int tvalue;float ftvalue;uint warnl=320;uint warnh=992;/****lcd程序****/void delayms(uint ms)//延时{uint i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);}void wrcom(uchar com)//写指令{delayms(1);rs=0;P3=com;delayms(1);e=1;delayms(1);e=0;}void wrdat(uchar dat)//写数据{rs=1;e=0;P3=dat;delayms(5);e=1;delayms(5);e=0;}void lcdinit()//初始化lcd{delayms(15);wrcom(0x38);delayms(5); wrcom(0x0c);delayms(5); wrcom(0x06);delayms(5);wrcom(0x01);delayms(5);}void display(uchar *p)//显示{while(*p!='\0'){wrdat(*p);p++;delayms(1);}}displayinit()//初始化显示{lcdinit();wrcom(0x80);display(table0);}/****ds18b20程序****/void dsrst()//ds18b20复位{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit dsrd0()//读一位数据{uint i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return(dat);}uchar dsrd()//读1个字节数据{uchar i,j,dat;dat=0;for(i=8;i>0;i--){j=dsrd0();dat=(j<<7)|(dat>>1);}return(dat);}void dswr(uchar dat)//写数据{uint i;uchar j;bit testb;for(j=8;j>0;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++;}}}void tmstart()//初始化ds18b20{sp=1;d1=1;d2=1;dsrst();delayms(1);dswr(0xcc);dswr(0x44);}void read_dealtemp()//读取并处理温度{uchar i,j,t;uchar a,b;for(j=0;j<4;j++){dsrst();delayms(1);dswr(0x55);for(i=0;i<8;i++){dswr(lcdrom[j][i]);//发送64位序列号}dswr(0xbe);a=dsrd();b=dsrd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0){d1=1;tvalue=~tvalue+1;wrcom(0xc0);wrdat(0x2d);if(tvalue>warnl){d2=0;sp=0;}else{d2=1;sp=1;}}else{d2=1;wrcom(0xc0); wrdat(' ');if(tvalue>warnh) {d1=0;sp=0;}else{d1=1;sp=1;}}if(j==0){wrcom(0x8e);wrdat('2'); }if(j==1){wrcom(0x8e);wrdat('3');}if(j==2){wrcom(0x8e);wrdat('4');}if(j==3){wrcom(0x8e);wrdat('5');}ftvalue=tvalue*0.0625;tvalue=ftvalue*10+0.5;ftvalue=ftvalue+0.05;f[j]=tvalue;//温度扩展十倍,切确到一位小数tvalue=f[j];t=tvalue/1000;wrcom(0x80+0x41);wrdat(table1[t]);//显示百位t=tvalue%1000/100;wrdat(table1[t]);//显示十位t=tvalue%100/10;wrdat(table1[t]);//显示个位wrdat(0x2e); //显示小数点儿t=tvalue%10/1;wrdat(table1[t]);//显示小数位delayms(5000);}}/****主函数****/void main(){d1=1;d2=1;sp=1;displayinit();//初始化显示while(1){tmstart();//初始化read_dealtemp();//读取温度}}/****序列号读取程序****/#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P1^1; //温度传感器信号线sbit rs = P1^4; //LCD数据/饬令选择端(H/L)位声明sbit lcden = P1^6; //LCD使能信号端位声明void delay(uint z);//延时函数void DS18B20_Reset(void); //DQ18B20复位,初始化函数bit DS18B20_Readbit(void); //读1位数据函数uchar DS18B20_ReadByte(void); //读1个字节数据函数void DS18B20_WriteByte(uchar dat); //向DQ18B20写一个字节数据函数void LCD_WriteCom(uchar com); //1602液晶饬令写入函数void LCD_WriteData(uchar dat); //1602液晶数据写入函数void LCD_Init(); //LCD初始化函数void Display18B20Rom(char Rom); //显示18B20序列号函数/**********************************************//* 主函数*//**********************************************/void main(){ uchar a,b,c,d,e,f,g,h; LCD_Init();DS18B20_Reset();delay(1);DS18B20_WriteByte(0x33); delay(1);a = DS18B20_ReadByte();b = DS18B20_ReadByte();c = DS18B20_ReadByte();d = DS18B20_ReadByte();e = DS18B20_ReadByte();f = DS18B20_ReadByte();g = DS18B20_ReadByte();h = DS18B20_ReadByte(); LCD_WriteCom(0x80+0x40); Display18B20Rom(h);Display18B20Rom(g);Display18B20Rom(f);Display18B20Rom(e);Display18B20Rom(d);Display18B20Rom(c);Display18B20Rom(b);Display18B20Rom(a);while(1);}/***************************************************//* 延时函数:void delay() *//* 功能:延时函数*//***************************************************/void delay(uint z)//延时函数{uint x,y;for( x = z; x > 0; x-- )for( y = 110; y > 0; y-- );}/***************************************************//* DS18B20函数:void DS18B20_Reset() *//* 功能:复位18B20/***************************************************/void DS18B20_Reset(void)//DQ18B20复位,初始化函数{uint i;DQ = 0;i = 103;while( i > 0 ) i--;DQ = 1;i = 4;while( i > 0 ) i--;}/***************************************************//* DS18B20函数:void DS18B20_Readbit() *//* 功能:读1个字节数据函数*//***************************************************/bit DS18B20_Readbit(void) //读1位数据函数uint i;bit dat;DQ = 0;i++; //i++起延时作用DQ = 1;i++;i++;dat = DQ;i = 8;while( i > 0 )i--;return( dat );}/***************************************************//* DS18B20函数:void DS18B20_ReadByte() *//* 功能:读1个字节数据函数*//***************************************************/uchar DS18B20_ReadByte(void) //读1个字节数据函数{uchar i,j,dat;dat = 0;for( i = 1; i <= 8; i++ ){j = DS18B20_Readbit();dat = ( j << 7 ) | ( dat >> 1 );}return(dat);}/***************************************************//* DS18B20函数:void DS18B20_WriteByte() *//* 功能:向DQ18B20写一个字节数据函数*//***************************************************/void DS18B20_WriteByte(uchar dat) //向DQ18B20写一个字节数据函数{uint i;uchar j;bit testb;for( j=1; j<=8; j++){testb = dat&0x01;dat= dat>>1;if(testb) //写1{DQ = 0;i++;i++;DQ = 1;i = 8;while(i>0)i--; }else{DQ = 0; //写0 i = 8;while(i>0)i--; DQ = 1;i++;i++;}}}/***********************************************//* LCD函数:void LCD_WriteCom() *//* 功能:向LCD写入饬令*//***********************************************/void LCD_WriteCom(uchar com){rs = 0;P3= com;delay(5);lcden = 0;delay(5);lcden = 1;delay(5);lcden = 0;}/***********************************************//* LCD函数:void LCD_WriteData(uchar dat) *//* 功能:向LCD写入数据/***********************************************/void LCD_WriteData(uchar dat){rs = 1; //选择LCD为写入数据状态lcden = 0;P3= dat; //将待写入数据放到总线上delay(5);lcden = 1; //给LCD使能端一个脉冲delay(5); //信号将之前放到总线上lcden = 0; //的数据写入LCDdelay(5);}/***********************************************//* LCD函数:void LCD_Init() *//* 功能:初始化LCD,设定LCD的初始状态/***********************************************/void LCD_Init(){LCD_WriteCom(0x38); //LCD显示形式设定delay(15);LCD_WriteCom(0x08); //关闭LCD显示delay(3);LCD_WriteCom(0x01); //LCD显示清屏delay(3);LCD_WriteCom(0x06); //设定光标地址指针为自动加1delay(3);LCD_WriteCom(0x0c); //打开LCD显示,但不显示光标}/**********************************************//* *//* 显示18B20序列号*//* *//**********************************************/void Display18B20Rom(char Rom){uchar h,l;l = Rom & 0x0f; //取低4位h = Rom & 0xf0; //取高4位h >>= 4;if( ( h >= 0x00 )&&( h <= 0x09 ) )LCD_WriteData(h+0x30);//取ASCII码elseLCD_WriteData(h+0x37);//取ASCII码if( ( l >= 0x00 )&&( l <= 0x09 ) )LCD_WriteData(l+0x30);//取ASCII码elseLCD_WriteData(l+0x37);//取ASCII码}。
#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();}}。
程序介绍:本程序为单总线上多个ds18b20温度传感器自动读取身份ID并保存,然后在显示屏上分别显示温度程序,以用3个18b20测试过,可执行程序。
程序内容:#include <reg52.h>#include <intrins.h>#define uchar unsigned char //定义无符号单字节#define uint unsigned int //定义无符号整形#define MAXNUM 5 //定义最多DS18B20个数超过的无法显示sbit DQ=P3^7; //定义数据线sbit RS=P3^0;sbit RW=P3^1;sbit E=P3^2;uchar code lcd0[]={"SEARCH ROMING..."};uchar code lcd1[]={"SEARCH ROM OK!"};uchar code lcd2[]={"The total is:"};uchar code lcd3[]={"No.( ):"};uchar code lcd4[]={'0','1','2','3','4','5','6','7','8','9','.',0xdf,0x43};uchar dat[6];uchar temp_l,temp_h,is_fuwen,temp_x,temp_over,t;uchar num=0;uint i;uchar al[MAXNUM];idata uchar ID[MAXNUM][8]; // ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}void alarm_search(void);/***********************液晶模块**********************************/void delay()//延时程序{uchar y;for(y=0;y<250;y++);}void LCD_write_com(uchar com)//写{delay();RS=0;RW=0;E=0;E=1;P0=com;E=0;delay();}void LCD_write_data(uchar dat){delay();RS=1;RW=0;E=0;E=1;P0=dat;E=0;delay();}void init()//初始化{LCD_write_com(0x01);LCD_write_com(0x38);LCD_write_com(0x0c);LCD_write_com(0x06);}/************************ds18b20****************************/void delay_nus(uint n)//延时程序一次8+6(进出)=14us{while(n--);}void reset(void) //ds18b20初始化复位操作{unsigned char x=0;DQ = 1; //DQ复位delay_nus(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_nus(80); //精确延时大于480usDQ = 1; //拉高总线delay_nus(10);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_nus(5);}void write_bit(uchar dat) //DS18B20 写一位操作{DQ = 0;_nop_();_nop_();DQ = dat&0x01;delay_nus(5);DQ = 1;}void write_byte(uchar dat)//写一个字节{unsigned char i,j;for (i=8; i>0; i--){j=dat&0x01;write_bit(j);dat>>=1;}}uchar read_2bit()//读二位子程序{uchar i;uchar dat = 0;for (i=2;i>0;i--){DQ = 0; // 给脉冲信号dat<<=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x01;delay_nus(4);}return(dat);}uchar read_byte()//读一个字节子程序{uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_nus(4);}return(dat);}void delay_nms(uint n){uint j;for(j=0;j<n;j++);}void read_temp(uchar i)//读取温度子程序{uchar f;reset();write_byte(0xcc);write_byte(0x44);delay_nms(50000);reset();write_byte(0x55);for(f=0;f<8;f++){write_byte(ID[i][f]);//发匹配ROM}delay_nus(100);write_byte(0xbe);delay_nus(100);temp_l=read_byte();temp_h=read_byte();}void temp_convert()//温度转换{temp_x=(temp_l&0x0f)*0.625+0.5;is_fuwen=temp_h&0xf8;if(is_fuwen){is_fuwen=1;temp_h=~temp_h;if(temp_l==0)temp_h++; //若低8位全为0且温度为负,取补时就要向高位进1temp_l=~temp_l+1;}temp_h<<=4;temp_l>>=4;temp_over=temp_h|temp_l;delay_nus(255);}/*******************显示***************************/ void _search_cartoon(void)//搜索ROM动画{init();LCD_write_com(0x80);for(i=0;i<16;i++){LCD_write_data(lcd0[i]);}LCD_write_com(0xc0);for(i=0;i<16;i++){LCD_write_data(0xff);delay_nms(num*2000);}}void _display_total() //显示总数{init();LCD_write_com(0x80);for(i=0;i<14;i++){LCD_write_data(lcd1[i]);}LCD_write_com(0xc0);for(i=0;i<13;i++){LCD_write_data(lcd2[i]);}LCD_write_data(lcd4[num]);delay_nms(50000);delay_nms(50000);}void _display_ds18b20(i)//显示编号为i的DS18B20的温度// {uint data_b,data_temp,l;data_b=temp_over/100;//百位//data_temp=temp_over%100;dat[0]=data_temp/10;//十位//dat[1]=data_temp%10;//个位//dat[2]=10;dat[3]=temp_x;dat[4]=11;dat[5]=12;init();LCD_write_com(0x80);for(l=0;l<14;l++){LCD_write_data(lcd1[l]);}LCD_write_com(0xc0);for(l=0;l<7;l++){LCD_write_data(lcd3[l]);}LCD_write_com(0xc4);LCD_write_data(lcd4[++i]);LCD_write_com(0xc8);if(is_fuwen==1){LCD_write_data(0x2d);}else{LCD_write_data(lcd4[data_b]);}for(l=0;l<6;l++)LCD_write_data(lcd4[dat[l]]);delay_nms(50000);delay_nms(50000);}/***********************自动搜索ROM*****************************/ void search_rom(void)//搜索ROM{uchar k,l,chongtuwei,m,n;uchar zhan[(MAXNUM-1)];uchar ss[64];l=0;do{reset();write_byte(0xf0);for(m=0;m<8;m++){uchar s=0;for(n=0;n<8;n++){k=read_2bit();//读两位数据k=k&0x03;s>>=1;if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应{write_bit (0);ss[(m*8+n)]=0;}else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应{s=s|0x80;write_bit (1);ss[(m*8+n)]=1;}else if(k==0x00)//读到的数据为00 有冲突位判断冲突位{ //如果冲突位大于栈顶写0 小于栈顶写以前数据等于栈顶写1chongtuwei=m*8+n+1;if(chongtuwei>zhan[l]){write_bit (0);ss[(m*8+n)]=0;zhan[++l]=chongtuwei;}else if(chongtuwei<zhan[l]){s=s|((ss[(m*8+n)]&0x01)<<7);write_bit (ss[(m*8+n)]);}else if(chongtuwei==zhan[l]){s=s|0x80;write_bit (1);ss[(m*8+n)]=1;l=l-1;}}else{goto loop;}}ID[num][m]=s;}num=num+1;}while(zhan[l]!=0&&(num<MAXNUM));loop: _search_cartoon(); //搜索ROM动画_display_total(); //显示总数}void match_rom(uchar i){uchar c;reset();write_byte(0x55);for(c=0;c<8;c++)write_byte(ID[--i][c]);}void write_schratchpad(char H,char L){write_byte(0x4e);write_byte(H);write_byte(L);}void copy_schratchpad(){write_byte(0x48);//复制ram中第2.3字节}void recall_EE(){write_byte(0xb8);//将e*eprom中内容恢复到ram中的第3,4字节}void main (void){uchar i;search_rom();//搜索ROM并且存储// reset();// write_byte(0xcc);// write_schratchpad(30,15);// reset();// write_byte(0xcc);// copy_schratchpad();reset();match_rom(0);recall_EE();while(1){for(i=0;i<num;i++) //编号0到num-1 个ds18b20 循环{read_temp(i); //读编号i (0--(num-1))ds18b20 的温度temp_convert(); //调用温度转换_display_ds18b20(i);//显示编号i 的温度while(temp_over%100/10>=3);}//alarm_search();}}/*void alarm_search(void){uchar k,l,chongtuwei,m,n,numb,a;uchar zhan[(MAXNUM-1)];uchar ss[64],ID0[MAXNUM][8];l=0;P1=0xe0;do{reset();write_byte(0xec);for(m=0;m<8;m++){uchar s=0;for(n=0;n<8;n++){k=read_2bit();//读两位数据k=k&0x03;s>>=1;if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应{write_bit (0);ss[(m*8+n)]=0;}else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应{s=s|0x80;write_bit (1);ss[(m*8+n)]=1;}else if(k==0x00)//读到的数据为00 有冲突位判断冲突位{ //如果冲突位大于栈顶写0 小于栈顶写以前数据等于栈顶写1chongtuwei=m*8+n+1;if(chongtuwei>zhan[l]){write_bit (0);ss[(m*8+n)]=0;zhan[++l]=chongtuwei;}else if(chongtuwei<zhan[l]){s=s|((ss[(m*8+n)]&0x01)<<7);write_bit (ss[(m*8+n)]);}else if(chongtuwei==zhan[l]){s=s|0x80;write_bit (1);ss[(m*8+n)]=1;l=l-1;}}else{goto loop1;}}ID0[numb][m]=s;}numb=numb+1;}while(zhan[l]!=0&&(numb<MAXNUM));k=0;for(m=0;m<numb;m++){for(l=0;l<num;l++){for(n=0;n<8;n++){if(ID0[m][n]==ID[l][n]){a++;if(a==8){al[k]=m;k++;}}}a=0;}}LCD_write_com(0x8f);for(m=0;m<k;m++){LCD_write_data(lcd4[al[m]+1]);}P1=0x00;loop1: if(P1!=0x00)P1=0xfe;} */。
硬件:51板(1)单线ds18b20接P2.2(2)使用外部电源给ds18b20供电,没有使用寄生电源奥软件:Kei uVision 2刚开始对时序把握不好,可是在论坛里没找到比较详细的解释,所以俺倒塌了这个东东,就把俺的经验贴上来,供大家参考,呵呵……如有错误请指正#include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){while(us--);}void delay(uint count) //延时子函数{uint i;while(count){i=200;while(i>0)i--;count--;}}/*串口初始化,波特率9600,方式1 */void init_com(){TMOD=0x20; //设置定时器1为模式2TH1=0xfd; //装初值设定波特率TL1=0xfd;TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示*/void display(uint temp){uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存wela=0;P0=0xfe;wela=1;wela=0;delay(1); //延时约2msP0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1);}/*****************************************时序:初始化时序、读时序、写时序。
本程序为ds18b20的多路温度采集程序,是我自己参考其他程序后改写而成,可显示4路正负温度值,并有上下限温度报警(声音、灯光报警)。
亲测,更改端口即可使用。
(主要器件:51单片机,ds18b20,lcd显示器)附有proteus仿真图,及序列号采集程序/****上限62度下限-20度****/#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit ds=P1^1;sbit rs=P1^4;sbit e=P1^6;sbit sp=P1^0;sbit d1=P1^2;sbit d2=P1^3;uchar lcdrom[4][8]={{0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0x8e}, {0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9},{0x28,0x32,0xc5,0xb8,0x00,0x00,0x00,0xe0},{0x28,0x33,0xc5,0xb8,0x00,0x00,0x00,0xd7}}; unsigned char code table0[]={"TEMPERARTURE:U "}; unsigned char code table1[]={"0123456789ABCDEF"};int f[4];int tvalue;float ftvalue;uint warnl=320;uint warnh=992;/****lcd程序****/void delayms(uint ms)//延时{uint i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);void wrcom(uchar com)//写指令{delayms(1);rs=0;P3=com;delayms(1);e=1;delayms(1);e=0;}void wrdat(uchar dat)//写数据{rs=1;e=0;P3=dat;delayms(5);e=1;delayms(5);e=0;}void lcdinit()//初始化lcddelayms(15);wrcom(0x38);delayms(5);wrcom(0x0c);delayms(5);wrcom(0x06);delayms(5);wrcom(0x01);delayms(5); }void display(uchar *p)//显示{while(*p!='\0'){wrdat(*p);p++;delayms(1);}}displayinit()//初始化显示{lcdinit();wrcom(0x80);display(table0);}/****ds18b20程序****/ void dsrst()//ds18b20复位{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit dsrd0()//读一位数据{uint i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return(dat);uchar dsrd()//读1个字节数据{uchar i,j,dat;dat=0;for(i=8;i>0;i--){j=dsrd0();dat=(j<<7)|(dat>>1);}return(dat);}void dswr(uchar dat)//写数据{uint i;uchar j;bit testb;for(j=8;j>0;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++;}}}void tmstart()//初始化ds18b20 {sp=1;d1=1;d2=1;dsrst();delayms(1);dswr(0xcc);dswr(0x44);}void read_dealtemp()//读取并处理温度{uchar i,j,t;uchar a,b;for(j=0;j<4;j++){dsrst();delayms(1);dswr(0x55);for(i=0;i<8;i++){dswr(lcdrom[j][i]);//发送64位序列号}dswr(0xbe);a=dsrd();b=dsrd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0){d1=1;tvalue=~tvalue+1;wrcom(0xc0);wrdat(0x2d);if(tvalue>warnl){d2=0;sp=0;}else{d2=1;sp=1;}}else{d2=1;wrcom(0xc0);wrdat(' ');if(tvalue>warnh){d1=0;sp=0;}else{d1=1;sp=1;}}if(j==0){wrcom(0x8e); wrdat('2');}if(j==1){wrcom(0x8e);wrdat('3');}if(j==2){wrcom(0x8e);wrdat('4');}if(j==3){wrcom(0x8e);wrdat('5');}ftvalue=tvalue*0.0625;tvalue=ftvalue*10+0.5;ftvalue=ftvalue+0.05;f[j]=tvalue;//温度扩大十倍,精确到一位小数tvalue=f[j];t=tvalue/1000;wrcom(0x80+0x41);wrdat(table1[t]);//显示百位t=tvalue%1000/100;wrdat(table1[t]);//显示十位t=tvalue%100/10;wrdat(table1[t]);//显示个位wrdat(0x2e); //显示小数点儿t=tvalue%10/1;wrdat(table1[t]);//显示小数位delayms(5000);}}/****主函数****/void main(){d1=1;d2=1;sp=1;displayinit();//初始化显示while(1){tmstart();//初始化read_dealtemp();//读取温度}}/****序列号读取程序****/#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P1^1; //温度传感器信号线sbit rs = P1^4; //LCD数据/命令选择端(H/L)位声明sbit lcden = P1^6; //LCD使能信号端位声明void delay(uint z); //延时函数void DS18B20_Reset(void); //DQ18B20复位,初始化函数bit DS18B20_Readbit(void); //读1位数据函数uchar DS18B20_ReadByte(void); //读1个字节数据函数void DS18B20_WriteByte(uchar dat); //向DQ18B20写一个字节数据函数void LCD_WriteCom(uchar com); //1602液晶命令写入函数void LCD_WriteData(uchar dat); //1602液晶数据写入函数void LCD_Init(); //LCD初始化函数void Display18B20Rom(char Rom); //显示18B20序列号函数/**********************************************//* 主函数 *//**********************************************/void main(){ uchar a,b,c,d,e,f,g,h;LCD_Init();DS18B20_Reset();delay(1);DS18B20_WriteByte(0x33);delay(1);a = DS18B20_ReadByte();b = DS18B20_ReadByte();c = DS18B20_ReadByte();d = DS18B20_ReadByte();e = DS18B20_ReadByte();f = DS18B20_ReadByte();g = DS18B20_ReadByte();h = DS18B20_ReadByte();LCD_WriteCom(0x80+0x40);Display18B20Rom(h);Display18B20Rom(g);Display18B20Rom(f);Display18B20Rom(e);Display18B20Rom(d);Display18B20Rom(c);Display18B20Rom(b);Display18B20Rom(a);while(1);}/***************************************************//* 延时函数:void delay() *//* 功能:延时函数*//***************************************************/void delay(uint z)//延时函数{uint x,y;for( x = z; x > 0; x-- )for( y = 110; y > 0; y-- );}/***************************************************//* DS18B20函数:void DS18B20_Reset() *//* 功能:复位18B20 *//***************************************************/void DS18B20_Reset(void)//DQ18B20复位,初始化函数{uint i;DQ = 0;i = 103;DQ = 1;i = 4;while( i > 0 ) i--;}/***************************************************//* DS18B20函数:void DS18B20_Readbit() *//* 功能:读1个字节数据函数*//***************************************************/bit DS18B20_Readbit(void) //读1位数据函数{uint i;bit dat;DQ = 0;i++; //i++起延时作用DQ = 1;i++;i++;dat = DQ;i = 8;return( dat );}/***************************************************//* DS18B20函数:void DS18B20_ReadByte() *//* 功能:读1个字节数据函数*//***************************************************/uchar DS18B20_ReadByte(void) //读1个字节数据函数{uchar i,j,dat;dat = 0;for( i = 1; i <= 8; i++ ){j = DS18B20_Readbit();dat = ( j << 7 ) | ( dat >> 1 );}return(dat);}/***************************************************//* DS18B20函数:void DS18B20_WriteByte() *//* 功能:向DQ18B20写一个字节数据函数*//***************************************************/void DS18B20_WriteByte(uchar dat) //向DQ18B20写一个字节数据函数{uint i;uchar j;bit testb;for( j=1; j<=8; j++){testb = dat&0x01;dat= dat>>1;if(testb) //写1{DQ = 0;i++;i++;DQ = 1;i = 8;while(i>0)i--;}else{DQ = 0; //写0i = 8;while(i>0)i--;DQ = 1;i++;i++;}}}/***********************************************//* LCD函数:void LCD_WriteCom() *//* 功能:向LCD写入命令*//***********************************************/void LCD_WriteCom(uchar com){rs = 0;P3= com;delay(5);lcden = 0;delay(5);lcden = 1;delay(5);lcden = 0;}/***********************************************//* LCD函数:void LCD_WriteData(uchar dat) *//* 功能:向LCD写入数据*//***********************************************/void LCD_WriteData(uchar dat){rs = 1; //选择LCD为写入数据状态lcden = 0;P3= dat; //将待写入数据放到总线上delay(5);lcden = 1; //给LCD使能端一个脉冲delay(5); //信号将之前放到总线上lcden = 0; //的数据写入LCDdelay(5);}/***********************************************//* LCD函数:void LCD_Init() *//* 功能:初始化LCD,设定LCD的初始状态*//***********************************************/void LCD_Init(){LCD_WriteCom(0x38); //LCD显示模式设定delay(15);LCD_WriteCom(0x08); //关闭LCD显示delay(3);LCD_WriteCom(0x01); //LCD显示清屏delay(3);LCD_WriteCom(0x06); //设定光标地址指针为自动加1delay(3);LCD_WriteCom(0x0c); //打开LCD显示,但不显示光标}/**********************************************//* *//* 显示18B20序列号 */ /* *//**********************************************/void Display18B20Rom(char Rom){uchar h,l;l = Rom & 0x0f; //取低4位h = Rom & 0xf0; //取高4位h >>= 4;if( ( h >= 0x00 )&&( h <= 0x09 ) )LCD_WriteData(h+0x30); //取ASCII码 elseLCD_WriteData(h+0x37); //取ASCII码if( ( l >= 0x00 )&&( l <= 0x09 ) )LCD_WriteData(l+0x30); //取ASCII码 elseLCD_WriteData(l+0x37); //取ASCII码}。