51单片机的问题

温度DS18B20读取到温度值后怎么控制小数点?怎么转换并显示到1602上,急急急!!!请详细说明

18B20不说其他东西(校验、温度限值、系列号配对),就说 温度的结果,18B20的温度精度可以设置 9位~12位,而其温度结果有2字节(16位),多余的位,使用 符号扩展 方式填充:
如下列:其中 S表示符号(正负温度),D表示温度结果
9位精度:SSSS SSSS DDDD DDDD,分辨率为 0.5℃;也就是一个数值代表 0.5℃,(数值/2)就是实际温度;
10位精度:SSSS SSSD DDDD DDDD,分辨率为 0.25℃;(/4)
11位精度:SSSS SSDD DDDD DDDD,分辨率为 0.125℃;(/8)
12位精度:SSSS SDDD DDDD DDDD,分辨率为 0.0625℃;(/16)
通常都使用 高精度 的12位模式,符号位要特殊处理,判断并自己记录后(正/负),将结果转为正(正值不变,负值采用“取反+1”的方法),再根据分辨率计算 温度整数、小数部分,(小数点自己点),整数、小数的划分很简单,/2(/4、/8、/16)其实就是右移 1位(2位、3位、4位),移动后取一个字节就是 整数部分,而被移出去的就是 小数部分,而小数部分的计算,根据自己需要的精确度进行计算,如果精确到小数2位,则可以将小数部分 乘以 扩大100倍后的分辨率(50、12.5、6.25),建议先扩大10000倍,精确到所有小数(4位),再除去不需要的小数位。
bit ChangeTempValue(uchar *temp_buf,uchar reso_bit,uchar *save_buf,uchar save_start) //返回:0正温度,1负温度
{
// 9bit(SSSS SSSS DDDD DDDD): S符号位:0正1负,D数据位,0.5℃单位(/2)
//10bit(SSSS SSSD DDDD DDDD): S符号位:0正1负,D数据位,0.25℃单位(/4)
//11bit(SSSS SSDD DDDD DDDD): S符号位:0正1负,D数据位,0.125℃单位(/8)
//12bit(SSSS SDDD DDDD DDDD): S符号位:0正1负,D数据位,0.0625℃单位(/16)
bit polar=0; //温度极性:0正温度,1负温度
uchar temp_int,reso_value;
uint temp_dec,temp_A;
reso_value=(reso_bit>>5)+9; //分辨率指令码转换数值:Reso_9bit/10bit/11bit/12bit→9/10/11/12
if(reso_value>12) reso_value=12; //默认 12bit分辨率精度
if(*(temp_buf+1)>>3)//正负值识别,温度值高5位为1则为 负值
{
polar=1; //负极性
temp_A=(~*(temp_buf+1)<<8 | ~*temp_buf)+1; //取 补码(取反+1)
}
else temp_A=*(temp_buf+1)<<8 | *temp_buf; //正值,合成16位数据
temp_int=(uchar)(temp_A>>(reso_value-8)); //取整数部分,8bit(可以不加强制转换(uchar))
temp_dec=temp_A & (0x0f>>(12-reso_value)); //取小数部分
switch(reso_bit) //小数转换需进行精度选择
{
case Reso_9bit: //9位精度,0.5℃
temp_dec*=5000; //小数扩大10000倍
break;
case Reso_10bit: //10位精度,0.25℃
temp_dec*=2500; //小数扩大10000倍
break;
case Reso_11bit: //11位精度,0.125℃
temp_dec*=1250; //小数扩大10000倍
break;
case Reso_12bit: //12位精度,0.0625℃
default: //其他精度,按12位精度算
temp_dec*=625; //小数扩大10000倍
break;
}
save_buf+=save_start; //指向存储数组中的存储起始位置
*save_buf++=temp_int; //存温度值整数部分
*save_buf++=temp_dec/100; //存温度值小数点 十分位、百分位
*save_buf=temp_dec%100; //存温度值小数点 千分位、万分位
return polar; //返回温度极性:0正温度,1负温度
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2015-10-12
你好!,温度可以精确到 0.5 度,把你程序发一下,帮你看看追问

温度值不能更精确吗?

追答

你是仿真还是做实物

第2个回答  2015-10-12
就把程序里读出来的数按百位,十位,个位,依次求出,想显示几进制就按几进制数作除求余,时间好长了,记不清了,找了一段程序可以显示小数
void Disp_Numb(uint temper)
{
uchar i;

for(i = 0;i < 6;i++) dN[i] = 0; //初始化显示变量

//数值转换
if(temper & BIT0)
{
dN[0] = 5;
dN[1] = 2;
dN[2] = 6;
}
if(temper&BIT1)
{
dN[1] += 5;
dN[2] += 2;
dN[3] += 1;
}
if(temper & BIT2)
{
dN[2] += 5;
dN[3] += 2;
if(dN[2] >= 10)
{
dN[2] -= 10;
dN[3] += 1;
}
}
if(temper&BIT3)
{
dN[3] += 5;
}
if(temper & BIT4)
{
dN[4] += 1;
}
if(temper & BIT5)
{
dN[4] += 2;
}
if(temper & BIT6)
{
dN[4] += 4;
}
if(temper & BIT7)
{
dN[4] += 8;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BIT8)
{
dN[4] += 6;
dN[5] += 1;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BIT9)
{
dN[4] += 2;
dN[5] += 3;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BITA)
{
dN[4] += 4;
dN[5] += 6;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
if(dN[5] >= 10)
{
dN[5] -= 10;
}
}
}
求完之后可以这样显示,这是在LCD屏上显示的,其实就是依次把上面求出来的数显示出来,别的地方显示也是一样道理,
Disp_Numb(Do1Convert());
Disp1Char(4,1,dN[5]+0x30);
Disp1Char(5,1,dN[4]+0x30);
Disp1Char(6,1,0x2e); //0x2e是小数点对应的ASCII码值
Disp1Char(7,1,dN[3]+0x30);
Disp1Char(8,1,dN[2]+0x30);
Disp1Char(9,1,dN[1]+0x30);
Disp1Char(10,1,dN[0]+0x30);本回答被网友采纳
相似回答