DS18B20温度采集程序代码
- 格式:doc
- 大小:41.00 KB
- 文档页数:4
DS18B20温度传感器实现代码平台: freescale CodeWarriorMCU:MC9S12G128(汽车级芯⽚)#include "Ds18b20.h"/************************************************************* DS18B20 status initialization************************************************************/#pragma MESSAGE DISABLE C12056 //屏蔽警告INT8U Ds18b20StsInit(void){INT8U ack = DB_OK;INT16U outTime = 500;//DisableInterrupts/* 初始化状态 */BUS_DIR = HIGH;BUS = HIGH;DelayUs(8);/* 拉低BUS,延时500us */BUS = LOW;DelayUs(480);/* BUS上拉,延时15us-60us */BUS = HIGH;DelayUs(30);/* BUS设置为输⼊ */BUS_DIR = LOW;/* 等待DS18B20存在脉冲做出回应,0正常,60-240us */DelayUs(8);while(BUS){--outTime; //超时处理if(outTime == 0){ack = DB_ERR;break;}}/* 等待DS18B20恢复稳定 */DelayUs(128);/* BUS上拉 */BUS_DIR = HIGH;BUS = HIGH;DelayUs(280);//EnableInterruptsreturn (ack);}/************************************************************* Write data to ds18b20************************************************************/PRIVATE void Ds18b20WriteData(INT8U cmd){INT8U i;DisableInterruptsfor(i = 0; i < 8; i++){//BUS = LOW; //HIGH->LOW 启动写时序//Tim_Delay8Us(2);if(cmd & 0x01) //从低位开始发送数据,15us完成 {BUS = 0; //写1时序DelayUs(5);BUS = 1;}else{BUS = 0; //写0时序DelayUs(5);}DelayUs(60); //等待从器件采集数据BUS = HIGH; //拉⾼总线,起始状态DelayUs(8);cmd >>= 0x01;}EnableInterrupts}#if 1/************************************************************* Read data from ds18b20************************************************************/ PRIVATE INT8U Ds18b20ReadData(void){INT8U i;INT8U data = 0x00;BUS = HIGH;DelayUs(8);DisableInterruptsfor(i = 0; i < 8; i++){data >>= 0x01;BUS = LOW; //拉低总线,进⾏读时序操作 DelayUs(8);BUS = HIGH; //拉低总线,进⾏读时序操作 DelayUs(8);BUS_DIR = LOW; //配置为输⼊asm("nop");//Tim_Delay8Us(1);if(BUS){data |= 0x80;}DelayUs(60); //等待数据读缓存BUS_DIR = HIGH;BUS = HIGH;DelayUs(8);}EnableInterruptsreturn (data);#endifINT8U Dt = 0, Dt1 = 0;/************************************************************* Get data from ds18b20************************************************************/INT16U Ds18b20GetTemperature(void){INT16U data = CLEAR;INT8U temp[2] = {0};Dt = Ds18b20StsInit();Ds18b20WriteData(0xcc); //跳过rom命令Ds18b20WriteData(0x44); //启动温度转换Dt1 = Ds18b20StsInit();Ds18b20WriteData(0xcc); //跳过rom命令Ds18b20WriteData(0xbe); //读暂存寄存器temp[0] = Ds18b20ReadData();temp[1] = Ds18b20ReadData();data = (temp[1] << 8) | temp[0];return (data);}调试DS18B20遇到采集数据不稳定情况: 不稳定现象:每读到⼏个正常数据后会有⼏个不正常的数据 不稳定原因:因为中断在打断我数据的读写以及采集 解决办法:因为DS18B20单总线读写时对时序要求很严格,每次读写时关闭中断即可得到稳定数据。
ds18b20汇编程序:本汇编程序仅适合单个DS18B20和51单片机的连接,晶振为12 MHZ左右DQ:DS18B20的数据总线接脚FLAG1:标志位,为"1"时表示检测到DS18B20TEMPER_NUM:保存读出的温度数据TEMPER_LEQU36HTEMPER_HEQU35HDQBITP1.7; DS18B20初始化汇编程序;//*****************************************//INIT_1820:SETBDQNOPCLRDQMOVR0,#06BHTSR1:DJNZR0,TSR1; 延时SETBDQMOVR0,#25HTSR2:JNBDQ,TSR3DJNZR0,TSR2LJMPTSR4; 延时TSR3:SETBFLAG1; 置标志位,表示DS1820存在LJMPTSR5TSR4:CLRFLAG1; 清标志位,表示DS1820不存在LJMPTSR7TSR5:MOVR0,#06BHTSR6:DJNZR0,TSR6; 延时TSR7:SETBDQRET;//*****************************************// ; 重新写DS18B20暂存存储器设定值;//*****************************************//RE_CONFIG:JBFLAG1,RE_CONFIG1; 若DS18B20存在,转RE_CONFIG1 RETRE_CONFIG1:MOVA,#0CCH; 发SKIP ROM命令LCALLWRITE_1820MOVA,#4EH; 发写暂存存储器命令LCALLWRITE_1820MOVA,#00H; TH(报警上限)中写入00HLCALLWRITE_1820MOVA,#00H; TL(报警下限)中写入00HLCALLWRITE_1820MOVA,#1FH; 选择9位温度分辨率LCALLWRITE_1820RET;//*****************************************//; 读出转换后的温度值;//*****************************************//GET_TEMPER:SETBDQ; 定时入口LCALLINIT_1820JBFLAG1,TSS2RET; 若DS18B20不存在则返回TSS2:MOVA,#0CCH; 跳过ROM匹配LCALLWRITE_1820MOVA,#44H; 发出温度转换命令LCALLWRITE_1820LCALLINIT_1820MOVA,#0CCH; 跳过ROM匹配LCALLWRITE_1820MOVA,#0BEH; 发出读温度命令LCALLWRITE_1820LCALLREAD_1820MOVTEMPER_NUM,A; 将读出的温度数据保存RET;//*****************************************//; 读DS18B20的程序,从DS18B20中读出一个字节的数据;//*****************************************// READ_1820:MOVR2,#8RE1:CLRCSETBDQNOPNOPCLRDQNOPNOPNOPSETBDQMOVR3,#7DJNZR3,$MOVC,DQMOVR3,#23DJNZR3,$RRCADJNZR2,RE1RET;//*****************************************//; 写DS18B20的程序;//*****************************************// WRITE_1820:MOVR2,#8CLRCWR1:CLRDQMOVR3,#6DJNZR3,$RRCAMOVDQ,CMOVR3,#23DJNZR3,$SETBDQNOPDJNZR2,WR1SETBDQ RET;//*****************************************//; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据;//*****************************************//READ_18200:MOVR4,#2; 将温度高位和低位从DS18B20中读出MOVR1,#36H; 低位存入36H(TEMPER_L),高位存入35H(TEMP ER_H)RE00:MOVR2,#8RE01:CLRCSETBDQNOPNOPCLRDQNOPNOPNOPSETBDQMOVR3,#7DJNZR3,$MOVC,DQMOVR3,#23DJNZR3,$RRCADJNZR2,RE01MOV@R1,ADECR1DJNZR4,RE00RET;//*****************************************//; 将从DS18B20中读出的温度数据进行转换;//*****************************************//TEMPER_COV:MOVA,#0F0HANLA,TEMPER_L; 舍去温度低位中小数点后的四位温度数值SWAPAMOVTEMPER_NUM,AMOVA,TEMPER_LJNBACC.3,TEMPER_COV1; 四舍五入去温度值INCTEMPER_NUMTEMPER_COV1:MOVA,TEMPER_HANLA,#07HSWAPAORLA,TEMPER_NUMMOVTEMPER_NUM,A; 保存变换后的温度数据LCALLBIN_BCDRET;//*****************************************//; 将16进制的温度数据转换成压缩BCD码;//*****************************************//BIN_BCD:MOVDPTR,#TEMP_TABMOVA,TEMPER_NUMMOVCA,@A+DPTRMOVTEMPER_NUM,ARETTEMP_TAB:DB00H,01H,02H,03H,04H,05H,06H,07HDB08H,09H,10H,11H,12H,13H,14H,15HDB16H,17H,18H,19H,20H,21H,22H,23HDB24H,25H,26H,27H,28H,29H,30H,31HDB32H,33H,34H,35H,36H,37H,38H,39HDB40H,41H,42H,43H,44H,45H,46H,47HDB48H,49H,50H,51H,52H,53H,54H,55HDB56H,57H,58H,59H,60H,61H,62H,63HDB64H,65H,66H,67H,68H,69H,70H;//*****************************************//下面还介绍一个ds18b20汇编程序;**********************************FLAG1 BIT F0 ;DS18B20存在标志位DQ BIT P1.7TEMPER_L EQU 29HTEMPER_H EQU 28HA_BIT EQU 35HB_BIT EQU 36H;************ds18b20汇编程序起始******************** ORG 0000HAJMP MAINORG 0100H;**************主程序开始************MAIN:LCALL INIT_18B20;LCALL RE_CONFIGLCALL GET_TEMPERAJMP CHANGE;**********DS18B20复位程序*****************INIT_18B20: SETB DQNOPCLR DQMOV R0,#0FBHTSR1: DJNZ R0,TSR1 ;延时SETB DQMOV R0,#25HTSR2: JNB DQ ,TSR3DJNZ R0,TSR2TSR3: SETB FLAG1 ;置标志位,表明DS18B20存在CLR P2.0 ;二极管指示AJMP TSR5TSR4: CLR FLAG1LJMP TSR7TSR5: MOV R0,#06BHTSR6: DJNZ R0,TSR6TSR7:SETB DQ ;表明不存在RET;********************设定DS18B20暂存器设定值********** ****;RE_CONFIG:;JB FLAG1,RE_CONFIG1;RET;RE_CONFIG1: MOV A,#0CCH ;放跳过ROM命令;LCALL WRITE_18B20;MOV A,#4EH;LCALL WRITE_18B20 ;写暂存器命令;MOV A,#00H ;报警上限中写入00H;LCALL WRITE_18B20;MOV A,#00H ;报警下限中写入00H; LCALL WRITE_18B20;MOV A,#1FH ;选择九位温度分辨率; LCALL WRITE_18B20; RET;*****************读转换后的温度值****************GET_TEMPER:SETB DQLCALL INIT_18B20JB FLAG1,TSS2RET ;若不存在则返回TSS2: MOV A,#0CCH ;跳过ROMLCALL WRITE_18B20MOV A,#44H ;发出温度转换命令LCALL WRITE_18B20LCALL DISPLAY ;延时LCALL INIT_18B20MOV A,#0CCH ;跳过ROMLCALL WRITE_18B20MOV A,#0BEH ;发出读温度换命令LCALL WRITE_18B20LCALL READ2_18B20 ;读两个字节的温度RET;***************写ds18b20汇编程序************WRITE_18B20:MOV R2,#8CLR CWR1:CLR DQMOV R3,#6DJNZ R3,$RRC AMOV DQ,CMOV R3,#23DJNZ R3,$SETB DQNOPDJNZ R2,WR1SETB DQRET;***********读18B20程序,读出两个字节的温度********* READ2_18B20:MOV R4,#2 ;低位存在29 H,高位存在28HMOV R1,#29HRE00: MOV R2,#8RE01: CLR CSETB CNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;************读出的温度进行数据转换**************CHANGE: MOV A,29HMOV C,28H.0 ;将28H中的最低位移入CRRC AMOV C,28H.1RRC AMOV C,28H.2RRC AMOV C,28H.3RRC AMOV 29H,A;setb p2.0LCALL DISPLAY ;调用数码管显示子程序; setb P2.0LJMP MAIN;*******************DISPLAY******DISPLAY: mov a,29H;将29H中的十六进制数转换成10进制mov b,#10 ;10进制/10=10进制div abmov b_bit,a ;十位在amov a_bit,b ;个位在bmov dptr,#TAB ;指定查表启始地址mov r0,#4dpl1: mov r1,#250 ;显示1000次dplop: mov a,a_bit ;取个位数MOVC A,@A+DPTR ;查个位数的7段代码mov p0,a ;送出个位的7段代码clr p2.5;开个位显示acall d1ms ;显示1mssetb p2.5mov a,b_bit ;取十位数MOVC A,@A+DPTR ;查十位数的7段代码mov p0,a ;送出十位的7段代码clr p2.4;开十位显示acall d1ms ;显示1mssetb p2.4djnz r1,dplop ;100次没完循环djnz r0,dpl1 ;4个100次没完循环ret;***********************************D1MS: MOV R7,#80 ;1MS延时(按12MHZ算)DJNZ R7,$RET;*************************TAB: 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码}。
源代码:;这是关于单个DS18B20的测温程序,数据脚为P3.3,晶振是11.059MHZ;(因为我要用到串口通信,只是下面没有给出具体的程序,所以下面的延时用12MHZ计算) ;温度传感器18B20采用器件默认的12位转化,最大转化时间要750毫秒;用1602液晶屏显示,显示温度从00到99度,精确到0.0625度;内存分配声明TEMPER_L EQU 29H;用于保存读出温度的低字节TEMPER_H EQU 28H;用于保存读出温度的高字节T_DF EQU 27H ;FORMA T后的小数部分(decimal fraction),半字节的温度小数(存在低四位) T_INTEGER EQU 26H ;FORMA T后的整数部分(integer),将两字节的温度整合成1字节FLAG1 BIT 50H;位地址50H是字节2AH的最低位,用作是否检测到DS18B20的标志位A_BIT EQU 20h ;液晶十位数存放内存位置B_BIT EQU 21h ;液晶个位数存放内存位置C_BIT EQU 22H ;个位小数D_BIT EQU 23H ;十位小数E_BIT EQU 24H ;百位小数F_BIT EQU 25H ;千位小数RS BIT P3.7 ;这3位是液晶屏的控制信号,连接方式由具体硬件而定RW BIT P3.6E BIT P3.5ORG 0000HLJMP MAINORG 0100HMAIN: LCALL T_CONVERSION;调用读温度子程序LCALL T_FORMA T;将读出的2字节温度格式化LCALL DISPLAY;调用液晶显示子程序LCALL D1S;延时1秒后再测LJMP MAIN;--------------DS18B20的温度转换子程序,具体时序请参考资料-------------------T_CONVERSION:LCALL INIT_1820;先复位DS18B20JB FLAG1,T_C0RET ; 判断DS1820是否存在?若DS18B20不存在则返回T_C0: MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820LCALL D1S ;这里等待AD转换结束,12位的话要延时750m秒LCALL INIT_1820;准备读温度前先复位MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_1820; 将读出的温度数据保存到28H(TEMPER_H)和29H(TEMPER_L)处RET;------DS18B20复位初始化程序-----------------------------------------INIT_1820: SETB P3.3NOPCLR P3.3MOV R0,#2 ;主机发出延时500微秒的复位低脉冲INIT0: MOV R1,#250DJNZ R1,$DJNZ R0,INIT0SETB P3.3;然后拉高数据线NOPMOV R0, #15INIT1: JNB P3.3, INIT3;延时60us等待DS18B20回应DJNZ R0, INIT1LJMP INIT4 ; 超时而没有响应INIT3: SETB FLAG1 ; 置标志位,表示DS1820存在LJMP INIT5INIT4: CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP INIT6INIT5: MOV R0, #120DJNZ R0, $ ; 延时240usINIT6: SETB P3.3RET;---------写DS18B20的子程序(有具体的时序要求)-------------------------------------WRITE_1820: MOV R2,#8;一共8位数据WR0: CLR P3.3MOV R3,#6DJNZ R3,$RRC AMOV P3.3,CMOV R3,#20DJNZ R3,$SETB P3.3NOPNOPDJNZ R2,WR0SETB P3.3RET;------读DS18B20的程序,从DS18B20中读出两个字节的温度数据-------------------------- READ_1820: MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#TEMPER_L ; 低位存入29H(TEMPER_L)RE0: MOV R2,#8RE1: SETB P3.3NOPNOPCLR P3.3NOPNOPSETB P3.3MOV R3,#5DJNZ R3, $MOV C,P3.3MOV R3,#20DJNZ R3, $RRC ADJNZ R2,RE1MOV @R1,ADEC R1 ; 高位存入28H(TEMPER_H)DJNZ R4,RE0RET;-----整合读出的两字节温度(关于DS18B20读出的2字节温度格式请参考资料)---------- T_FORMAT: MOV A, #0FHANL A, TEMPER_LMOV T_DF, A ;获得小数部分(4位)MOV A, TEMPER_LSWAP AMOV TEMPER_L, AMOV A, TEMPER_HSWAP AMOV R0, #TEMPER_LXCHD A, @R0MOV T_INTEGER, A ;获得整数部分(1字节)RET;-------液晶显示的子程序(显示前先格式转换)--------------------------------------- DISPLAY: mov a, T_INTEGERmov b,#10div abmov A_BIT,a ;十位存在A_BITmov B_BIT,b ;个位存在B_BITMOV A, T_DFMOV R0, #C_BITMOV R2, #4D0: MOV B, #10MUL ABMOV B, #16DIV ABMOV @R0, A ;从个位小数C_BIT,到十位D_BIT,百位E_BIT,千位F_BITINC R0MOV A, BDJNZ R2, D0;----二进制到ASCII码转换--------------MOV A, #30HORL A_BIT, AORL B_BIT, AORL C_BIT, AORL D_BIT, AORL E_BIT, AORL F_BIT, A;-------------------------------------LCALL INITIALMOV A, #10000000B ; LINE1: DB 'Now is:',00HLCALL WRITE_INSTRUCTIONMOV DPTR, #LINE1LCALL PR_STRINGMOV A, A_BITLCALL WRITE_LCDDATAMOV A, B_BITLCALL WRITE_LCDDATAMOV A, #2EH ;'.'字符LCALL WRITE_LCDDATAMOV A, C_BITLCALL WRITE_LCDDATAMOV A, D_BITLCALL WRITE_LCDDATAMOV A, E_BITLCALL WRITE_LCDDATAMOV A, F_BITLCALL WRITE_LCDDATAMOV A, #0DFH ;下面两个是摄氏度的数字符号LCALL WRITE_LCDDATAMOV A, #63HLCALL WRITE_LCDDATAmov a, #11000000B ; LINE2: DB 'Design by liang!',00HLcall write_instructionMOV DPTR, #LINE2LCALL PR_STRINGRET;---液晶屏初始化,具体请参考资料------------------------------------------------- initial: MOV A, #01HLCALL WRITE_INSTRUCTIONMOV A, #38HLCALL WRITE_instructionMOV A, #0FHLCALL WRITE_instructionMOV A, #06HLCALL WRITE_instructionRET;----写液晶指令的子程序------------------------------------------WRITE_instruction: MOV P1, ACLR RS ;写入控制命令CLR RWCLR ELCALL DELAYSETB ERET;----写液晶数据的子程序---------------------------------------------write_lcddata: MOV P1, ASETB RS ;写入数据CLR RWCLR ELCALL DELAY ;判断液晶模块是否忙?SETB ERET;-----写行字符的子程序---------------------------------------------------------------PR_STRING: CLR AMOVC A, @A+DPTRJZ END_PRLCALL WRITE_LCDDATAINC DPTRLJMP PR_STRINGEND_PR: RET;----查看液晶忙碌信号的子程序--------------------------------------------------------- DELAY: MOV P1,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOPSETB EJB P1.7,DELAY ;如果P1.7为高电平表示忙就循环等待RET;---1mS延时(按12MHZ算)----------------------------------------------------------------- D1mS: MOV R7,#250LOOP0: NOPNOPDJNZ R7,LOOP0RET;----1S延时(按12MHZ算)----------------------------------------------------------------- D1S: Mov R6,#4LOOP2: mov R5,#250LOOP1: LCALL D1mSDJNZ R5,LOOP1DJNZ R6,LOOP2RET;--------------------------------------------------------------------------------------LINE1: DB 'Now is:',00HLINE2: DB 'Design by liang!',00HEND。
这个是我自己制作的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;}。
本程序为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()//初始化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; //写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码}。
/*******************代码部分**********************//*************** writer:shopping.w ******************/ #include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define delayNOP() {_nop_();_nop_();_nop_();_nop_();}sbit DQ = P3^3;sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;uchar code Temp_Disp_Title[]={"Current Temp : "};uchar Current_Temp_Display_Buffer[]={" TEMP: "};uchar code Temperature_Char[8] ={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};uchar code df_Table[]=0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};uchar CurrentT = 0;uchar Temp_Value[]={0x00,0x00}; uchar Display_Digit[]={0,0,0,0};bit DS18B20_IS_OK = 1;void DelayXus(uint x){uchar i;while(x--){for(i=0;i<200;i++);}}bit LCD_Busy_Check(){bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;delayNOP();result = (bit)(P0&0x80);LCD_EN=0;return result;}void Write_LCD_Command(uchar cmd) {while(LCD_Busy_Check());LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();P0 = cmd;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0;}void Write_LCD_Data(uchar dat){while(LCD_Busy_Check());LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0;}void LCD_Initialise(){Write_LCD_Command(0x01);DelayXus(5);Write_LCD_Command(0x38);DelayXus(5);Write_LCD_Command(0x0c);DelayXus(5);Write_LCD_Command(0x06);DelayXus(5);}void Set_LCD_POS(uchar pos){Write_LCD_Command(pos|0x80); }void Delay(uint x){while(--x);}uchar Init_DS18B20(){uchar status;DQ = 1;Delay(8);DQ = 0;Delay(90);DQ = 1;Delay(8);DQ = 1;return status;}uchar ReadOneByte(){uchar i,dat=0;DQ = 1;_nop_();for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;_nop_();_nop_();if(DQ)dat |= 0X80;Delay(30);DQ = 1;}return dat;}void WriteOneByte(uchar dat) {uchar i;for(i=0;i<8;i++){DQ = 0;DQ = dat& 0x01;Delay(5);DQ = 1;dat >>= 1;}}void Read_Temperature(){if(Init_DS18B20()==1)DS18B20_IS_OK=0;else{WriteOneByte(0xcc);WriteOneByte(0x44);Init_DS18B20();WriteOneByte(0xcc);WriteOneByte(0xbe);Temp_Value[0] = ReadOneByte();Temp_Value[1] = ReadOneByte();DS18B20_IS_OK=1;}}void Display_Temperature(){uchar i;uchar t = 150, ng = 0;if((Temp_Value[1]&0xf8)==0xf8){Temp_Value[1] = ~Temp_Value[1];Temp_Value[0] = ~Temp_Value[0]+1;if(Temp_Value[0]==0x00)Temp_Value[1]++;ng = 1;}Display_Digit[0] = df_Table[Temp_Value[0]&0x0f];CurrentT = ((Temp_Value[0]&0xf0)>>4) | ((Temp_Value[1]&0x07)<<4);Display_Digit[3] = CurrentT/100;Display_Digit[2] = CurrentT%100/10;Display_Digit[1] = CurrentT%10;Current_Temp_Display_Buffer[11] = Display_Digit[0] + '0';Current_Temp_Display_Buffer[10] = '.';Current_Temp_Display_Buffer[9] = Display_Digit[1] + '0';Current_Temp_Display_Buffer[8] = Display_Digit[2] + '0';Current_Temp_Display_Buffer[7] = Display_Digit[3] + '0';if(Display_Digit[3] == 0)Current_Temp_Display_Buffer[7] = ' ';if(Display_Digit[2] == 0&&Display_Digit[3]==0)Current_Temp_Display_Buffer[8] = ' ';if(ng){if(Current_Temp_Display_Buffer[8] == ' ')Current_Temp_Display_Buffer[8] = '-';else if(Current_Temp_Display_Buffer[7] == ' ')Current_Temp_Display_Buffer[7] = '-';elseCurrent_Temp_Display_Buffer[6] = '-';}Set_LCD_POS(0x00);for(i=0;i<16;i++){Write_LCD_Data(Temp_Disp_Title[i]);}Set_LCD_POS(0x40);for(i=0;i<16;i++){Write_LCD_Data(Current_Temp_Display_Buffer[i]);}Set_LCD_POS(0x4d);Write_LCD_Data(0x00);Set_LCD_POS(0x4e);Write_LCD_Data('C');}void main(){LCD_Initialise();Read_Temperature();Delay(50000);Delay(50000);while(1){Read_Temperature();if(DS18B20_IS_OK)Display_Temperature();DelayXus(100);}}。
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。