打印
[51单片机]

DS18B20温度传感器问题

[复制链接]
1141|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
[/img][code]#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit DQ = P1^6                        ;                       //单总线接口
sbit wela1 = P1^3                ;                    //数码管位选
sbit wela2 = P1^2                ;
sbit wela3 = P1^1                ;
sbit wela4 = P1^0                ;
uint temp                                ;                           //温度值16位
float tt;

//不带小数点
unsigned char code table[] =  {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//带小数点
unsigned char code table1[] = {0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd, 0x87, 0xff,0xef};

/*************精确延时函数*****************/

/*****************************************

延时时间为2*T*i+5*T,T为机器周期        ,这里为12M晶振 T为1us

******************************************/
void delay(unsigned char i)
{
        while(--i);
}
/*****************DS18B20******************/

void Init_Ds18b20(void)     //DS18B20初始化
{
        //uchar flag                ;                                         //应答标志位
        DQ = 1                        ;                     //DQ复位
        delay(1)                ;                  //稍做延时
        DQ = 0                        ;                    //单片机拉低总线
        delay(250)                ;                //精确延时,维持480us~960us
        DQ = 1              ;                    //释放总线,即拉高了总线
        delay(200)           ;                //此处延时约45us
//        flag=DQ              ;                                  //读回应答脉冲
//        delay(200)                 ;            //延时应该足够长时间保证 应答脉冲输出完毕
}

uchar Read_Byte()            //读取一个字节的数据
                            //读数据时,数据以字节的最低有效位先从总线移出
{
        uchar i   = 0;
        uchar dat = 0;                                   //存储读出的一个字节数据
        for(i=0;i<8;i++)
        {   
                DQ=1  ;                                         //        先将数据线拉高
            _nop_();                                         //        等待一个时钟周期
                DQ = 0;                  //将总线拉低,要在1us之后释放总线,单片机要在此下降沿后的15us内读数据才会有效。                                                       
                _nop_();                 //至少维持了1us,表示读时序开始
                dat >>= 1;               //让从总线上读到的位数据,依次从高位移动到低位。
                DQ = 1;                  //释放总线,此后DS18B20会控制总线,把数据传输到总线上
                delay(1);                 //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
                if(DQ)                   //控制器进行采样
                        {
                                dat |= 0x80;            //若总线为1,即DQ为1,那就把dat的最高位置1;                               
                        }
                else
                        {
                        dat |= 0x00    ;                                //若为0,与0或,保持为0
                        }
                        delay(10);               //      确保读时序的长度60us,两个读时序之间必须大于1us的间隔时间
        }
                return (dat);
}

void Write_Byte(uchar dat)
{
                uchar i = 0;
                for(i=0;i<8;i++)
                        {
                                DQ=1  ;                                         //        先将数据线拉高
                                   _nop_();                                         //        等待一个时钟周期
                                DQ = 0;                        //拉低总线
                                _nop_();                       //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
                                DQ = dat& 0x01;                 //从字节的最低位开始传输
                                                                       //指令dat的最低位赋给总线,必须在拉低总线后的15us内,
                                                                            //因为15us后DS18B20会对总线采样。
                                delay(10);                     //必须让写时序持续至少60us
                                DQ = 1;                               //写完后,必须释放总线,
                                dat >>= 1;
                                delay(10);                                           //延时7us两个写时序间隔至少1us
                        }
}

uint Get_Tmp()                   //获取温度get the temperature
{
                uchar a=0;
                uchar b=0;
                Init_Ds18b20();                //每一步操作之前都要进行初始化
                Write_Byte(0xcc);          //忽略ROM指令
                Write_Byte(0x44);          //温度转换指令
                Init_Ds18b20();             //初始化
                Write_Byte(0xcc);          //忽略ROM指令
                Write_Byte(0xbe);          //读暂存器指令
                a = Read_Byte();           //读取到的第一个字节为温度LSB
                b = Read_Byte();           //读取到的第一个字节为温度MSB
                temp = b;                      //先把高八位有效数据赋于temp
                temp <<= 8;                    //把以上8位数据从temp低八位移到高八位
                temp = temp|a;                //两字节合成一个整型变量
                tt = temp*0.0625;              //得到真实十进制温度值
                                       //因为DS18B20可以精确到0.0625度
                                       //所以读回数据的最低位代表的是0.0625度
                temp = tt*10+0.5;               //放大十倍
                                                        //这样做的目的将小数点后第一位也转换为可显示数字
                                                //同时进行一个四舍五入操作。
                return temp;
}

/****************数码码动态显示函数**************/

void Display(uint temp)   //显示程序
{
                uchar A1,A2,A3,a;
                A1 = temp/100;    //千位,因为扩大10倍实际中是百位
                a = temp%100         ;
                A2=a/10;   //百位,实际是十位
                A3 = a%10;                          //实际中的小数位
                  //A4 = temp%1000%100%10;

                wela1=1;
                wela2=1;
                wela3=1;
                wela4=1;
               
               
                 //if(A1>0)
               
                P2 = table[A1];    //显示百位
                wela2 = 0;
                delay(200);
                wela2 = 1;
               

                P2 = table1[A2];   //显示十位
                wela3 = 0;
                delay(200);
                wela3 = 1;

                P2 = table[A3];    //显示个位
                wela4 = 0;
                delay(100);
                wela4 = 1;

         /*   P2 = table[A4];    //显示小数位
                wela4 = 0;
                delay(100);
                wela4 = 1;
                */

}

void main()
{
                uint temp0;
                while(1)
                        {
                        temp0 = Get_Tmp()  ;
                         Display(temp0)    ;
                        }
}[/code]#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit DQ = P1^6                        ;                       //单总线接口
sbit wela1 = P1^3                ;                    //数码管位选
sbit wela2 = P1^2                ;
sbit wela3 = P1^1                ;
sbit wela4 = P1^0                ;
uint temp                                ;                           //温度值16位
float tt;

//不带小数点
unsigned char code table[] =  {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//带小数点
unsigned char code table1[] = {0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd, 0x87, 0xff,0xef};

/*************精确延时函数*****************/

/*****************************************

延时时间为2*T*i+5*T,T为机器周期        ,这里为12M晶振 T为1us

******************************************/
void delay(unsigned char i)
{
        while(--i);
}
/*****************DS18B20******************/

void Init_Ds18b20(void)     //DS18B20初始化
{
        //uchar flag                ;                                         //应答标志位
        DQ = 1                        ;                     //DQ复位
        delay(1)                ;                  //稍做延时
        DQ = 0                        ;                    //单片机拉低总线
        delay(250)                ;                //精确延时,维持480us~960us
        DQ = 1              ;                    //释放总线,即拉高了总线
        delay(200)           ;                //此处延时约45us
//        flag=DQ              ;                                  //读回应答脉冲
//        delay(200)                 ;            //延时应该足够长时间保证 应答脉冲输出完毕
}

uchar Read_Byte()            //读取一个字节的数据
                            //读数据时,数据以字节的最低有效位先从总线移出
{
        uchar i   = 0;
        uchar dat = 0;                                   //存储读出的一个字节数据
        for(i=0;i<8;i++)
        {   
                DQ=1  ;                                         //        先将数据线拉高
            _nop_();                                         //        等待一个时钟周期
                DQ = 0;                  //将总线拉低,要在1us之后释放总线,单片机要在此下降沿后的15us内读数据才会有效。                                                       
                _nop_();                 //至少维持了1us,表示读时序开始
                dat >>= 1;               //让从总线上读到的位数据,依次从高位移动到低位。
                DQ = 1;                  //释放总线,此后DS18B20会控制总线,把数据传输到总线上
                delay(1);                 //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
                if(DQ)                   //控制器进行采样
                        {
                                dat |= 0x80;            //若总线为1,即DQ为1,那就把dat的最高位置1;                               
                        }
                else
                        {
                        dat |= 0x00    ;                                //若为0,与0或,保持为0
                        }
                        delay(10);               //      确保读时序的长度60us,两个读时序之间必须大于1us的间隔时间
        }
                return (dat);
}

void Write_Byte(uchar dat)
{
                uchar i = 0;
                for(i=0;i<8;i++)
                        {
                                DQ=1  ;                                         //        先将数据线拉高
                                   _nop_();                                         //        等待一个时钟周期
                                DQ = 0;                        //拉低总线
                                _nop_();                       //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
                                DQ = dat& 0x01;                 //从字节的最低位开始传输
                                                                       //指令dat的最低位赋给总线,必须在拉低总线后的15us内,
                                                                            //因为15us后DS18B20会对总线采样。
                                delay(10);                     //必须让写时序持续至少60us
                                DQ = 1;                               //写完后,必须释放总线,
                                dat >>= 1;
                                delay(10);                                           //延时7us两个写时序间隔至少1us
                        }
}

uint Get_Tmp()                   //获取温度get the temperature
{
                uchar a=0;
                uchar b=0;
                Init_Ds18b20();                //每一步操作之前都要进行初始化
                Write_Byte(0xcc);          //忽略ROM指令
                Write_Byte(0x44);          //温度转换指令
                Init_Ds18b20();             //初始化
                Write_Byte(0xcc);          //忽略ROM指令
                Write_Byte(0xbe);          //读暂存器指令
                a = Read_Byte();           //读取到的第一个字节为温度LSB
                b = Read_Byte();           //读取到的第一个字节为温度MSB
                temp = b;                      //先把高八位有效数据赋于temp
                temp <<= 8;                    //把以上8位数据从temp低八位移到高八位
                temp = temp|a;                //两字节合成一个整型变量
                tt = temp*0.0625;              //得到真实十进制温度值
                                       //因为DS18B20可以精确到0.0625度
                                       //所以读回数据的最低位代表的是0.0625度
                temp = tt*10+0.5;               //放大十倍
                                                        //这样做的目的将小数点后第一位也转换为可显示数字
                                                //同时进行一个四舍五入操作。
                return temp;
}

/****************数码码动态显示函数**************/

void Display(uint temp)   //显示程序
{
                uchar A1,A2,A3,a;
                A1 = temp/100;    //千位,因为扩大10倍实际中是百位
                a = temp%100         ;
                A2=a/10;   //百位,实际是十位
                A3 = a%10;                          //实际中的小数位
                  //A4 = temp%1000%100%10;

                wela1=1;
                wela2=1;
                wela3=1;
                wela4=1;
               
               
                 //if(A1>0)
               
                P2 = table[A1];    //显示百位
                wela2 = 0;
                delay(200);
                wela2 = 1;
               

                P2 = table1[A2];   //显示十位
                wela3 = 0;
                delay(200);
                wela3 = 1;

                P2 = table[A3];    //显示个位
                wela4 = 0;
                delay(100);
                wela4 = 1;

         /*   P2 = table[A4];    //显示小数位
                wela4 = 0;
                delay(100);
                wela4 = 1;
                */

}

void main()
{
                uint temp0;
                while(1)
                        {
                        temp0 = Get_Tmp()  ;
                         Display(temp0)    ;
                        }
}
上面是源程序,为啥显示会乱码,找了好久都没找到

相关帖子

沙发
希望的叶子|  楼主 | 2015-5-24 00:01 | 只看该作者
另附仿真图,谢谢啦!!!!

QQ图片20150524000041.png (23.09 KB )

QQ图片20150524000041.png

使用特权

评论回复
板凳
ningling_21| | 2015-5-24 10:29 | 只看该作者
希望的叶子 发表于 2015-5-24 00:01
另附仿真图,谢谢啦!!!!

程序里的延时准确吗?

和芯片手册对比一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

63

帖子

0

粉丝