#includereg52.h#includeintrins.h#defineucharunsignedchar#defineuintunsignedintsbitDQ=P2^2;//数据口defineinterfacesbitdula=P2^6;//数码管段选sbitwela=P2^7;//数码管位选uinttemp;//温度值variableoftemperature//不带小数点unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//带小数点unsignedcharcodetable1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};/*************精确延时函数*****************/voiddelay(unsignedchari){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******************/voidInit_Ds18b20(void)//DS18B20初始化sendresetandinitializationcommand{DQ=1;//DQ复位,不要也可行。delay(1);//稍做延时DQ=0;//单片机拉低总线delay(250);//精确延时,维持至少480usDQ=1;//释放总线,即拉高了总线delay(100);//此处延时有足够,确保能让DS18B20发出存在脉冲。}ucharRead_One_Byte()//读取一个字节的数据readabytedate//读数据时,数据以字节的最低有效位先从总线移出{uchari=0;uchardat=0;for(i=8;i0;i--){DQ=0;//将总线拉低,要在1us之后释放总线//单片机要在此下降沿后的15us内读数据才会有效。_nop_();//至少维持了1us,表示读时序开始dat=1;//让从总线上读到的位数据,依次从高位移动到低位。DQ=1;//释放总线,此后DS18B20会控制总线,把数据传输到总线上delay(1);//延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分if(DQ)//控制器进行采样{dat|=0x80;//若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0}delay(10);//此延时不能少,确保读时序的长度60us。}return(dat);}voidWrite_One_Byte(uchardat){uchari=0;for(i=8;i0;i--){DQ=0;//拉低总线_nop_();//至少维持了1us,表示写时序(包括写0时序或写1时序)开始DQ=dat&0x01;//从字节的最低位开始传输//指令dat的最低位赋予给总线,必须在拉低总线后的15us内,//因为15us后DS18B20会对总线采样。delay(10);//必须让写时序持续至少60usDQ=1;//写完后,必须释放总线,dat=1;delay(1);}}uintGet_Tmp()//获取温度getthetemperature{floattt;uchara,b;Init_Ds18b20();//初始化Write_One_Byte(0xcc);//忽略ROM指令Write_One_Byte(0x44);//温度转换指令Init_Ds18b20();//初始化Write_One_Byte(0xcc);//忽略ROM指令Write_One_Byte(0xbe);//读暂存器指令a=Read_One_Byte();//读取到的第一个字节为温度LSBb=Read_One_Byte();//读取到的第一个字节为温度MSBtemp=b;//先把高八位有效数据赋于temptemp=8;//把以上8位数据从temp低八位移到高八位temp=temp|a;//两字节合成一个整型变量tt=temp*0.0625;//得到真实十进制温度值//因为DS18B20可以精确到0.0625度//所以读回数据的最低位代表的是0.0625度temp=tt*10+0.5;//放大十倍//这样做的目的将小数点后第一位也转换为可显示数字//同时进行一个四舍五入操作。returntemp;}/****************数码码动态显示函数**************/voidDisplay(uinttemp)//显示程序{ucharA1,A2,A3;A1=temp/100;//百位A2=temp%100/10;//十位A3=temp%10;//个位dula=0;P0=table[A1];//显示百位dula=1;//打开段选,对应74573的锁存位,高电平不锁存dula=0;wela=0;P0=0x7e;wela=1;//打开位选wela=0;delay(0);dula=0;P0=table1[A2];//显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)dula=1;dula=0;wela=0;P0=0x7d;wela=1;wela=0;delay(0);P0=table[A3];//显示个位dula=1;dula=0;P0=0x7b;wela=1;wela=0;delay(0);}voidmain(){while(1){Display(Get_Tmp());}}