初学不要直接去写,在开发板里小小修改一下,等熟透了再去写,这样才是对的。 |
直接贴程序不好吗?还方便一些嘛。 给你一个例程: main.c #include<reg51.h> #include"DS18B20.h" #define SMG P0//数码管IO sbit LSA=P2^2;//138译码器 sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code ZF[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//要显示的数字 unsigned int XS[5]={0x3f,0x3f,0x3f,0x3f,0x3f};//显示缓存 void FZ(int temp)//给数码管显示缓存放入数据 { float tp;//要进行带符号的小数运算,必须用有符号实型数据,32位 if(temp< 0)//当温度值为负数 { XS[0] = 0x40;//显示负号- temp=temp-1;//因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp=~temp; tp=temp; temp=tp*0.0625*100+0.5;//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数 //转换为整型的时候把小数点后面的数自动去掉,不管是否 //大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上.5,还是在小数点后面。 } else { XS[0] = 0x70;//正数就显示┣ tp=temp; temp=tp*0.0625*100+0.5; } XS[1] = ZF[temp % 10000 / 1000]; XS[2] = ZF[temp % 1000 / 100] + 0x80;//显示小数点 XS[3] = ZF[temp % 100 / 10]; XS[4] = ZF[temp % 10 / 1]; } void DISPLAY() { LSC=1;LSB=0;LSA=0;//温度正负号 SMG=XS[0]; Delay1ms(1); SMG=0x00; LSC=0;LSB=1;LSA=1;//温度的十位 SMG=XS[1]; Delay1ms(1); SMG=0x00; LSC=0;LSB=1;LSA=0;//温度的个位带小数点 SMG=XS[2]; Delay1ms(1); SMG=0x00; LSC=0;LSB=0;LSA=1;//温度的小数点后第一位 SMG=XS[3]; Delay1ms(1); SMG=0x00; LSC=0;LSB=0;LSA=0;//温度的小数点后第二位 SMG=XS[4]; Delay1ms(1); SMG=0x00; } void main() { while(1) { FZ(Ds18b20ReadTemp());//读取温度值并对显示缓存赋值 DISPLAY();//数码管显示 } } DS18B20.c #include"DS18B20.h" void Delay1ms(unsigned int y)//延时yms { unsigned int x; for(y;y>0;y--) for(x=110;x>0;x--); } unsigned char Ds18b20Init()//初始化 { unsigned int i; DSPORT=0;//将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1;//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT)//等待DS18B20拉低总线 { i++; if(i>1000)//等待>1MS { return 0;//初始化失败 } } return 1;//初始化成功 } void Ds18b20WriteByte(unsigned char dat)//向18B20写入一个字节 { unsigned int i,j; for(j=0;j<8;j++) { DSPORT=0;//每写入一位数据之前先把总线拉低1us i++; DSPORT=dat&0x01;//然后写入一个数据,从最低位开始 i=6; while(i--);//延时68us,持续时间最少60us DSPORT=1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } } unsigned char Ds18b20ReadByte()//从DS18B20读取一个字节 { unsigned char byte,bi; unsigned int i,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT;//读取数据,从最低位开始读取 byte=(byte>>1)|(bi<<7); i=4;//读取完之后等待48us再接着读取下一个数 while(i--); } return byte; } void Ds18b20ChangTemp()//向DS18B20发送温度转换命令 { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc);//跳过ROM操作命令 Ds18b20WriteByte(0x44);//温度转换命令 } void Ds18b20ReadTempCom()//发送读取温度命令 { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc);//跳过ROM操作命令 Ds18b20WriteByte(0xbe);//发送读取温度命令 } int Ds18b20ReadTemp()//读取温度 { int temp=0; unsigned char tmh,tml; Ds18b20ChangTemp();//先写入转换命令 Ds18b20ReadTempCom();//然后等待转换完后发送读取温度命令 tml=Ds18b20ReadByte();//读取温度值共16位,先读低字节 tmh=Ds18b20ReadByte();//再读高字节 temp=tmh;//把两次得到的8位数据,合并为16位实际数据 temp<<=8; temp|=tml; return temp;//温度的英文单词temperature } DS18B20.h #ifndef __TEMP_H_ #define __TEMP_H_ #include<reg51.h> sbit DSPORT=P3^7; void Delay1ms(unsigned int ); unsigned char Ds18b20Init(); void Ds18b20WriteByte(unsigned char com); unsigned char Ds18b20ReadByte(); void Ds18b20ChangTemp(); void Ds18b20ReadTempCom(); int Ds18b20ReadTemp(); #endif 程序适用的电路: ![]() ![]() ![]() |
如果你用protues上的ds18b20,你检查的ds18b20的时序, 之前我也存在这个问题 |
检查下单片机读DS18B20传感器的时序机延时是否有问题 |
应与显示无关,与DS18b20读出数据有关,可能没有读出,tp=0是初始值。 |