ds18b20的完整程序
- 格式:pdf
- 大小:154.91 KB
- 文档页数:4
(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);}}。
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。
#include<reg52.h>//52单片机头文件,规定了52单片机的寄存器和IO口等#include<intrins.h>//_nop_空指令及左右循环移位子函数库#include "DS18B20.h"#include "lcd1602.h"#include "ds1302.h"unsigned char code digit[10]={"0123456789"}; //定义字符数组显示数字/************************************************************************以下是DS18B20的操作程序************************************************************************/sbit DQ=P3^5;unsigned char time; //设置全局变量,专门用于严格延时/*****************************************************函数功能:将DS18B20传感器初始化,读取应答信号出口参数:flag***************************************************/bit Init_DS18B20(void){bit flag; //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在DQ = 1; //先将数据线拉高for(time=0;time<2;time++) //略微延时约6微秒;DQ = 0; //再将数据线从高拉低,要求保持480~960usfor(time=0;time<200;time++) //略微延时约600微秒; //以向DS18B20发出一持续480~960us的低电平复位脉冲DQ = 1; //释放数据线(将数据线拉高)for(time=0;time<10;time++); //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)flag=DQ; //让单片机检测是否输出了存在脉冲(DQ=0表示存在)for(time=0;time<200;time++) //延时足够长时间,等待存在脉冲输出完毕;return (flag); //返回检测成功标志}/*****************************************************函数功能:从DS18B20读取一个字节数据出口参数:dat***************************************************/unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat; //储存读出的一个字节数据for (i=0;i<8;i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ = 0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序dat>>=1;_nop_(); //等待一个机器周期DQ = 1; //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备for(time=0;time<2;time++); //延时约6us,使主机在15us内采样if(DQ==1)dat|=0x80; //如果读到的数据是1,则将1存入datelsedat|=0x00;//如果读到的数据是0,则将0存入dat//将单片机检测到的电平信号DQ存入r[i]for(time=0;time<8;time++); //延时3us,两个读时序之间必须有大于1us的恢复期}return(dat); //返回读出的十进制数据}/*****************************************************函数功能:向DS18B20写入一个字节数据入口参数:dat***************************************************/WriteOneChar(unsigned char dat){unsigned char i=0;for (i=0; i<8; i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ=0; //将数据线从高拉低时即启动写时序DQ=dat&0x01; //利用与运算取出要写的某位二进制数据,//并将其送到数据线上等待DS18B20采样for(time=0;time<10;time++);//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样DQ=1; //释放数据线for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期dat>>=1; //将dat中的各二进制位数据右移1位}for(time=0;time<4;time++); //稍作延时,给硬件一点反应时间}/****************************************************************************** 以下是与温度有关的显示设置******************************************************************************//*****************************************************函数功能:显示温度符号***************************************************//*void display_symbol(void){unsigned char i;write_com(0x80); //写显示地址,将在第1行第1列开始显示i = 0; //从第一个字符开始显示while(Temp[i] != '\0') //只要没有写到结束标志,就继续写{write_data(Temp[i]); //将字符常量写入LCDi++; //指向下一个字符delay1ms(); //延时1ms给硬件一点反应时间}}*//*****************************************************函数功能:显示温度的小数点***************************************************/void display_dot(void){write_com(0x80+14); //写显示地址,将在第1行第9列开始显示write_data('.'); //将小数点的字符常量写入LCDdelay1ms(); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:显示温度的单位(C)***************************************************//***void display_cent(void){unsigned char i;write_com(0x80+10); //写显示地址,将在第1行第10列开始显示i = 0; //从第一个字符开始显示while(Cent[i] != '\0') //只要没有写到结束标志,就继续写{write_data(Cent[i]); //将字符常量写入LCDi++; //指向下一个字符delay1ms(); //延时1ms给硬件一点反应时间}} *//*****************************************************函数功能:显示温度的整数部分入口参数:x***************************************************/void display_temp1(unsigned char x){unsigned char k,l; //j,k,l分别储存温度的百位、十位和个位/*j=x/100; //取百位*/k=(x%100)/10; //取十位l=x%10; //取个位*/write_com(0x80+12); //写显示地址,将在第1行第6列开始显示/* write_data(digit[j]); //将百位数字的字符常量写入LCD */ write_data(digit[k]); //将十位数字的字符常量写入LCDwrite_data(digit[l]); //将个位数字的字符常量写入LCD */}/*****************************************************函数功能:显示温度的小数数部分入口参数:x***************************************************/void display_temp2(unsigned char x){write_com(0x80+15); //写显示地址,将在第2行第11列开始显示write_data(digit[x]); //将小数部分的第一位数字字符常量写入LCDdelay1ms(); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:做好读温度的准备***************************************************/void ReadyReadTemp(void){Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换for(time=0;time<100;time++); //温度转换需要一点时间Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位}。
DS18B20汇编程序;实验目的:熟悉DS18B20的使用;六位数码管显示温度结果,其中整数部分2位,小数部分4位;每次按下RB0键后进行一次温度转换。
;硬件要求:把DS18B20插在18B20插座上; 拨码开关S10第1位置ON,其他位置OFF; 拨码开关S5、S6全部置ON,其他拨码开关全部置OFF;*****************以下是暂存器的定义*****************************#INCLUDE<P16F877A.INC>#DEFINE DQ PORTA,0 ;18B20数据口__CONFIG_DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS _OSCCBLOCK 20HDQ_DELAY1DQ_DELAY2TEMPTEMP1TEMP2 ;存放采样到的温度值TEMP3COUNTCOUNT1ENDCTMR0_VALUE EQU 0AH ;寄存器初值为6,预分频比1:4,中断一次时间为4*(256-6)=1000usDQ_DELAY_VALUE1 EQU 0FAHDQ_DELAY_VALUE2 EQU 4H;**********************以下是程序的开始************************ ORG 00HNOPGOTO MAIN ;入口地址ORG 04HRETFIE ;在中断入口出放置一条中断返回指令,防止干扰产生中断TABLEADDWF PCL,1RETLW 0C0H ;0的编码(公阳极数码管)RETLW 0F9H ;1的编码RETLW 0A4H ;2的编码RETLW 0B0H ;3的编码RETLW 99H ;4的编码RETLW 92H ;5的编码RETLW 082H ;6RETLW 0F8H ;7RETLW 080H ;8RETLW 090H ;9;***************************主程序******************************* MAINCLRF PORTACLRF PORTBBANKSEL TRISACLRF TRISA ;A口所有先设置为输出CLRF TRISDMOVLW 01HMOVWF TRISB ;B0口为输入,其他为输出MOVLW 06HMOVWF ADCON1 ;关闭所有A/D口MOVLW 01HMOVWF OPTION_REG ;分频比1:4,定时器,内部时钟源BCF STATUS,RP0CLRF TEMPCLRF TEMP1CLRF TEMP2 ;清零临时寄存器MOVLW 8HMOVWF COUNTMOVLW 38HMOVWF FSRCLRF INDFINCF FSR,1DECFSZ COUNT,1GOTO $-3;****************************循环处理部分************************;先启动18B20温度转换程序,在判断温度转换是否完成(需750us);未完成则调用显示子程序,直到完成温度转换;完成后读取温度值;送LCD显示LOOPBTFSC PORTB,0 ;判断温度转换按键是否按下GOTO LOOP1 ;否,转显示CALL DELAY ;消抖BTFSC PORTB,0 ;再次判断GOTO LOOP1CALL RESET_18B20 ;调用复位18B20子程序MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 44HMOVWF TEMPCALL WRITE_18B20 ;温度转换命令CLRF STATUSCALL DELAY_750MS ;调用温度转换所需要的750MS延时NOPCALL RESET_18B20MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 0BEHMOVWF TEMPCALL WRITE_18B20 ;读温度命令CALL READ_18B20 ;调用读温度低字节MOVFW TEMPMOVWF TEMP1 ;保存到TEMP1CALL READ_18B20 ;调用读温度高字节MOVFW TEMPMOVWF TEMP2 ;保存到TMEP2CALL RESET_18B20LOOP1CALL TEMP_CHANGE ;调用温度转换程序CALL DISPLAY ;调用LCD显示程序GOTO LOOP ;循环工作;*********************复位DS18B20子程序************************** RESET_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;主控制器把总线拉低至少480us,;18B20等待15-60us后,把总线拉低做为返回给控制器的应答信号BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF DQMOVLW 0A0HMOVWF COUNT ;160USDECFSZ COUNT,1GOTO $-1 ;拉低480usBSF DQ ;释放总线MOVLW 14HMOVWF COUNTDECFSZ COUNT,1GOTO $-1 ;等待60usBANKSEL TRISABSF TRISA,0 ;DQ设置为输入BCF STATUS,RP0BTFSC DQ ;数据线是否为低GOTO RESET_18B20 ;否则继续复位MOVLW 4HMOVWF COUNTDECFSZ COUNT,1 ;延时一段时间后再次判断GOTO $-1BTFSC DQGOTO RESET_18B20MOVLW 4BHMOVWF COUNTDECFSZ COUNT,1GOTO $-1BANKSEL TRISABCF TRISA,0 ;DQ设置为输出BCF STATUS,RP0RETURN;*********************写DS18B20子程序**************************** WRITE_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;写数据0时,主控制器把总线拉低至少60us;写数据1时,主控制器把总线拉低,但必须在15us内释放MOVLW 8HMOVWF COUNT ;8位数据BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF STATUS,CWRITE_18B20_1BSF DQ ;先保持DQ为高MOVLW 5HMOVWF COUNT1BCF DQ ;拉低DQ15usDECFSZ COUNT1,1GOTO $-1RRF TEMP,1BTFSS STATUS,C ;判断写的数据为0还是1GOTO WRITE_0BSF DQ ;为1,立即拉高数据线GOTO WRITE_ENDWRITE_0BCF DQ ;继续保持数据线为低WRITE_ENDMOVLW 0FHMOVWF COUNT1 ;保持45msDECFSZ COUNT1,1GOTO $-1BSF DQ ;释放总线DECFSZ COUNT,1 ;是否写完8位数据GOTO WRITE_18B20_1RETURN;**********************读DS18B20子程序**************************** READ_18B20;根据DATASHEET介绍,读数据时应遵照如下规定:;读数据0时,主控制器把总线拉低后,18B20再把总线拉低60us;读数据1时,主控制器把总线拉低后,保持总线状态不变;主控制器在数据线拉低后15us内读区数据线上的状态。
ds18b20的C语言完整程序(c51)(可组网数字式温度传感器)发布日期:[2005-05-10]作者:(sparkstar)//DS1820 C51 子程序//这里以11.0592M晶体为例,不同的晶体速度可能需要调整延时的时间//sbit DQ =P2^1;//根据实际情况定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ = 0; //pull DQ line lowdelay(29); // leave it low for 480usDQ = 1; // allow line to return highdelay(3); // wait for presencepresence = DQ; // get presence signaldelay(25); // wait for end of timeslotreturn(presence); // presence signal returned} // 0=presence, 1 = no part//从 1-wire 总线上读取一个字节byte read_byte(void){byte i;byte value = 0;for (i=8;i>0;i--){value>>=1;DQ = 0; // pull DQ low to start timeslotDQ = 1; // then return highdelay(1); //for (i=0; i<3; i++);if(DQ)value|=0x80;delay(6); // wait for rest of timeslot}return(value);}//向 1-WIRE 总线上写一个字节void write_byte(char val){byte i;for (i=8; i>0; i--) // writes byte, one bit at a time {DQ = 0; // pull DQ low to start timeslotDQ = val&0x01;delay(5); // hold value for remainder of timeslotDQ = 1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0xBE); // Read Scratch Padtemp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC); //Skip ROMwrite_byte(0x44); // Start Conversionreturn temp.x/2;}。
Lesson11-1:数字温度传感器DS18B20,采用3位数码管显示,仿真通过#include <reg51.h>#define uchar unsigned char#define uint unsigned intsbit DS=P2^2; // 定义DS18B20接口uchar time=100;sbit dula=P2^6;sbit wela=P2^7;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 mdelay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}///////功能:串口初始化,波特率9600,方式1///////void Init_Com(void){TMOD = 0x20;PCON = 0x00;SCON = 0x50;TH1 = 0xFd;TL1 = 0xFd;TR1 = 1;}void dsreset(void) // DS18B20初始化{uint i;DS=0; // 首先拉低,要求480usi=103;while(i>0)i--;DS=1; // 上升沿,要求15~60usi=4;while(i>0)i--;}void rxwait()//等待应答脉冲{uint i;while(DS);while(~DS);i=8;while(i>0)i--;}bit tmpreadbit(void) //读一位{uint i;bit dat;DS=0;i++; //1us延时DS=1;//15us内,主机必须停止将DS引脚置低i++;i++; //15us延时dat=DS;i=8;while(i>0)i--;//读时隙不低于60us延时return (dat);}uchar tmpread(void) // 读一个字节{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样刚好一个字节在DA T里}return(dat); //将一个字节数据返回}void tmpwritebyte(uchar dat) //写一个字节到DS18B20里{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb) //写1部分{DS=0;i++;i++;DS=1;i=8;while(i>0)i--;}else{DS=0; //写0部分i=8;while(i>0)i--;DS=1;i++;i++;}}}void tmpchange(void) //发送温度转换命令{dsreset();//初始化DS18B20rxwait(); //等待应答脉冲mdelay(1); //延时tmpwritebyte(0xcc); // 跳过序列号命令tmpwritebyte(0x44); //发送温度转换命令}uint tmp() //获得温度{float tt;uchar a,b;uint temp; // 存放温度值dsreset();rxwait();//等待应答脉冲mdelay(1);tmpwritebyte(0xcc);tmpwritebyte(0xbe); //发送读取数据命令a=tmpread(); //连续读两个字节数据b=tmpread();temp=b;temp<<=8; //出厂默认设置为12位分辨率temp=temp|a; //两字节合成一个整型变量。
DS18B20简单使用流程
1.复位
2.跳过ROM命令(通过单总线写入0xCC,注意时序)
3.温度转换命令(通过单总线写入0x44,延迟750-900ms)
***************************************************************
4.复位
5.跳过ROM命令
6.读温度暂存器命令(通过单总线写入0xbe,注意时序)
****************************************************************
7.开始读温度(每字节均从低位a0读起)
(读数据操作时序也分为读0时序和读1时序两个过程。
读时隙是从主机把单总线拉低之后,在1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。
DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。
若要送出1则释放总线为高电平。
主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。
采样期内总线为高电平则确认为1。
完成一个读时序过程,至少需要60us才能完成)
8.数据处理(将12位2进制数转成十进制数)
9.显示输出
推荐《DS18B20中文全套资料》。
;单片机DS18B20温度计C语言程序; 有程序#include<reg51.h>#include<intrins.h>#include <math.H> //要用到取绝对值函数abs()//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125度sbit wela = P2^7; //数码管位选sbit dula = P2^6; //数码管段选sbit ds = P2^2;int tempValue;//0-F数码管的编码(共阳极)unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//0-9数码管的编码(共阳极), 带小数点unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,0x19, 0x12, 0x02,0x78, 0x00, 0x10};//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.void delay(unsigned int i){unsigned int j;while(i--){for(j = 0; j < 125; j++);}}//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动 void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us unsigned int i;ds = 0;i = 100; //拉低约800us, 符合协议要求的480us以上while(i>0) i--;ds = 1; //产生一个上升沿, 进入等待应答状态i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds);while(~ds); //检测到应答脉冲i = 4;while(i > 0) i--;}//向DS18B20读取一位数据//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,//之后DS18B20则会输出持续一段时间的一位数据bit readBit(){unsigned int i;bit b;ds = 0;i++; //延时约8us, 符合协议要求至少保持1usds = 1;i++; i++; //延时约16us, 符合协议要求的至少延时15us以上b = ds;i = 8;while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求return b;}//读取一字节数据, 通过调用readBit()来实现unsigned char readByte(){unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}//向DS18B20写入一字节数据void writeByte(unsigned char dat){unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){ds = 0;i++; i++; //拉低约16us, 符号要求15~60us内ds = 1;i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120usds = 0;i = 8; while(i>0) i--; //拉低约64us, 符号要求ds = 1;i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us 了}}//向DS18B20发送温度转换命令void sendChangeCmd(){dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化dsWait(); //等待DS18B20应答delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0x44); //写入温度转换命令字Convert T}//向DS18B20发送读取数据命令void sendReadCmd(){dsInit();dsWait();delay(1);writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0xbe); //写入读取数据令字Read Scratchpad}//获取当前温度值int getTmpValue(){unsigned int tmpvalue;int value; //存放温度数值float t;unsigned char low, high;sendReadCmd();//连续读取两个字节数据low = readByte();high = readByte();//将高低两个字节合成一个整形变量//计算机中对于负数是利用补码来表示的//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的valuetmpvalue = high;tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度t = value * 0.0625;//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}unsigned char const timeCount = 3; //动态扫描的时间间隔//显示当前温度值, 精确到小数点后一位//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码void display(int v){unsigned char count;unsigned char datas[] = {0, 0, 0, 0, 0};unsigned int tmp = abs(v);datas[0] = tmp / 10000;datas[1] = tmp % 10000 / 1000;datas[2] = tmp % 1000 / 100;datas[3] = tmp % 100 / 10;datas[4] = tmp % 10;if(v < 0){//关位选, 去除对上一位的影响P0 = 0xff;wela = 0;//段选P0 = 0x40; //显示"-"号dula = 1; //打开锁存, 给它一个下降沿量dula = 0;//位选P0 = 0xfe;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}for(count = 0; count != 5; count++){//关位选, 去除对上一位的影响P0 = 0xff;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;//段选if(count != 2){P0 = table[datas[count]]; //显示数字}else{P0 = tableWidthDot[datas[count]]; //显示带小数点数字}dula = 0;//位选P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}}void main(){unsigned char i;while(1){//启动温度转换sendChangeCmd();//显示5次for(i = 0; i < 40; i++){display(tempValue);}tempValue = getTmpValue();}以下是我编的程序,可用#include <reg52.h>#include <intrins.h>//-----------------------------------------------------------sbit DQ=P1^5;//-----------------------------------------------------------unsigned char number[10]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};//数字0~9unsigned char wei[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位循环unsigned char Flag;unsigned char Templ,Temph;unsigned int temp;//-----------------------------------------------------------//函数声明//-----------------------------------------------------------void delay(unsigned char i); //延时程序//----------------------------------void Int18b20(void); //18b20初始化void Write18b20(unsigned char dat); //向18b20写一字节unsigned char Read18b20(void); //从18b20读一字节void Start18b20(void); //开始转换温度void Get18b20(void); //读出温度void chinT(void); //数据转换//----------------------------------void display(void); //显示程序//-----------------------------------------------------------//函数功能:延时//-----------------------------------------------------------/*************精确延时函数*****************/void delay(unsigned char i){while(--i);}/*此延时函数针对的是12Mhz的晶振delay(0); //延时518us 误差:518-2*256=6delay(1); //延时7us (原帖写"5us"是错的)delay(10); //延时25us 误差:25-20=5delay(20); //延时45us 误差:45-40=5delay(100); //延时205us 误差:205-200=5delay(200); //延时405us 误差:405-400=5*///-----------------------------------------------------------//DS18b20的相关程序//-----------------------------------------------------------//初始化//-----------------------------------------------------------void Int18b20(void){DQ=1;_nop_();_nop_();DQ=0; //拉低delay(100); //延时205usdelay(200); //延时405us //等待400~960微秒,最短为480us DQ=1;delay(1); //延时7usdelay(20); //延时45us //等待15~60微秒(等待回复)if(DQ==1) //判断初始化的情况是否成功{Flag=0; //复位失败}else{Flag=1;while(!DQ); //等待回复完成}delay(200); //延时405us //等待完成初始化}//-----------------------------------------------------------//写一字节//-----------------------------------------------------------void Write18b20(unsigned char dat){unsigned char i;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7us //拉低后延时小于15usif(dat&0x01){DQ=1;}else{DQ=0;}dat=dat>>1;delay(20); //延时45usdelay(10); //延时25us //延时大于60usDQ=1;delay(1); //延时7us //延时大于1us}}//-----------------------------------------------------------//读一字节//-----------------------------------------------------------unsigned char Read18b20(void){unsigned char i,dat=0;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7usdat=dat>>1;DQ=1;delay(1); //延时7us //确保在15us后60us前读数据if(DQ){dat|=0x80;}delay(20); //延时45us //确保读时续大于60us}return dat;}//-----------------------------------------------------------//开始转换温度//-----------------------------------------------------------void Start18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0x44); //温度转换指令}//-----------------------------------------------------------//读出温度//-----------------------------------------------------------void Get18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0xbe); //读暂存器指令Templ=Read18b20();Temph=Read18b20();}//-----------------------------------------------------------//数据转换//-----------------------------------------------------------void chinT(void){float Tt;temp=Temph; //先把高八位有效数据赋于temptemp=(temp<<8); //将数据从temp低八位移到高八位temp=temp|Templ; //将两字节合成一个整型变量Tt=temp*0.0625; //得到真实十进制温度值(因为DS18B20可以精确到0.0625度) temp=Tt*10+0.5; //放大十倍(将小数点后一位变成个位,个位变成十位,十位变成百位,并四舍五入)}//-----------------------------------------------------------//显示程序//-----------------------------------------------------------void display(void){unsigned int i;unsigned char A1,A2,A3;A1=temp/100; //百位(温度的十位)A2=temp%100/10; //十位(温度的个位)A3=temp%10; //个位(温度的小数点后一位)for(i=0;i<20;i++){P0=0x00;P2=0x00;P0=number[A1];P2=wei[0];delay(220);P0=0x00;P2=0x00;P0=number[A2];P2=wei[1];delay(220);P0=0x00;P2=0x00;P0=number[A3];P2=wei[2];delay(220);P0=0x00;P2=0x00;P0=0x80;P2=wei[1];delay(220);}}//-----------------------------------------------------------//----------------------------------------------------------- void main(void){while(1){Int18b20();if(Flag){Start18b20(); //开始转换温度Get18b20(); //得到温度chinT(); //数据转换display(); //显示}else P3=0x01;}}。
实验任务用一片DS18B20构成测温系统,测量的温度精度达到0.1度,测量的温度的范围在-20度到+100度之间,用8位数码管显示出来。
5.电路原理图6.系统板上硬件连线(1).把“单片机系统”区域中的P0.0-P0.7用8芯排线连接到“动态数码显示”区域中的ABCDEFGH端子上。
(2).把“单片机系统”区域中的P2.0-P2.7用8芯排线连接到“动态数码显示”区域中的S1S2S3S4S5S6S7S8端子上。
(3).把DS18B20芯片插入“四路单总线”区域中的任一个插座中,注意电源与地信号不要接反。
(4).把“四路单总线”区域中的对应的DQ端子连接到“单片机系统”区域中的P3.7/RD端子上。
7.C语言源程序#include <AT89X52.H>#include <INTRINS.h>unsigned char code displaybit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};unsigned char code displaycode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00,0x40};unsigned char code dotcode[32]={0,3,6,9,12,16,19,22,25,28,31,34,38,41,44,48,50,53,56,59,63,66,69,72,75,78,81,84,88,91,94,97};unsigned char displaycount;unsigned char displaybuf[8]={16,16,16,16,16,16,16,16};unsigned char timecount;unsigned char readdata[8];sbit DQ=P3^7;bit sflag;bit resetpulse(void){unsigned char i;DQ=0;for(i=255;i>0;i--);DQ=1;for(i=60;i>0;i--);return(DQ);for(i=200;i>0;i--);}void writecommandtods18b20(unsigned char command) {unsigned char i;unsigned char j;for(i=0;i<8;i++){if((command & 0x01)==0){DQ=0;for(j=35;j>0;j--);DQ=1;}else{DQ=0;for(j=2;j>0;j--);DQ=1;for(j=33;j>0;j--);}command=_cror_(command,1);}}unsigned char readdatafromds18b20(void) {unsigned char i;unsigned char j;unsigned char temp;temp=0;for(i=0;i<8;i++){temp=_cror_(temp,1);DQ=0;_nop_();_nop_();DQ=1;for(j=10;j>0;j--);if(DQ==1){temp=temp | 0x80;}else{temp=temp | 0x00;}for(j=200;j>0;j--);}return(temp);}void main(void){TMOD=0x01;TH0=(65536-4000)/256;TL0=(65536-4000)%256;ET0=1;EA=1;while(resetpulse());writecommandtods18b20(0xcc);writecommandtods18b20(0x44);TR0=1;while(1){;}void t0(void) interrupt 1 using 0{unsigned char x;unsigned int result;TH0=(65536-4000)/256;TL0=(65536-4000)%256;if(displaycount==2){P0=displaycode[displaybuf[displaycount]] | 0x80;}else{P0=displaycode[displaybuf[displaycount]];}P2=displaybit[displaycount];displaycount++;if(displaycount==8){displaycount=0;}timecount++;if(timecount==150)timecount=0;while(resetpulse());writecommandtods18b20(0xcc);writecommandtods18b20(0xbe);readdata[0]=readdatafromds18b20(); readdata[1]=readdatafromds18b20(); for(x=0;x<8;x++){displaybuf[x]=16;}sflag=0;if((readdata[1] & 0xf8)!=0x00) {sflag=1;readdata[1]=~readdata[1];readdata[0]=~readdata[0];result=readdata[0]+1;readdata[0]=result;if(result>255){readdata[1]++;}}readdata[1]=readdata[1]<<4;readdata[1]=readdata[1] & 0x70; x=readdata[0];x=x>>4;x=x & 0x0f;readdata[1]=readdata[1] | x;x=2;result=readdata[1];while(result/10){displaybuf[x]=result%10;result=result/10;x++;}displaybuf[x]=result;if(sflag==1){displaybuf[x+1]=17;}x=readdata[0] & 0x0f;x=x<<1;displaybuf[0]=(dotcode[x])%10; displaybuf[1]=(dotcode[x])/10; while(resetpulse());writecommandtods18b20(0xcc);writecommandtods18b20(0x44);}}。
DS18B20汇编程序(完整版)DS18B20汇编程序;实验目的:熟悉DS18B20的使用;六位数码管显示温度结果,其中整数部分2位,小数部分4位;每次按下RB0键后进行一次温度转换。
;硬件要求:把DS18B20插在18B20插座上; 拨码开关S10第1位置ON,其他位置OFF; 拨码开关S5、S6全部置ON,其他拨码开关全部置OFF;*****************以下是暂存器的定义*****************************#INCLUDE#DEFINE DQ PORTA,0 ;18B20数据口__CONFIG_DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF &_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS _OSC CBLOCK 20HDQ_DELAY1DQ_DELAY2TEMPTEMP1TEMP2 ;存放采样到的温度值TEMP3COUNTCOUNT1ENDCTMR0_VALUE EQU 0AH ;寄存器初值为6,预分频比1:4,中断一次时间为4*(256-6)=1000usDQ_DELAY_VALUE1 EQU 0FAHDQ_DELAY_VALUE2 EQU 4H;**********************以下是程序的开始************************ ORG 00HNOPGOTO MAIN ;入口地址ORG 04HRETFIE ;在中断入口出放置一条中断返回指令,防止干扰产生中断TABLEADDWF PCL,1RETLW 0C0H ;0的编码(公阳极数码管)RETLW 0F9H ;1的编码RETLW 0A4H ;2的编码RETLW 0B0H ;3的编码RETLW 99H ;4的编码RETLW 92H ;5的编码RETLW 082H ;6RETLW 0F8H ;7RETLW 080H ;8RETLW 090H ;9;***************************主程序******************************* MAINCLRF PORTACLRF PORTBBANKSEL TRISACLRF TRISA ;A口所有先设置为输出CLRF TRISDMOVLW 01HMOVWF TRISB ;B0口为输入,其他为输出MOVLW 06HMOVWF ADCON1 ;关闭所有A/D口MOVLW 01HMOVWF OPTION_REG ;分频比1:4,定时器,内部时钟源BCF STATUS,RP0CLRF TEMPCLRF TEMP1CLRF TEMP2 ;清零临时寄存器MOVLW 8HMOVWF COUNTMOVLW 38HMOVWF FSRCLRF INDFINCF FSR,1DECFSZ COUNT,1GOTO $-3;****************************循环处理部分************************;先启动18B20温度转换程序,在判断温度转换是否完成(需750us);未完成则调用显示子程序,直到完成温度转换;完成后读取温度值;送LCD显示LOOPBTFSC PORTB,0 ;判断温度转换按键是否按下GOTO LOOP1 ;否,转显示CALL DELAY ;消抖BTFSC PORTB,0 ;再次判断GOTO LOOP1CALL RESET_18B20 ;调用复位18B20子程序MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 44HMOVWF TEMPCALL WRITE_18B20 ;温度转换命令CLRF STATUSCALL DELAY_750MS ;调用温度转换所需要的750MS延时NOPCALL RESET_18B20MOVLW 0CCHMOVWF TEMPCALL WRITE_18B20 ;SKIP ROM命令MOVLW 0BEHMOVWF TEMPCALL WRITE_18B20 ;读温度命令CALL READ_18B20 ;调用读温度低字节MOVFW TEMPMOVWF TEMP1 ;保存到TEMP1CALL READ_18B20 ;调用读温度高字节MOVFW TEMPMOVWF TEMP2 ;保存到TMEP2CALL RESET_18B20LOOP1CALL TEMP_CHANGE ;调用温度转换程序CALL DISPLAY ;调用LCD显示程序GOTO LOOP ;循环工作;*********************复位DS18B20子程序************************** RESET_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;主控制器把总线拉低至少480us,;18B20等待15-60us后,把总线拉低做为返回给控制器的应答信号BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF DQMOVLW 0A0HMOVWF COUNT ;160USDECFSZ COUNT,1GOTO $-1 ;拉低480usBSF DQ ;释放总线MOVLW 14HMOVWF COUNTDECFSZ COUNT,1GOTO $-1 ;等待60usBANKSEL TRISABSF TRISA,0 ;DQ设置为输入BCF STATUS,RP0BTFSC DQ ;数据线是否为低GOTO RESET_18B20 ;否则继续复位MOVLW 4HMOVWF COUNTDECFSZ COUNT,1 ;延时一段时间后再次判断GOTO $-1BTFSC DQGOTO RESET_18B20MOVLW 4BHMOVWF COUNTDECFSZ COUNT,1GOTO $-1BANKSEL TRISABCF TRISA,0 ;DQ设置为输出BCF STATUS,RP0RETURN;*********************写DS18B20子程序**************************** WRITE_18B20;根据DATASHEET介绍,写数据时应遵照如下规定:;写数据0时,主控制器把总线拉低至少60us;写数据1时,主控制器把总线拉低,但必须在15us内释放MOVLW 8HMOVWF COUNT ;8位数据BANKSEL TRISABCF TRISA,0BCF STATUS,RP0BCF STATUS,CWRITE_18B20_1BSF DQ ;先保持DQ为高MOVLW 5HMOVWF COUNT1BCF DQ ;拉低DQ15usDECFSZ COUNT1,1GOTO $-1RRF TEMP,1BTFSS STATUS,C ;判断写的数据为0还是1GOTO WRITE_0BSF DQ ;为1,立即拉高数据线GOTO WRITE_ENDWRITE_0BCF DQ ;继续保持数据线为低WRITE_ENDMOVLW 0FHMOVWF COUNT1 ;保持45msDECFSZ COUNT1,1GOTO $-1BSF DQ ;释放总线DECFSZ COUNT,1 ;是否写完8位数据GOTO WRITE_18B20_1RETURN;**********************读DS18B20子程序**************************** READ_18B20;根据DATASHEET介绍,读数据时应遵照如下规定:;读数据0时,主控制器把总线拉低后,18B20再把总线拉低60us ;读数据1时,主控制器把总线拉低后,保持总线状态不变;主控制器在数据线拉低后15us内读区数据线上的状态。
#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();}}。
#include "reg51.H"#include "stdio.h"#include "intrins.h"sbit DQ=P1^4; //接18B20的数据口#define uchar unsigned char#define uint unsigned intuint temp; //温度值variable of temperature/*****************DS18B20******************/void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command{DQ = 0; //单片机拉低总线delay10us(60); //精确延时,维持至少480usDQ = 1; //释放总线,即拉高了总线delay10us(20); //此处延时有足够,确保能让DS18B20发出存在脉冲。
}uchar Read_One_Byte() //读取一个字节的数据read a byte date//读数据时,数据以字节的最低有效位先从总线移出{uchar i = 0;uchar dat = 0;for(i=8;i>0;i--){DQ = 0; //将总线拉低,要在1us之后释放总线//单片机要在此下降沿后的15us内读数据才会有效。
_nop_(); //至少维持了1us,表示读时序开始dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。
DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上delay10us(2); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分if(DQ) //控制器进行采样{dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0}delay10us(4); //此延时不能少,确保读时序的长度60us。
c语言程序单总线接6个DS18B20(其实程序只要多余3个即可),。
//将DQ与Vcc之间接入4.7K上拉电阻#include "reg52.h"#include "INTRINS.H"#include "1602.c"#define uchar unsigned char#define uint unsigned int//#define CLEARSCREEN LCD_en_command(0x01) 1602清屏sbit DQ="P1"^0;/*操作命令代码跳过ROM 0xCC发送温度转换0xBE写EEPROM 0x4E*//////////////低层驱动子程序///////////void Init18B20(void); //初始化void Write18B20(uchar ch);//写数据unsigned char Read18B20(void);//读数据void Delay15(uchar n);void Delay10ms(uint delay_num);void Display(void);/////////////////////////////////////code uchar decimalH[]={00,06,12,18,25,31,37,43,50,56,62,68,75,81,87,93}; code uchar decimalL[]={00,25,50,75,00,25,50,75,00,25,50,75,00,25,50,75};uint ResultTemperatureH ,ResultTemperatureLH,ResultTemperatureLL;//整数,小数高位,小数低位uint ResultSignal;//符号位main(){ uint TemH,TemL,delay,k=0;for(; ; ){Init18B20();Write18B20(0xCC);//跳过ROM_nop_();//Write18B20(0x4E);//写EEPROM// Write18B20(0x00);//Th//Write18B20(0x00);//TlWrite18B20(0x7f);//12 bits温度分辨率Init18B20();Write18B20(0xCC);//跳过ROM_nop_();Write18B20(0x44);//发送温度转换指令Delay10ms(25);Delay10ms(25);Delay10ms(25);Delay10ms(25);//等待1s转换Init18B20();Write18B20(0xCC);//跳过ROMWrite18B20(0xBE);//发送温度转换指令TemL="Read18B20"(); //读低位温度值TemH="Read18B20"(); //读高位温度值Delay10ms(2);TemH=(TemH<<4)|(TemL>>4);TemL="TemL"&0x0f; //取低4位if(TemH&0x80){ TemH=~TemH;TemL=~TemL+1;ResultSignal="1"; //负}else ResultSignal="0"; //正ResultTemperatureLH="decimalH"[TemL];ResultTemperatureLL="decimalL"[TemL];ResultTemperatureH="TemH";Display();for(delay=0;delay<60000;delay++);for(delay=0;delay<20000;delay++);}}void Display(void){ uint i,j,q;LCD_init();CLEARSCREEN;LCD_en_command(0x01);delay_nms(2);q="ResultTemperatureH/100";i=(ResultTemperatureH%100)/10;j="ResultTemperatureH-"(i*10+q*100);LCD_write_string(0,LINE1," Jaq1217 18B20 "); if(ResultSignal){ LCD_write_string(0,LINE2," T is:- . "); }else {LCD_write_string(0,LINE2," T is:+ . ");}LCD_write_char(0x07,LINE2,q|0x30);LCD_write_char(0x08,LINE2,i|0x30);LCD_write_char(0x09,LINE2,j|0x30);LCD_write_char(0x0b,LINE2,(ResultTemperatureLH/10)|0x30); LCD_write_char(0x0c,LINE2,(ResultTemperatureLH%10)|0x30); LCD_write_char(0x0d,LINE2,(ResultTemperatureLL/10)|0x30); LCD_write_char(0x0e,LINE2,(ResultTemperatureLL%10)|0x30);}unsigned char Read18B20(void){ unsigned char ch;unsigned char q ;for(q=0;q<8;q++){ch=ch>>1;DQ="0";_nop_();DQ="1";_nop_();_nop_();_nop_();_nop_();if(DQ==1){ch="ch|0x80";}else {ch="ch"&0x7f;}Delay15(3);DQ="1";}return (ch);}void Write18B20(uchar ch){ uchar i;for(i=0;i<8;i++){ DQ="0";Delay15(1);DQ="ch"&0x01;Delay15(3);DQ="1";ch="ch">>1;_nop_();}}void Init18B20(void){ DQ="0";Delay15(33);//至少延时480usDQ="1";Delay15(10);//至少延时100us/*if(DQ==1) return 0; //初始化失败else return 1;DQ=1; Delay15(18); */}void Delay15(uchar n){ do{ _nop_(); _nop_(); _nop_(); _nop_(); _nop_();_nop_(); _nop_(); _nop_(); _nop_(); _nop_();_nop_(); _nop_(); _nop_();n--;}while(n);}void Delay10ms(uint delay_num){uchar i;while(delay_num--){for(i=0;i<125;i++){;}}}说明:如果你只需要温度部分的,那么LCD部分的,你可以不看,只参考18B20的程序段。
1.单DS18B20温度读取#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P1^4; //数据线端口void delayms(uint x) //延时函数{uchar j;while(x--){for(j=0;j<123;j++){;}}}//ROM操作命令#define READ_ROM 0x33 //读ROM#define SKIP_ROM 0xCC //跳过ROM#define MATCH_ROM 0x55 //匹配ROM#define SEARCH_ROM 0xF0 //搜索ROM#define ALARM_SEARCH 0xEC //告警搜索//存储器操作命令#define ANEW_MOVE 0xB8 //重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换#define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器//数据存储结构typedef struct tagTempData{unsigned char btThird; //百位数据unsigned char btSecond; //十位数据unsigned char btFirst; //个位数据unsigned char btDecimal; //小数点后一位数据unsigned char btNegative; //是否为负数}TEMPDATA;void Delay16us() //延时16us子函数{unsigned char a;for (a = 0; a < 4; a++);}void Delay60us() //延时60us子函数{unsigned char a;for (a = 0; a < 18; a++);}void Delay480us() //延时480us子函数{unsigned char a;for (a = 0; a < 158; a++);}void Delay240us() //延时240us子函数{unsigned char a;for (a = 0; a < 78; a++);}void Initialization() //芯片初始化{while(1) //无限循环知道收到了存在脉冲(即DS18B20的应答脉冲){DQ = 0;Delay480us(); //延时480us 复位单总线至少480us的低电平信号DQ = 1;Delay60us(); //延时60us 在复位电平结束后将数据总线拉高,以便在15~60us后接收存在脉冲if(~DQ) //收到ds18b20的应答信号{DQ = 1;Delay240us(); //延时240us 存在脉冲为一个60~240us的低电平信号break;}}}void WriteByte(unsigned char btData) //写ROM(从低位开始写) {unsigned char i, btBuffer;for (i = 0; i < 8; i++){btBuffer = btData >> i; //最低位移出if (btBuffer & 1){DQ = 0;_nop_(); //延时1个机器周期_nop_();DQ = 1;Delay60us(); //延时60us}else{DQ = 0;Delay60us();DQ = 1;}}}unsigned char ReadByte() //读ROM(从低位开始读) {unsigned char i, btDest;for (i = 0; i < 8; i++){btDest >>= 1;DQ = 0;_nop_();_nop_();DQ = 1;Delay16us();if (DQ) btDest |= 0x80;Delay60us();}return btDest;}//读取温度值TEMPDATA ReadTemperature(){TEMPDATA TempData; //定义储存结构用于存储温度的值unsigned int iTempDataH;unsigned char btDot, iTempDataL;TempData.btNegative = 0; //为0温度为正Initialization();WriteByte(SKIP_ROM); //跳过ROM匹配WriteByte(TEMP_SWITCH); //启动温度转换delayms(1); //温度转换需要时间500usInitialization();WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)WriteByte(READ_MEMORY); //读暂存储存数据iTempDataL = ReadByte(); //读取温度的低8位iTempDataH = ReadByte(); //读取温度的高8位iTempDataH <<= 8;iTempDataH |= iTempDataL;if (iTempDataH & 0x8000) //判断温度的值是否为负数{TempData.btNegative = 1; //负数标志iTempDataH = ~iTempDataH + 1; //负数求补}btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分iTempDataH >>= 4; //得到整数部分btDot *= 5; //btDot*10/16得到转换后的小数数据btDot >>= 3;//数据处理TempData.btThird = (unsigned char)iTempDataH /100; //整数部分的百位TempData.btSecond = (unsigned char)iTempDataH % 100/10;//整数部分的十位TempData.btFirst = (unsigned char)iTempDataH % 10; //整数部分的个位TempData.btDecimal = btDot; //小数点后的一位return TempData; //函数返回温度值的存储结构体}2.多个DS18B20单总线温度读取#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P2^7; //数据线端口unsigned char channel,n=0;void delayms(uint x) //延时函数{uchar j;while(x--){for(j=0;j<123;j++){;}}}//ROM操作命令#define READ_ROM 0x33 //读ROM#define SKIP_ROM 0xCC //跳过ROM #define MATCH_ROM 0x55 //匹配ROM #define SEARCH_ROM 0xF0 //搜索ROM//存储器操作命令#define ANEW_MOVE 0xB8//重新调出E^2数据#define READ_POWER 0xB4 //读电源#define TEMP_SWITCH 0x44 //启动温度变换#define READ_MEMORY 0xBE //读暂存存储器#define COPY_MEMORY 0x48 //复制暂存存储器#define WRITE_MEMORY 0x4E //写暂存存储器//数据存储结构typedef struct tagTempData{unsigned char btThird; //百位数据unsigned char btSecond; //十位数据unsigned char btFirst; //个位数据unsigned char btDecimal; //小数点后一位数据unsigned char btNegative; //是否为负数}TEMPDATA;//DS18B20序列号const unsigned char code ROMData1[8] = {0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7}; //U1const unsigned char code ROMData2[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E}; //U2const unsigned char code ROMData3[8] = {0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9}; //U3const unsigned char code ROMData4[8] = {0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0}; //U4const unsigned char code ROMData5[8] = {0x28, 0x34, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x52}; //U5const unsigned char code ROMData6[8] = {0x28, 0x35, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x65}; //U6const unsigned char code ROMData7[8] = {0x28, 0x36, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x3C}; //U7const unsigned char code ROMData8[8] = {0x28, 0x37, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x0B}; //U8void Delay16us() //延时16us子函数{unsigned char a;for (a = 0; a < 4; a++);}void Delay60us() //延时60us子函数{unsigned char a;for (a = 0; a < 18; a++);}void Delay480us() //延时480us子函数{unsigned char a;for (a = 0; a < 158; a++);}void Delay240us() //延时240us子函数{unsigned char a;for (a = 0; a < 78; a++);}void Initialization() //芯片初始化{while(1) //无限循环知道收到了存在脉冲(即DS18B20的应答脉冲){DQ = 0;Delay480us(); //延时480us 复位单总线至少480us的低电平信号DQ = 1;Delay60us(); //延时60us 在复位电平结束后将数据总线拉高,以便在15~60us后接收存在脉冲if(!DQ) //收到ds18b20的应答信号{DQ = 1;Delay240us(); //延时240us 存在脉冲为一个60~240us的低电平信号break;}}}void WriteByte(unsigned char btData) //写ROM(从低位开始写) {unsigned char i, btBuffer;for (i = 0; i < 8; i++){btBuffer = btData >> i; //最低位移出if (btBuffer & 1){_nop_(); //延时1个机器周期_nop_();DQ = 1;Delay60us(); //延时60us}else{DQ = 0;Delay60us();DQ = 1;}}}unsigned char ReadByte() //读ROM(从低位开始读) {unsigned char i, btDest;for (i = 0; i < 8; i++){DQ = 0;_nop_();_nop_();DQ = 1;Delay16us();if (DQ) btDest |= 0x80;Delay60us();}return btDest;}//序列号匹配void MatchROM(const unsigned char *pMatchData) {unsigned char i;Initialization(); //芯片初始化WriteByte(MATCH_ROM); //写入匹配ROM指令for (i = 0; i < 8; i++) WriteByte(*(pMatchData + i)); }//读取温度值TEMPDATA ReadTemperature(){TEMPDATA TempData; //定义储存结构用于存储温度的值unsigned int iTempDataH;unsigned char btDot, iTempDataL;static unsigned char i = 0;TempData.btNegative = 0; //为0温度为正i++;if (i == 9) i = 1;channel=i;Initialization();WriteByte(SKIP_ROM); //跳过ROM匹配WriteByte(TEMP_SWITCH); //启动温度转换if(n==0)delayms(1000); //温度转换需要时间500msn++;if(n==8)n=1;delayms(1);Initialization();//多个芯片的时候用MatchROM(ROMData)换掉WriteByte(SKIP_ROM)switch (i){case 1 : MatchROM(ROMData1); break; //匹配1case 2 : MatchROM(ROMData2); break; //匹配2case 3 : MatchROM(ROMData3); break; //匹配3case 4 : MatchROM(ROMData4); break; //匹配4case 5 : MatchROM(ROMData5); break; //匹配5case 6 : MatchROM(ROMData6); break; //匹配6case 7 : MatchROM(ROMData7); break; //匹配7case 8 : MatchROM(ROMData8); break; //匹配8 }//WriteByte(SKIP_ROM); //跳过ROM匹配(单个芯片时用这句换掉上面的switch)WriteByte(READ_MEMORY); //读暂存储存数据iTempDataL = ReadByte(); //读取温度的低8位iTempDataH = ReadByte(); //读取温度的高8位iTempDataH <<= 8;iTempDataH |= iTempDataL;if (iTempDataH & 0x8000) //判断温度的值是否为负数{TempData.btNegative = 1; //负数标志iTempDataH = ~iTempDataH + 1; //负数求补}btDot = (unsigned char)(iTempDataH & 0x000F); //得到小数部分iTempDataH >>= 4; //得到整数部分btDot *= 5; //btDot*10/16得到转换后的小数数据btDot >>= 3;//数据处理TempData.btThird = (unsigned char)iTempDataH / 100;//整数部分的百位TempData.btSecond = (unsigned char)iTempDataH % 100 / 10;//整数部分的十位TempData.btFirst = (unsigned char)iTempDataH % 10;//整数部分的个位TempData.btDecimal = btDot; //小数点后的一位return TempData; //函数返回温度值的存储结构体}3. DS18B20的序列号读取程序<用LCD1602显示序列号>#include<reg52.h>#include<LCD1602.h>#include<string.h>#define uchar unsigned char#define uint unsigned intuchar sn[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10};uchar t;uchart01,t02,t11,t12,t21,t22,t31,t32,t41,t42,t51,t52,t61,t62,t71,t72;sbit DQ=P2^7;//ds18b20与单片机连接口void delay1ms(unsigned int ms)// 延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void delay_18B20(unsigned int i)// 延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{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_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}////////////////////////读取器件序列号子程序////////////////////////////void rom(void){ds1820rst(); //复位//delay1ms(1); //延时//ds1820wr(0x33); //发送读序列号子程序//sn[0]=ds1820rd(); //连续读出64位ROM t01=sn[0]/16;t02=sn[0]%16; //转为16进制sn[1]=ds1820rd(); //t11=sn[1]/16;t12=sn[1]%16; //转为16进制sn[2]=ds1820rd(); //t21=sn[2]/16;t22=sn[2]%16; //转为16进制sn[3]=ds1820rd(); //t31=sn[3]/16;t32=sn[3]%16; //转为16进制sn[4]=ds1820rd(); //t41=sn[4]/16;t42=sn[4]%16; //转为16进制sn[5]=ds1820rd(); //t51=sn[5]/16;t52=sn[5]%16; //转为16进制sn[6]=ds1820rd(); //t61=sn[6]/16;t62=sn[6]%16; //转为16进制sn[7]=ds1820rd(); //t71=sn[7]/16;t72=sn[7]%16; //转为16进制}void chuan(uchar i,uchar j,uchar x) {if(x<10)DisplayOne(i,j,x,1);if(x==10)DisplayOne(i,j,'A',0);if(x==11)DisplayOne(i,j,'B',0);if(x==12)DisplayOne(i,j,'C',0);if(x==13)DisplayOne(i,j,'D',0);if(x==14)DisplayOne(i,j,'E',0);if(x==15)DisplayOne(i,j,'F',0);}void Displaychar(){chuan(0,0,t01);chuan(0,1,t02);chuan(0,4,t11);chuan(0,5,t12);chuan(0,8,t21);chuan(0,9,t22);chuan(0,12,t31);chuan(0,13,t32);chuan(1,0,t41);chuan(1,1,t42);chuan(1,4,t51);chuan(1,5,t52);chuan(1,8,t61);chuan(1,9,t62);chuan(1,12,t71);chuan(1,13,t72);}/********************主程序***********************************/void main(){Clear();Init();while(1){rom(); //调用读序列号子程序//Displaychar();}}。