求一个ds18b20例案,正负数都可以显示,精度到0.1的
最简单的skip rom方案 或者给我讲一下最后接收到的两个byte的数据怎么处理就行了谢谢了 比如说收到的字节是TH和TL
则hh=TH*256+TL;
然后温度就等于hh*0.0625*10+0.5就是温度的十倍就好了
显示的时候除以10 ********************************************************************
//获取当前温度值
int getTmpValue()
{
unsigned int tmpvalue;
int value; //存放温度数值
float tt;
unsigned char low, high;
sendReadCmd();
//连续读取两个字节数据
low = readByte();
high = readByte();
//将高低两个字节合成一个整形变量
//计算机中对于负数是利用补码来表示的
//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
tmpvalue = high;
tmpvalue <<= 8;
tmpvalue |= low;
value = tmpvalue;
//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
tt = value * 0.0625;
//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
value = tt * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
return value;
}
*******************************************************************************************
//向DS18B20发送读取数据命令获取当前温度值
uint tmp()
{
float tt;
uchar low,high;
dsreset();
delay(1);
tempwritebyte(0xcc); //写入跳过序列号命令字 Skip Rom
tempwritebyte(0xbe); //写入读取数据令字 Read Scratchpad
//连续读取两个字节数据
low =tempread(); //读低8位
high=tempread(); //读高8位
temp=high; //高8位赋予temp
temp<<=8; //将高低两个字节合成一个整形变量 temp为16位 高8位左移8位 低8位补0
temp=temp|low;//高低8位相或=temp为16位=高8位+低8位
tt=temp*0.0625;//DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
// temp = tt * 100 + (temp > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
temp=tt*100;//将它放大100倍, 使显示时可显示小数点后两位(t=11.0625,计算得temp = 1106, 即11.06 度)
return temp; //temp是整型
} 回复【2楼】yao1
-----------------------------------------------------------------------
yao1的解释很精辟啊!佩服! 回复【2楼】yao1
temp<<=8; //将高低两个字节合成一个整形变量 temp为16位 高8位左移8位 低8位补0
-----------------------------------------------------------------------
有一点不明白,temp前面定义为类型的变量?
51不是8位单片机吗?怎么temp可以为16位的数据呢? 很容易
读来的数据,是个双字节有符号数,用C写的话,直接除16就是温度值,计算结果保留小数点后一位即可
不过我喜欢用汇编,为了简化处理,一般不考虑负值。此时低字节位的低4位就是小数值,先乘10再除16,结果就是小数值。然后把高位字节的低4位保留,去除高4位,高低4位交换,最后与去除低4位的低字节位合并,就是整数部分。这样的处理都可以用C51自带的运算指令完成,速度快,程序简单。
要显示负值则需要加负数判断并求补码的程序,也是很容易的 +_+#
18b20本身就做不到0.1度.....
你程序怎么写都没用..... 回复【4楼】Ilove51andAVR
-----------------------------------------------------------------------
有一点不明白,temp前面定义为类型的变量?
51不是8位单片机吗?怎么temp可以为16位的数据呢?
-----------------------------------------------------------------------
unsigned int tmpvalue; 16位 ......
unsigned char low,high; 8位 ......
18B20:
测量数据以16位带符号位扩展的二进制补码形式存放
单片机读取温度,一次读2字节16位,读完将低11位的二进制转化为十进制后乘0.0625即为实际温度,只需要判断11位即可
还需要判断温度正负:前5位为符号位,1为负,0为正
1)前5位为1时,读取温度为负值,实际温度=测得数值需要取反加1再乘0.0625
-55——11111 10010010000——低11位取反011 0110 1111(十进制879)——加1(880)——乘0.0625——实际温度880*0.0625=55(11111为负)
2)前5位为0时,读取温度为正值,实际温度=测得数值乘0.0625
+125 ——00000 11111010000——低11位十进制为2000 ——2000*0.0625=12500000位正
上面的程序只能读正的 要读负值 增加判断(注意变量名不一样)
把tplsb和tpmsb都是8位的合成一个16位的有符号数t;temp为浮点数
t=tpmsb<<8;
t=t|tplsb
if(t<0) //负温度
{
temp=(~t+1)*0.0625*10+0.5; //负温度时,取反加1再乘以0.0625得实际温度,乘10+0.5显示小数点一位,且四舍五入
}
else //正温度
{
temp=t*0.0625*10+0.5; //正温度 实际温度=测得数值乘0.0625
} 还在乘以0.0625……这就是右移4位啊!浮点乘法增加多少运算量? http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_689077KF6V2Q.JPG
(原文件名:表1.JPG) //初学者先理解算法了 再用移位法 理解是关键
//移位原理:
//用10进制来理解,如果把123456这个数右移4位,是不是得到12?也就是除以10的4次方10000得到的(因为是整型,小数部分被舍去了)。
//二进制右移4位,自然是除以2的4次方16了。
//因0.0625=1/16 所以T*0.0625=T/16=T>>4
void v_TemperatureUpdate_f( void )
{
uint16 TempDat ;
float Temp ;
TempDat = v_Ds18b20ReadTemp_f() ;
if( TempDat & 0xf000 )
{
Tflag = 1 ;
TempDat = ~ TempDat + 1 ;
}
Temp = TempDat >> 4; // (TempDat * 0.0625)浮点数运算很慢,效率不高,改成移位
TempDat = Temp * 10;// 保留1位小数
Temperature[ 0 ] = Tflag ; //温度正负标志
Temperature[ 1 ] = TempDat / 100; //温度十位值
Temperature[ 2 ] = (TempDat % 100) / 10; //温度个位值
Temperature[ 3 ] = TempDat % 10; //温度小数位---- 0.1
// Temperature[ 4 ] = (TempDat%10)/10; //温度小数位---- 0.01
} 数字温度传感器 做不到那么高的精度吧
DS18B25的精度只有±0.5℃,分辨率0.0625℃
MAXIM官方的datasheet上有精度的曲线 二楼的帖子是不错的,赞一个 对了,14楼的帖子也不错 主要给获取温度的代码吧:
void gettemperature()
{
uchar temp1,temp2,temp,tflag ;
reset();
writebyte(0xcc);
writebyte(0x44);
reset();
writebyte(0xcc);
writebyte(0xbe);
temp1=readchar();
temp2=readchar();
temp=(temp2<<8)|temp1;
if(temp<0x0fff)
tflag=1;
else
{
tflag=0;
temp=~temp+1;//负温度时,使其取反加一
}
d_temp=temp*(0.625);//正温度
tempshi=d_temp/100;
tempge=d_temp%100/10;
tempxiaoshu=d_temp%10;
} 十六楼这么解释很好。通俗易懂。同样讲一件事,讲_法不同,效果也不同。 是十四楼啊?!刚才看错了。 yao1 发表于 2011-10-27 09:24 static/image/common/back.gif
回复【4楼】Ilove51andAVR
-----------------------------------------------------------------------
...
xiexie ! yao1 发表于 2011-10-27 19:45 static/image/common/back.gif
//初学者先理解算法了 再用移位法 理解是关键
//移位原理:
//用10进制来理解,如果把123456这个数右移4位 ...
“Temp = TempDat >> 4; // (TempDat * 0.0625)浮点数运算很慢,效率不高,改成移位”
这一句中右移四位小数位就没有了吧,后面一句乘以10还有用吗? void get_tem()
{
uchar teml,temh;
reset();
Write_Byte(0xcc);//跳过读序列号的操作
Write_Byte(0x44);//启动温度转换
delay_ms(750);//750ms
reset();
Write_Byte(0xcc);
Write_Byte(0xbe);//读取温度转换结果
teml=Read_Byte();
temh=Read_Byte();
if((temh&0xf0)==0xf0)//如果是负温度
{
flag_low=1;
temper=(~((temh)*256+(teml))+1)*6.25;
}
else
temper=(temh*256+teml)*6.25;//放大100倍
} {:titter:}{:titter:}{:titter:}{:titter:} 请问,有没有人用cvavr做过 啊,你们是用什么来做精确延时的啊,我用自带的延时,就是读不出数据求高手帮忙看看,我发的贴不好,都没人理,只好到这边来拉人啦,求高手指点http://www.amobbs.com/thread-5509739-1-4.html 都没有人响应精度问题? 前面整数部份我就不说了,我只给个最后一位小数得到的方法,结果四舍五入。
x为18B20提取的小数部份,z为输出。
z=(((unsigned char)(x*10u))+8u)>>4;
页:
[1]