DS18B20温度转换程序
- 格式:docx
- 大小:21.19 KB
- 文档页数:14
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。
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内读区数据线上的状态。
#include<reg51.H>#include<absacc.H>#include <intrins.h>#include<stdio.h>#define uchar unsigned char#define uint unsigned intuchar code TAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar code TAB1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; sbit DQ=P3^3;void delay(uint i){while(i--);}void DelayMS(uint ms){uchar i;while(ms--) for(i=0;i<120;i++);}void display(int k)//数码管显示{P2=0x08;P0=TAB[k%10];DelayMS(5);P2=0x04;P0=TAB[k/10%10];DelayMS(5);P2=0x02;P0=TAB1[k/100%10];DelayMS(5);P2=0x01;P0=TAB[k/1000];DelayMS(5);}init_DS(void){uchar x=0;DQ=1;delay(8);DQ=0;delay(85);DQ=1;delay(14);x=DQ;delay(20);}Read(void){uchar i=0;uchar dat=0;for(i=8;i>0;i--){//DQ=1;//delay(1);DQ=0;dat>>=1;DQ=1;if(DQ)dat|=0x80;//读出数据放入高位,最后右移到低位delay(4);}return(dat);}write(uchar dat){uchar i=0;for(i=8;i>0;i--){DQ=0;DQ=dat&0x01;//从地位开始写入delay(5);DQ=1;dat>>=1;}delay(4);}Readtem(void){ uchar a=0;uchar b=0;uchar t=0,t1;init_DS();write(0xcc);//跳过读序列号操作write(0x44);//启动温度转换delay(125);init_DS();write(0xcc);write(0xbe);// 读温度寄存器a=Read();//读取温度低位LSBb=Read();//读取温度低位HSBt1=(a&0x0f)*0.0625;//取小数部分t=((b<<4)|(a>>4));//取整数部分if(t>128){t=~t+1;}t=t+t1;return(t);}void main(){float tp;while(1){tp=Readtem();tp=tp*100;//把二位数乘以100变成四位数display(tp);}}。
;单片机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温度传感器程序#include "DS18B20.h"uchar TMPL,TMPH;sbit DQ=P2^3;uchar DS18B20_Reset(){uchar x;DQ=1 ; //数据线拉高DQ=0; //数据线拉低Delay_700us(); //延时480us-960usDQ=1; //数据线拉低Delay_30us(); //延时15us-60usx=DQ; //读取此时数据线的值while(!DQ); //直到DQ为高return x; //返回复位结果}uchar DS18B20_readbit(){ bit x ;uchar i;DQ=1; //数据线拉高i++; //延时2微秒DQ=0; //数据线拉低Delay_6us(); //延时6微秒DQ=1; //数据线拉高i++;i++; //延时4微秒x=DQ; //读数据线状态Delay_50us();//延时50微秒return (x); //返回数值void DS18B20_writebit(uchar aa){ uchar i;DQ=1; //将数据线拉高i++; //延时大于1微秒DQ=0; //将数据线拉低i++; //延时大于1微秒DQ=aa; //写入数据Delay_50us(); //延时使写周期在60-120微秒之间DQ=1;}uchar DS18B20_readbyte(){uchar i,j,dat;dat=0;j=1;for(i=0;i<8;i++){if(DS18B20_readbit()){dat=dat+(j<<i);}}return (dat);}void DS18B20_writebyte(uchar dat){uint temp;uchar j;for(j=0;j<8;j++)temp=dat>>j;temp=temp&0x01;DS18B20_writebit(temp) ;}}bit DS18B20_readpower(){bit x;while(DS18B20_Reset()); //复位,通信前必须复位DS18B20_writebyte(0xcc);DS18B20_writebyte(0xb4); //读供电方式命令x=DQ;Delay_10us();return x;}void DS18B20_SetResolution(unsigned char res) {switch (res){case 9:res=0;break;case 10:res=1;break;case 11:res=2;break;case 12:res=3;break;}while(DS18B20_Reset()); //复位,通信前必须复位DS18B20_writebyte(0x4e); //写暂存器指令DS18B20_writebyte(0xff); //此值被写入THDS18B20_writebyte(0xff); //此值被写入TLDS18B20_writebyte(0x1f|(res<<5)); //设置精度0 res[1-0] 11111}long DS18B20_GetTemperature(){ long wendu;while(DS18B20_Reset());DS18B20_writebyte(0xcc);//跳过ROMDS18B20_writebyte(0x44);//温度转换while(DS18B20_Reset());DS18B20_writebyte(0xcc);//跳过ROMDS18B20_writebyte(0xbe);//读暂存器TMPL=DS18B20_readbyte();TMPH=DS18B20_readbyte();wendu=TMPH<<8|TMPL;wendu=wendu*0.0625;return wendu;}DS18B20.H#ifndef _DS18B20_H_#define _DS18B20_H_#include "delay.h"#include#define uchar unsigned char#define uint unsigned intuchar DS18B20_Reset();uchar DS18B20_readbit();void DS18B20_writebit(uchar aa);uchar DS18B20_readbyte();void DS18B20_writebyte(uchar dat);bit DS18B20_readpower();void DS18B20_SetResolution(unsigned char res); long DS18B20_GetTemperature();#endif</i);。
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();}}。
主程序ORG 0000HLJMP STARTSTART: MOV DISBUF4,#00H ;开始,初始化MOV DISBUF5, #00HMAIN: ;主程序LCAAL KEY ;调按键预置数子程序CLR RS1CLR RS0LCALL RESET ;调复位子程序MOV A,#0CCH ;跳过ROM匹配------0CCLCALL WRITE ;调DS18B20子程序MOV A,#44H ;发出温度转换命令LCALL WRITE ;调DS18B20子程序LCALL RESET ;调复位子程序MOV A,#0CCH ;跳过ROM匹配LCALL WRITE ;调DS18B20子程序MOV A,#0BEH ;发出读取温度值命令LCALL WRITE ;调DS18B20子程序LCALL READ ;调DS18B20子程序MOV A, 3DHMOV 29H,ALCALL READMOV A, 3DHMOV 28H,AMOV R0, #34HMOV A, 28HRLC AMOV 47H,CJNB 47H, BTOD1 ;28H中的最高位是不是为1(温度<0);小于0的温度值不处置,大于0顺序执行BTOD1: MOV A, 28HRRC AMOV 40H,CRRC AMOV 41H,CRRC AMOV 42H,CRRC AMOV 43H,CMOV A, 29HMOV 27H, AMOV C,40H ;将28H中的最低位移入C,40H41H42H43H ;为28H中的位地址RRC A ;将28H中的低4位移到A的高4位MOV C, 41HRRC AMOV C, 42HRRC AMOV C, 43HRRC AMOV 29H,A ;将28H中的低4位放入29H中MOV A, 29H ;将29H中的十六进制数转换成10进制MOV B, #100DIV ABMOV @R0, A ;百位存于34HMOV @R0, #11H ;百位不显示DEC R0MOV A, #10XCH A, BDIV ABMOV @R0, A ;十位存于33HDEC R0MOV @R0, B ;个位存于32HDEC R0ANL 27H, #0FH ;小数点后一名进制转换MOV A, 27HMOV B, #06HMUL ABMOV B, #10DIV ABMOV @R0, A ;小数点后一名存于31HMOV DISBUF0,33H ;十位MOV DISBUF1,32H ;个位MOV DISBUF2,31H ;小数位MOV DISBUF3, #0H ;置0MOV DISBUF6, #0HMOV DISBUF7, #0HLCALL CMP ;调比较报警子程序LCALL DISPLAY ;调显示子程序LJMP MAIN ;转到MAINDS18B20复位子程序RESET: NOPL0: CLR ;拉低数据线MOV R2,#200 ;发出600us的复位脉冲L1: NOPDJNZ R2, L1SETB ;主机释放数据线MOV R2,#30 ;DS18B20等待60usL4: DJNZ R2, L4CLR CORL C, ;DS18B20数据变低(存在脉冲)吗?JC L3 ;DS18B20未预备好,从头初始化MOV R6, #80L5: ORL C,JC L3 ;DS18B20数据变高,初始化成功DJNZ R6,L5 ;数据线低电平可持续3us*80=240us SJMP L0 ;初始化失败,从头初始化L3: MOV R2, #250L2: DJNZ R2,L2 ;DS18B20应答500usRET读DS18B20子程序READ: MOV R6,#8 ;循环8次,读一个字节RE1: CLRMOV R4, #6NOPNOPSETBRE2: DJNZ R4,RE2 ;等待8USMOV C, ;读DS18B20的数据RRC A ;读取的数据移入AMOV R5, #30DJNZ R6,RE1 ;读完一个字节的数据MOV 3DH,A ;数据存入3DH中SETB ;把数据线拉高RET写DS18B20子程序;写DS18B20的子程序, 从DS18B20中写出一个字节的数据WRITE: MOV R3,#8 ;循环8次,写一个字节WR1: SETB ;拉高数据线MOV R4, #8RRC A ;写入位从A中移到CYCLRWR2: DJNZ R4,WR2 ;等待16USMOV ,C ;命令字按位依次送给DS18B20MOV R4, #20WR3: DJNZ R4,WR3 ;保证写进程持续40USDJNZ R3,WR1 ;未写完一个字节转WR1继续SETB ;写完一个字节,数据线置高RET比较报警子程序CMP: MOV A,DISBUF0 ;实际测量温度值放在DISBUF8中SWAP AMOV DISBUF8, AMOV A, DISBUF1ORL A, DISBUF8MOV DISBUF8, AMOV A,DISBUF4 ;预置温度值放在DISBUF9中SWAP AMOV DISBUF9, AMOV A, DISBUF5ORL A, DISBUF9MOV DISBUF9, ACLR CMOV A, DISBUF8SUBB A, DISBUF9JNC KK ;没有借位,即实际温度值大于;预置温度值转KKCLR ;有借位,即实际温度值小于预置温度值;置0,不发报警信号RETKK: SETB ;置1,即发出报警标志发光二极管亮RET按键子程序KEY: JNB , YZBWJNB , YZSWLJMP KEYRET YZBW: LCALL DELAY1JB , KEYRETJNB , $INC DISBUF5MOV A, DISBUF4CJNE A, #10,KEYRETMOV DISBUF4, #0LJMP KEYRETYZSW: LCALL DELAY1JB , KEYRETJNB , $INC DISBUF5MOV A, DISBUF5CJNE A, #10,KEYRETMOV DISBUF5, #0 KEYRET: RET显示子程序DISPLAY: MOV A, DISBUF0MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00000001BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF1MOV DPTR, #SEGMOVC A, @A+DPTRORL A, #80HMOV P1, AMOV P2, #00000010BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF2MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00000100BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF3MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00001000BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF4MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00010000BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF5MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00100000BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF6MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00000000BLCALL DELAY1MOV P2, #00000000BMOV A, DISBUF7MOV DPTR, #SEGMOVC A, @A+DPTRMOV P1, AMOV P2, #00000000BLCALL DELAY1MOV P2, #00000000BRET; (00) (01) (02) (03) (04)SEG: DB 03FH, 06H, 05BH, 04FH, 066H ; (05) (06) (07) (08) (09)DB 06DH, 07DH, 007H, 07FH, 06FH ;延时子程序DELAY1: MOV R1, #0A0HDEL11: NOPDJNZ R1, DEL11RETEND;工作内存概念:DISBUF0 EQU 10H DISBUF1 EQU 11H DISBUF2 EQU DISBUF1+1 DISBUF3 EQU DISBUF2+1 DISBUF4 EQU DISBUF3+1 DISBUF5 EQU DISBUF4+1 DISBUF6 EQU DISBUF5+1 DISBUF7 EQU DISBUF6+1 DISBUF8 EQU DISBUF7+1 DISBUF9 EQU DISBUF8+1。
基于DS18B20温度显示仪--------程序#include <reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar BCD_7[12] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00} ; sbit DS18B20=P2^0 ;void saomiao( uint k );void Delay_ms(uchar t){uint i;for(;t>0;t--)for(i=0;i<124;i++);}uint d[4];uchar temp;void delay500us(unsigned int t){ unsigned int i;for(;t>0;t--)for(i=0;i<59;i++);}//--------------------------------------------------------------------------------void delay60us(void){ unsigned char i;for(i=0;i<18;i++);}//---------------------------------------------------------------------------------unsigned char Ds18b20_start () //返回0,总线上DS18B20{ unsigned char flag; //定义初始化成功或失败标志DS18B20=0; //总线产生下降沿,初始化开始delay500us(1); //总线保持低电平在480 - 960微秒之间DS18B20=1; //总线拉高,准备接收DS18B20的应答脉冲delay60us (); //读应答等待_nop_();_nop_();flag= DS18B20;while(!DS18B20);//等待复位成功return(flag);}//---------------------------------------------------------------------------------void ds18_send(unsigned char i) //向DS18B20写一字节函数{ unsigned char j=8; //设置读取的位数,一字节8位for(;j>0;j--){DS18B20=0; //总线拉低,启动"写时间片"_nop_();_nop_(); //大于1微妙if(i&0x01)DS18B20=1;delay60us (); //延时至少60微秒,使写入有效_nop_();_nop_();DS18B20=1; //准备启动下一个"写时间片"i>>=1;}}//---------------------------------------------------------------------------------unsigned char ds18_readChar() //从DS18B20读1个字节函数{unsigned char i=0,j=8;for(;j>0;j--){DS18B20=0; //总线拉低,启动读"时间片"_nop_();_nop_(); //大于1微妙DS18B20=1; //总线拉高,准备读取i>>=1;if(DS18B20)i|=0x80; //从总线拉低时算起,约15微秒后读取总线数据delay60us (); //延时至少60微秒_nop_();_nop_();}return(i);}//--------------------------------------------------------------------------------void Init_Ds18B20(void) //初始化DS18B20{if(Ds18b20_start()==0) //复位{ ds18_send (0xcc); //跳过ROM匹配ds18_send (0x4e); //设置写模式ds18_send (0x64); //设置温度上限100摄氏度ds18_send (0x8a); //设置温度下线-10摄氏度ds18_send (0x7f); //12bit(默认)}}//---------------------------------------------------------------------------------unsigned int Read_ds18b20(){unsigned char th,tl;if(Ds18b20_start ()) // Ds18b20_start ()为初始化函数return(0); //初始化失败,DS18B20出故障,返回ds18_send(0xcc); //发跳过序列号检测命令ds18_send(0x44); //发启动温度转换命令delay500us (5); //延时200ms等待转换完成。
//温度高于26摄氏度则蜂鸣器响#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charsbitdula=P2^6;sbitwela=P2^7;sbit beer=P2^3; //控制蜂鸣器sbitdsb=P2^2; //ds18b20的数据总线sbitrs=P3^5; //液晶显示数据命令选择端口sbitlcme=P3^4; //液晶显示使能信号sbit key=P3^7;uint temp; //温度传感器测得的温度uchar code listone[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};ucharcodelisttwo[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; ucharcodelistthree[]={"The temp is under:"};void delay(uchari){while(--i);}Voiddelayone(uint z){uintx,y;for(x=100;x>0;x--)for(y=z;y>0;y--);}/*液晶显示写命令初始化*/ Voidwritecom(uchar com) {rs=0;delayone(2);lcme=0;P0=com;lcme=1;delayone(2);lcme=0;}/*液晶显示写数据初始化*/ void writebyte(uchar byte) {rs=1;delayone(2);lcme=0;P0=byte;lcme=1;delayone(2);lcme=0;}/*液晶显示初始化*/ void ds18b20init() {uinttempone;uinti;dula=0;wela=0;lcme=0;writecom(0x38);writecom(0x0f);writecom(0x06);writecom(0x80);for(i=0;i<16;i++){writebyte(listthree[i]);delayone(2);}writecom(0x80+0x40);for(i=0;i<16;i++){tempone=temp&0x80;writebyte(tempone);delay(2);temp<<=1;}writecom(0x0c);}/*温度传感器初始化*/ voidtempinit(){dsb=1;delay(1);dsb=0;delay(250);dsb=1;delay(100);}voidwritedata(uchardat) {uinti;for(i=0;i<8;i++){dsb=1;_nop_();dsb=0;_nop_();_nop_();dsb=dat&0x01;delay(10);dat>>=1;delay(1);}dsb=1;}ucharreaddata(){uinti;for(i=0;i<8;i++){dsb=1;_nop_();dsb=0;_nop_();_nop_();// date>>=1;dsb=1;delay(1);date>>=1; //右移放于此处也可以if(dsb==1)date|=0x80;delay(10);}return date;}uint control(){floattt;// uint temp;tempinit();writedata(0xcc);writedata(0x44);tempinit();writedata(0xcc);writedata(0xbe);a =readdata();b = readdata();temp = b;temp<<= 8;temp = temp|a;tt = temp*0.0625;temp = tt*100+0.05;return temp;}voidshuma(uint temp) {ucharbai,shi,ge,xiaoshu; bai=(temp/1000);shi=temp%1000/100; ge=temp%100/10; xiaoshu=temp%10;dula=1;P0=listone[bai];dula=0;P0=0xff;wela=1;P0=0xfe;wela=0;delayone(1);dula=1;P0=listtwo[shi];dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delayone(1);dula=1;P0=listone[ge];dula=0;P0=0xff;wela=1;P0=0xfb;wela=0;delayone(1);dula=1;P0=listone[xiaoshu];dula=0;P0=0xff;wela=1;P0=0xf7;wela=0;delay(10);}void warning(uint temp){if((temp>=2600)&&(temp<2800)&&(key==1)){beer=0;P1=0x55;delayone(4);}if((key==0)||(temp<2600)){delayone(5);if((key==0)||(temp<2600)){beer=1;P1=0xff;}}}void main(){while(1){if(temp<2600){shuma(control());}if((temp>=2600)&&(temp<2800)){shuma(control());warning(temp);}if(temp>=2800){dula=0;wela=0;P0=0xff;}}}。
数字温度传感器DS18B20摘要DS-18B20 数字温度传感器具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
应用范围广泛,适用于冷冻库,粮仓,储罐,电讯机房,电力机房,电缆线槽等测温和控制领域,轴瓦,缸体,纺机,空调,等狭小空间工业设备测温和控制和汽车空调、冰箱、冷柜、以及中低温干燥箱等。
一、引脚图DS18B20引脚定义:(1)DQ为数字信号输入/输出端;(2)GND为电源地;(3)VDD为外接供电电源输入端(在寄生电源接线方式时接地)二、DS18B20的主要特性1.1、电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电1.2、DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯1.3、多个DS18B20可以并联在唯一的三线上,实现组网多点测温1.4、DS18B20在使用中不需要任何外围元件1.5、温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃1.6、可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温1.7、在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快1.8、测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力1.9、负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
三、DS18B20的外形和内部结构DS18B20内部结构主要由四部分组成:64位光刻ROM 、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20内部结构图四、DS18B20工作原理DS18B20的温度转换时的延时时间由2s 减为750ms。
DS18B20测温原理如图3所示。
ds18b20转换为10进制如何将DS18B20温度传感器的输出值转换为10进制值DS18B20是一种数字温度传感器,它可以提供高精度的温度测量结果。
传感器输出的温度值是以16进制形式呈现的。
然而,有时候我们可能需要将其转换为10进制值,以便更好地理解和使用。
步骤一:了解DS18B20温度传感器的工作原理和数据格式在开始转换前,我们需要了解DS18B20温度传感器的工作原理和数据格式。
该传感器通过一条数字总线与主循环器连接,主循环器可以通过发送一系列的命令来获取传感器所测量的温度值。
传感器输出的温度值是一个16位的二进制数,其中10位表示整数部分,6位表示小数部分。
步骤二:读取DS18B20传感器输出的16进制值首先,我们需要读取DS18B20传感器输出的16进制值。
可以使用各种编程语言或工具来实现这一步骤。
例如,如果我们使用C语言,我们可以通过操作GPIO脚来读取传感器的输出值。
读取结果将是一个16位的二进制数。
步骤三:将16进制值转换为二进制数下一步,我们需要将读取的16进制值转换为二进制数。
这可以通过将每个十六进制数字转换为4个二进制位来完成。
例如,如果传感器输出的16进制值为0x3A5C,则它的二进制表示将是0011 1010 0101 1100。
步骤四:分离整数和小数部分根据DS18B20温度传感器的数据格式,我们需要将16位的二进制数分为整数和小数两部分。
10位二进制数表示整数部分,6位二进制数表示小数部分。
对于上述示例的二进制值,我们将前面的10位作为整数部分,后面的6位作为小数部分。
步骤五:将整数部分和小数部分转换为10进制值最后一步是将整数和小数部分分别转换为10进制值。
对于整数部分,我们可以使用任何编程语言中提供的相应方法或函数来完成转换。
然而,对于小数部分,我们需要注意到它只有6位,因此我们需要相应地计算小数部分的值。
如果将上述示例的整数部分转换为10进制数,将得到58。
对于小数部分,我们可以计算出它的十进制值。
#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charsbit DQ=P1^3;//ds18b20与单片机连接口sbit RS=P1^0;sbit RW=P1^1;sbit EN=P1^2;uchar data disdata[5];uint tvalue,CurrentT=0;//温度值uchar tflag;//温度正负标志#define LCD_BUS P0sbit SetKey = P3^0;sbit UpKey = P3^1;sbit DnKey = P3^2;sbit BEEP = P1^4;sbit Heat = P1^0;sbit Cool = P1^1;unsigned char AlarmTempLow=10,AlarmTempTop=40,Set=0,NG=0; void delayms(uint ms) //延时xx毫秒{uchar i;while(ms--){for(i=0;i<120;i++);}}void command(uint com) //LCD写指令{RS=0; //RS为0LCD_BUS=com; //装载指令delayms(5); //延时5msEN=1; //LCD使能delayms(5); //延时5msEN=0; //LCD不使能}void write_dat(uchar dat) //LCD写数据{RS=1; //RS为1LCD_BUS=dat; //装载数据delayms(5); //延时5msEN=1; //LCD使能delayms(5); //延时5msEN=0; //LCD不使能}void writestring(uchar x,uchar y,uchar *s) //LCD 写字符串{if (y == 0) command(0x80 + x); //表示第一行else command(0xC0 + x); //表示第二行while (*s) //判断是否字符串的结尾{write_dat( *s); //显示当前字符s ++; //字符串地址加1}}void writeChar(uchar x,uchar y,uchar s) //LCD 写字符串{if (y == 0) command(0x80 + x); //表示第一行else command(0xC0 + x); //表示第二行{write_dat( s); //显示当前字符}}void LCD_Initial() //LCD初始化{EN=0; //LCD不使能RW=0; //RW为0command(0x38); //发送初始化指令command(0x0c); //发送初始化指令command(0x06); //发送初始化指令command(0x01); //发送初始化指令command(0x80+0x02); //发送LCD初始位置}/*************************DS1820程序****************************/void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst(void)/*ds1820复位*/{unsigned char x=0;DQ= 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd(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_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;}}unsigned int Read_Temperature(void)/*读取温度值并转换*/ { uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff) tflag=0;else {tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数CurrentT=tvalue;return(tvalue);}void Display_Temperature() //显示温度{uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0) flagdat=0x20;//正温度不显示符号else flagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30) disdata[1]=0x20;//如果百位为0,十位为0也不显示}if(tflag==1){writeChar(10,0,flagdat);//wr_com(0x8a);wr_dat(flagdat);//显示符号位writeChar(11,0,disdata[0]);//wr_com(0x8b);wr_dat(disdata[0]);//显示百位writeChar(12,0,disdata[1]);//wr_com(0x8c);wr_dat(disdata[1]);//显示十位writeChar(13,0,disdata[2]);//wr_com(0x8d);wr_dat(disdata[2]);//显示个位writeChar(14,0,0X2E);//wr_com(0x8e);wr_dat(0x2e);//显示小数点writeChar(15,0,disdata[3]);//wr_com(0x8f); wr_dat(disdata[3]);//显示小数位}else{writeChar(10,0,disdata[0]);//wr_com(0x8a);wr_dat(disdata[0]);//显示百位writeChar(11,0,disdata[1]);//wr_com(0x8b);wr_dat(disdata[1]);//显示十位writeChar(12,0,disdata[2]);//wr_com(0x8c);wr_dat(disdata[2]);//显示个位writeChar(13,0,0X2e);//wr_com(0x8d);wr_dat(0x2e);//显示小数点writeChar(14,0,disdata[3]);//wr_com(0x8e);wr_dat(disdata[3]);//显示小数位}}void SetFun(void){unsigned char i1=0,i2=0,i3=0,i4=0,i5=0,i6=0;if(SetKey==0){delayms(20);if(SetKey==0){if(Set<2) Set++;else Set=0;}switch(Set){case 0: writestring(0,1," ");writestring(8,1," ");break; case 1: writestring(0,1,">");writestring(8,1," ");break; case 2: writestring(0,1," ");writestring(8,1,">");break; }while(SetKey==0);}if((UpKey==0)&&(Set!=0)){delayms(20);if(UpKey==0){switch(Set){case 1: if(AlarmTempLow<99) AlarmTempLow++;else AlarmTempLow=99; break;case 2: if(AlarmTempTop<99) AlarmTempTop++;else AlarmTempTop=99; break;}i1 = AlarmTempLow/100; //获得温度值的百位i2 = AlarmTempLow%100/10; //获得温度值的十位i3 = AlarmTempLow%10; //获得温度值的个位i4 = AlarmTempTop/100; //获得温度值的百位i5 = AlarmTempTop%100/10; //获得温度值的十位i6 = AlarmTempTop%10; //获得温度值的个位writestring(5,1," ");writestring(13,1," ");if(i1!=0) writeChar(5,1,i1+'0');if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');if(i1!=0) writeChar(6,1,i2+'0');if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0');else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0');if((i1!=0)) writeChar(7,1,i3+'0');if(i4!=0) writeChar(13,1,i4+'0');if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');if(i4!=0) writeChar(14,1,i5+'0');if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0');else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0');if((i4!=0)) writeChar(15,1,i6+'0');while(UpKey==0);}}if((DnKey==0)&&(Set!=0)){delayms(20);if(DnKey==0){switch(Set){case 1: if(AlarmTempLow>0) AlarmTempLow--;else AlarmTempLow=0; break;case 2: if(AlarmTempTop>0) AlarmTempTop--;else AlarmTempTop=0; break;}i1 = AlarmTempLow/100; //获得温度值的百位i2 = AlarmTempLow%100/10; //获得温度值的十位i3 = AlarmTempLow%10; //获得温度值的个位i4 = AlarmTempTop/100; //获得温度值的百位i5 = AlarmTempTop%100/10; //获得温度值的十位i6 = AlarmTempTop%10; //获得温度值的个位writestring(5,1," ");writestring(13,1," ");if(i1!=0) writeChar(5,1,i1+'0');if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');if(i1!=0) writeChar(6,1,i2+'0');if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0');else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0');if((i1!=0)) writeChar(7,1,i3+'0');if(i4!=0) writeChar(13,1,i4+'0');if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');if(i4!=0) writeChar(14,1,i5+'0');if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0');else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0');if((i4!=0)) writeChar(15,1,i6+'0');/*writeChar(4,1,i1+'0');writeChar(5,1,i2+'0');writeChar(6,1,i3+'0');writeChar(12,1,i4+'0');writeChar(13,1,i5+'0');writeChar(14,1,i6+'0');*/while(DnKey==0);}}}void Alarm(void){if((CurrentT>(AlarmTempTop*10))||(CurrentT<(AlarmTempLow*10))||( tflag==1)){BEEP=0;}else{BEEP=1;}}void main(void)unsigned char i=0;//P3=0xef;P2=0xef;P1=0x00;BEEP=1;LCD_Initial(); //LCD 初始化Read_Temperature(); //读取温度值writestring(1,0,"DS18B20 Alarmer"); //显示“DS18B20 Alarmer”delayms(1000); //延时1Swritestring(0,0,"Current T= "); //显示“Current T= ”writestring(0,1," Low=10 Top=40 "); //显示“Low=10 Top=40 ”NG=0; while(1){Read_Temperature(); // //读取温度值Display_Temperature(); //显示温度值SetFun();Alarm();if((CurrentT<(AlarmTempTop*10))&&(CurrentT>(AlarmTempLow*10))) { Cool=0;Heat=0; }else if((CurrentT>(AlarmTempTop*10))){ Cool=1;Heat=0; }else if((CurrentT<(AlarmTempLow*10))||(tflag==1)){ Cool=0;Heat=1; }}。