1602显示18B20温度有乱码怎么办?

2019-07-15 15:07发布

1602.jpg 先上效果图,+和温度之间有一位乱码,程序是抄的,已经对了很多次了,找不到问题,大神帮忙看看,下面上程序。
#include<reg52.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden=P2^6; //使能信号       
sbit lcdrs=P2^4; //数据/命令选择端(H/L)
//sbit lcdrw=P2^5; //读/写选择端(H/L)
void delayus()
{
        _nop_();       
}

void delayms(uint a)
{
        uint i,j;
        for(i=a;i>0;i--)
                for(j=100;j>0;j--);
}

void writeComm(uchar comm)
{
        lcdrs=0; //写命令:rs=rw=0;
        //lcdrw=0;
        P0=comm;
        lcden=1;
        delayus();
        lcden=0;
        delayms(1);
}
void writeData(uchar dat)
{
        lcdrs=1; //写数据RS=1,RW=0;
        //lcdrw=0;
        P0=dat;
        lcden=1;
        delayus();
        lcden=0;
        delayms(1);
}
void init()        //初始化
{
        writeComm(0x38); //显示模式, 固定指令为00111000=0x38, 16*2显示, 5*7点阵,8位数据接口
        writeComm(0x0c); //指令1: 00001DCB : D:开显示/关显示(H/L); C:显示光标/不显示(H/L), B:光标闪烁/不闪烁(H/L)
        writeComm(0x06); //指令2: 000001NS :N=1, 当读/写一个字符后地址指针加1, 且光标也加1; N=0则相反
                                                                          //S=1, 当写一个字符, 整屏显示左移(N=1)或右移(N=0), 但光标不移动; S=0, 整屏不移动
        writeComm(0x01); //清屏
}
void writeString(uchar*str,uchar length)
{
        uchar i;
        for(i=0;i<length;i++)
        {
                writeData(str);
        }
}

/***********DS18B20*************/
sbit ds=P2^2;
//初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
void dsInit()
{
        uint i; //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us       
        ds=0;
        i=100;
        while(i>0)i--;
        ds=1;
        i=4;
        while(i>0)i--;
}

void dsWait()
{
        uint i;
        while(ds);
        while(~ds); //检测到应答脉冲
        i=4;
        while(i>0)i--;
}

//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readBit()
{
        uint i;
        bit b;
        ds=0;
        i++;  //延时约8us, 符合协议要求至少保持1us
        ds=1;
        i++;i++; //延时约16us, 符合协议要求的至少延时15us以上
        b=ds;
        i=8;
        while(i>0)i--; //延时约64us, 符合读时隙不低于60us要求
        return b;
}

//读取一字节数据, 通过调用readBit()来实现
uchar readByte()
{
        uint i;
        uchar j,dat;
        dat=0;
        for(i=0;i<8;i++)
        {
                j=readBit(); //最先读出的是最低位数据
                dat=(j<<7)|(dat>>1);
        }
        return dat;
}

//向DS18B20写入一字节数据
void writeByte(uchar dat)
{
        uint i;
        uchar j;
        bit b;
        for(j=0;j<8;j++)
        {
                b=dat & 0x01;
                dat>>=1; //写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
                if(b)
                {
                        ds=0;
                        i++;i++; //拉低约16us, 符号要求15~60us内
                        ds=1;
                        i=8;while(i>0)i--; //延时约64us, 符合写时隙不低于60us要求
                }
                else  //写"0", 将DQ拉低60us~120us
                {
                        ds=0;
                        i=8;while(i>0)i--; //拉低约64us, 符号要求
                        ds=1;
                        i++;i++;
                }
        }
}

//向DS18B20发送温度转换命令
void sendChangeCmd()
{
        dsInit();  //初始化DS18B20, 无论什么命令, 首先都要发起初始化
        dsWait();  //等待DS18B20应答
        delayms(1);         //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
        writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
        writeByte(0x44); //写入温度转换命令字 Convert T
}

//向DS18B20发送读取数据命令
void sendReadCmd()
{
        dsInit();
        dsWait();
        delayms(1);
        writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
        writeByte(0xbe); //写入读取数据令字 Read Scratchpad
}

//获取当前温度值
int getTmpValue()
{
        uint tmpvalue;
        int value; //存放温度数值
        float t;
        uchar low,high;
        sendReadCmd(); //连续读取两个字节数据
       
        low=readByte();
        high=readByte();
        //将高低两个字节合成一个整形变量
        //计算机中对于负数是利用补码来表示的
        //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
        tmpvalue=high;
        tmpvalue<<=8;
        tmpvalue|=low;
        value=tmpvalue;
        //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
        t=value*0.0625;
        //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
        //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
    //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
        value=t*100+(value>0?0.5:-0.5);        //大于0加0.5, 小于0减0.5
        return value;       
}

void display(int v)
{
        unsigned char count;
        unsigned char datas[]={0,0,0,0,0};
        unsigned int tmp=abs(v);
        datas[0]=tmp/10000;
        datas[1]=tmp%10000/1000;
        datas[2]=tmp%1000/100;
        datas[3]=tmp%100/10;
        datas[4]=tmp%10;
        writeComm(0xc0+3);
        if(v<0)
        {
                writeString("-",2);
        }
        else
        {
                writeString("+",2);
        }
        if(datas[0]!=0)
        {
                writeData('0'+datas[0]);
        }
        for(count=1;count!=5;count++)
        {
                writeData('0'+datas[count]);
                if(count==2)
                {
                        writeData('.');
                }
        }
}

/*****************DS18B20*****************/
void main()
{
        uchar table[]="Now Temperature:";
        sendChangeCmd();
        init();
        writeComm(0x80);
        writeString(table,16);
        while(1)
        {
                delayms(1000); //温度转换时间需要750ms以上
                writeComm(0xc0);
                display(getTmpValue());
                sendChangeCmd();
        }
}

初学者,菜鸟一枚,第一次发帖,大家见谅!就4分,都发了。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。