1.小于0度的转换

我们知道当测量的实际温度为0度以下时,temp没转换时的情况为下图所示

温度传感器7

我们已经知道高5位为1表示的是负数,那么-0.5度的时候为什么是1111 1111 1111 1000。

负数的计算涉及到补码的知识。首先0xFFF8,除去高5位那就是

111 1111 1000

反码为 000 0000 0111

而补码就是反码加1,也就是补码为000 0000 1000

这样0.5就是由补码(十进制的8)乘以0.0625得来。

我们要知道,负数的时候需要关注的是temp的低11位,补码其实就是2的11次方(2048)减去temp的低11位的数值。

-55度的时候,补码为2048-0x0490=880。 转换就是880*0.0625=55。加上符号就是-55度了。

因为测量负数时只能测-0.1~-55.0,所以液晶屏的显示就有像以下两种情况

温度传感器8

温度传感器9


代码上我们是这样处理的

temp=temp&0x07FF;                   //清除掉高5位使其变为0
temp=2048-temp;                     //此时的temp为补码     
temp_float=(float)temp*0.0625*10.0; //实际温度值再乘以10倍
temp=(unsigned int)temp_float;      //得到16位整型的数值
 
str[0]='-';                         //添加负数的符号
str[1]='0'+( (temp/100)%10 );       //当温度在-10度以下时需要显示十位数
str[2]='0'+( (temp/10)%10 );        //温度必须显示个位数,哪怕是0,比如“-0.5”
str[3]='.';
str[4]='0'+( temp%10 );             //温度必须显示小数点后的一位
 
if(str[1]=='0')
{ 
    str[1]='-';                     //如果温度没有低于等于-10.0度(比如是-9.8度),让str[1]填充负数符号,如果温度低于等于-10.0度,那么填充负数符号的是str[0]
    LcdShowStr(0, 0, str+1);        //温度高于-10.0度,只需显示4个字符
}
else LcdShowStr(0, 0, str);         //温度低于等于-10.0度,显示5个字符

实际温度是-10.0以下的话就是显示5个字符(比如-11.7度)。

实际温度大于-10.0的话,比如-9.8度,要做到高位为0不显示,所以str[1]等于'0'时让“str[1]='-';”。这样的话“LcdShowStr(0, 0, str+1);”就是如下图显示了


温度传感器10


2.再谈指针

以上两种转换方式我们整合成了一个“温度转换”的函数

unsigned char TEMP_CONV(unsigned int *temp, unsigned char *str)
{
    unsigned char res;
    float  temp_float;
    
    res = Get18B20Temp(temp);  //读取当前温度,传入的参数是指针类型
    if (res)                   //读取成功时,进行温度转换
    {
        if( (*temp>>11)==0 )   //温度大于等于0度     
        {   
            temp_float=( (float)(*temp) ) *0.0625*10.0;  //*temp就是没有转换时的16位那个变量,然后再把实际温度值再乘以10倍
            *temp=(unsigned int)temp_float;              //得到16位整型的数值
            str[0]='0'+( (*temp/1000)%10 );              //当温度大于等于100度时需要显示百位数
            str[1]='0'+( (*temp/100)%10 );               //当温度大于等于10度时需要显示十位数
            str[2]='0'+( (*temp/10)%10 );                //当温度大于等于1度时需要显示个位数
            str[3]='.';
            str[4]='0'+( (*temp)%10 );                   //温度必须显示小数点后的一位
 
            if(str[0]=='0')temp_i++;
            if(str[1]=='0')temp_i++;
 
            return 1;//读取温度成功,返回值一律为1
        } 
 
        else if( (*temp>>11)>0 )//温度小于0度     
        {
            *temp=(*temp)&0x07FF;                       //清除掉高5位使其变为0
            *temp=2048-(*temp);                         //此时的temp为补码     
            temp_float=( (float)(*temp) )*0.0625*10.0;  //实际温度值再乘以10倍
            *temp=(unsigned int)temp_float;             //得到16位整型的数值
 
            str[0]='-';                                 //添加负数的符号
            str[1]='0'+( (*temp/100)%10 );              //当温度在-10度以下时需要显示十位数
            str[2]='0'+( (*temp/10)%10 );               //温度必须显示个位数,哪怕是0,比如“-0.5”
            str[3]='.';
            str[4]='0'+( (*temp)%10 );                  //温度必须显示小数点后的一位
 
            if(str[1]=='0')
            { 
                str[1]='-';
                temp_i=1;//实际温度大于-10.0度的时候,假如是-5.4度,那么“LcdShowStr(0, 0, str+temp_i);”就是显示“-5.4”,小数点就是在第3个显示格上显示
                         //实际温度小于等于-10.0度的时候,假如是-12.6度,str[1]不等于‘0’,
                         //这样temp_i是等于0的,那么“LcdShowStr(0, 0, str+temp_i);”显示“-12.6”,小数点就是在第4个显示格上显示  
            }
 
            return 1;    //读取温度成功,返回值一律为1
        } 
    } 
     
    return 0;//读取温度不成功,返回值为0
}

这个函数在主函数里的用法就是判断返回值是否为1

if( TEMP_CONV(&temp,str)==1 )     //返回值为1代表读取温度成功

我们在主函数里定义了一个u16类型的变量temp,

传入给“unsigned char TEMP_CONV(unsigned int *temp, unsigned char *str)”的第一个参数是变量temp的指针,然后该函数执行的第一句“res = Get18B20Temp(temp);”此时传入的参数temp是个指针变量,“Get18B20Temp(temp)”函数内部的执行就是把温度数据赋给传入的指针的那个内存里,后面的“*temp”代表的就是这个内存的变量,也就是读出的未转换的温度值。

点赞(1)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)