DS20B18温度传感器+数码管显示
时间:2022-08-07 08:30:00
代码:
#include #define uint unsigned int #define uchar unsigned char typedef unsigned int u16; sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; sbit DS = P3^7; char code smgduan[13]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x00,0x80,0x40}; //0~9数码 char display_T[8]; //毫秒延迟函数 void delayms(uint ms) { uchar i; while(ms--) for(i=0;i<123;i ); } ///数字管显示函数 void Digdisplay() { char i; for(i=0;i<8;i ) { switch(i) { case 0: LSC=1;LSB=1;LSA=1; break; //显示第一位数码管 case 1: LSC=1;LSB=1;LSA=0; break; //显示第二位数码管 case 2: LSC=1;LSB=0;LSA=1; break; //显示第三位数码管 case 3: LSC=1;LSB=0;LSA=0; break; //显示第四位数码管 case 4: LSC=0;LSB=1;LSA=1; break; //显示第5位数码管 case 5: LSC=0;LSB=1;LSA=0; break; //显示第6位数码管 case 6: LSC=0;LSB=0;LSA=1; break; //显示第7位数码管 case 7: LSC=0;LSB=0;LSA=0; break; //显示第8位数码管 } P0=smgduan[display_T[i]]; ///发送数据 delayms(1); //延时1ms,让数码管不断显示 P0=0x00; ///数码管消遣 } } //DS18B20初始化函数 uchar Ds18b20_init() { unsigned char i; DS = 0; //将总线拉低480US~960us i = 70; while(i--); //延时642us DS = 1; ///拉高总线,如果DS18B1520会做出反应us~60us后总线拉低 i = 0; while(DS) //等待DS18B20拉低总线 { delayms(1); i ; if(i>5) //等待大于5MS,说明总线没有被拉低,初始化失败 { return 0; ///初始化失败 } } return 1; ///如果是低电平,直接跳过while循环初始化成功 } ///写时序函数 void Ds18b20WriteByte(uchar dat) { int i,j; for(j=0;j<8;j ) //8位数据 { DS = 0; //每写入一位数据之前先把总线拉低1us i ; DS = dat & 0x01; //然后从最低水平写入数据。只要数据中有0,位运算和运算就是0,只有1相和1 i=6; ///延迟初值 while(i--); //延时68us,因为持续时间最少为60us DS = 1; //然后释放总线,至少1us给总线恢复时间,然后写第二个值 dat >>= 1; //移位,从低到高写入数据,所以最低写入后,向右移动,原来的次低取代原来的低。 } } ///阅读时序函数 uchar Ds18b20ReadByte() { uchar byte,bi; uint i,j; for(j=8;j>0;j--) { DS = 0; ///先拉低总线1us i ; DS = 1; //然后释放总线 i ; i ; //延迟6us等待数据稳定 bi = DS; //读取数据,读取从最低水平开始 /*将byte左移一位,然后向上向右移动7位bi,移动后注意移动补0 */ byte = (byte >> 1) | (bi << 7); //现将byte右移一个,然后bi左移七位,相或获取数据 i=4; 阅读后等待488us然后读取下一个数字 while(i--); } return byte; } ////转换温度启动指令 void Ds18b20ChangTemp() { Ds18b20_init(); //初始化 delayms(1); Ds18b20WriteByte(0xcc); //写入跳过ROM操作命令(cc) Ds18b20WriteByte(0x44); ///温度转换命令(44) } //读取温度命令 void Ds18b20ReadTempCom() { Ds18b20_init(); delayms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0xbe); //发送读取温度命令 } //读取温度 int Ds18b20ReadTemp() { int temp = 0; uchar tmh,tm1; Ds18b20ChangTemp(); ///先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换后发送读取温度命令 tm1 = Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh = Ds18b20ReadByte(); ///读高字节 temp = tmh; temp <<= 8; //移位运算,高字节左移8位,变成16位 temp |= tm1; //位运算或运算,组合 return temp; //高8位和低8位的组合 } ///数字管显示温度 void ds20b18display(int temp) { float tp; if(temp < 0) { display_T[0] = 12; //显示- temp=temp-1; //因为读取的温度是实际温度的补码,所以减1,然后拿出原码进行反求 temp=~temp; tp=temp; temp=tp*0.0625*100 0.5; //0.0625是精度 留两个小数点*100, 0.五是四舍五入,因为C语言浮点数转化为整形时,小数点被转化为整形 ///自动去除后面的数字,不管是否大于0.5,而 0.5之后大于0.5是进1,小于0.5的就 //算加上0.还是在小数点后面。 } else { display_T[0] = 10; //无显示 tp=temp;///因为数据处理中有小数点,所以温度被赋予浮点变量 //如果温度是正的,那么正数原码就是补码本身 temp=tp*0.0625*100 0.5; 留两个小数点*100, 0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 无论是否大于0,///后面的数字都会自动去除.5,而 0.5之后大于0.5是进1,小于0.5的就 //算加上0.还是在小数点后面。 } display_T[2] = temp/10000; //显示百位 display_T[3] = temp000/1000; //显示十位 display_T[4] = temp00/100; //显示个位 display_T[6] = temp/10; ///显示小数点后的一个 display_T[7] = temp; // display_T[1] = 10; //无显示 display_T[5] = 11; //显示“.” } void main() { Ds18b20_init(); while(1) { ds20b18display(Ds18b20ReadTemp()); Digdisplay(); } }
结果图: