上一次讲了DS18B20的整数温度显示
蓝桥杯单片机(八)DS18B20温度测量(整数显示)
但近几年有出题小数部分的温度显示,首先打开DS18B20的数据手册,如图
通过这张表,我就知道读取数据时,低八位和高八位,其中低八位的高四位,和高八位的低四位组成整数部分,低八位的低四位是显示小数的,高八位的高四位是显示正负数的。
通过图发现具体表示方式为
当十六位数据高四位为0000时为正数,当十六位数据高四位为1111为负数。
所以当为正数时
温度=整数部分+低四位第一位×0.5+
整数部分+低四位第二位×0.25+
整数部分+低四位第三位×0.125+
整数部分+低四位第四位×0.0625+
当温度为负数时
先将16位全部取反再+1
温度=整数部分+低四位第一位×0.5+
整数部分+低四位第二位×0.25+
整数部分+低四位第三位×0.125+
整数部分+低四位第四位×0.0625+
所以代码读取温度代码为:
//小数和负数显示温度
signed long rd_temperature(void)
{
uchar low,high;
float point;
signed long integer;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
//(high>>4)&0x0f)!=0x0f判断高四位的值
if(((high>>4)&0x0f)!=0x0f)
{
//整数部分
integer=((low >>4)|(high<<4));
//小数部分
point=(((low&0x08)>>3)*0.5)+(((low&0x04)>>2)*0.25)+\
(((low&0x02)>>1)*0.125)+((low&0x01)*0.0625);
//相加再变为整数
//如25.0625 250625
integer=(integer+point)*10000;
}
else
{
//整数部分
integer=((~(low >>4))|(~(high<<4)));
//小数部分
point=((((~low+1)&0x08)>>3)*0.5)+((((~low+1)&0x04)>>2)*0.25)+\
((((~low+1)&0x02)>>1)*0.125)+(((~low+1)&0x01)*0.0625);
integer=(integer+point)*10000;
//变为负数
integer=-integer;
}
return integer;
}
最后DS18B20温度测量四位小数和负数显示的完整代码为:
#include <stc15f2k60s2.h>
#include "intrins.h"
sbit DQ = P1^4;
#define uchar unsigned char
#define uint unsigned int
void SMG_output(void);
void init(void);
void Delay1ms(void);
bit init_ds18b20(void);
signed long rd_temperature(void);
void Delay_OneWire(unsigned int t);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
signed long temp=0;
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管
void main(void)
{
init();
while(1)
{
temp=rd_temperature();//25 0625
if(temp>0)
{
SMG[0]=20;
SMG[1]=temp/100000;
SMG[2]=temp%100000/10000+10;
SMG[3]=temp%10000/1000;
SMG[4]=temp%1000/100;
SMG[5]=temp%100/10;
SMG[6]=temp%10;
SMG_output();
}
else
{
SMG[0]=21;
SMG[1]=temp/100000;
SMG[2]=temp%100000/10000+10;
SMG[3]=temp%10000/1000;
SMG[4]=temp%1000/100;
SMG[5]=temp%100/10;
SMG[6]=temp%10;
SMG_output();
}
}
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0Xff;
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
//小数和负数显示温度
signed long rd_temperature(void)
{
uchar low,high;
float point;
signed long integer;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
if(((high>>4)&0x0f)!=0x0f)
{
integer=((low >>4)|(high<<4));
point=(((low&0x08)>>3)*0.5)+(((low&0x04)>>2)*0.25)+\
(((low&0x02)>>1)*0.125)+((low&0x01)*0.0625);
integer=(integer+point)*10000;
}
else
{
integer=((~(low >>4))|(~(high<<4)));
point=((((~low+1)&0x08)>>3)*0.5)+((((~low+1)&0x04)>>2)*0.25)+\
((((~low+1)&0x02)>>1)*0.125)+(((~low+1)&0x01)*0.0625);
integer=(integer+point)*10000;
integer=-integer;
}
return integer;
}
//整数显示温度
//unsigned char rd_temperature(void)
//{
// uchar low,high;
// init_ds18b20();
// Write_DS18B20(0xcc);
// Write_DS18B20(0x44);
//
// init_ds18b20();
// Write_DS18B20(0xcc);
// Write_DS18B20(0xbe);
//
// low=Read_DS18B20();
// high=Read_DS18B20();
//
// return((low >>4)|(high<<4));
//}
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t*8;
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
效果如下:
有问题可以评论和私信