找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5278|回复: 7
收起左侧

DS18B20温度传感器不能读温度,读出来恒定一个数,应该是延时的问题

[复制链接]
ID:503048 发表于 2019-6-26 10:26 | 显示全部楼层 |阅读模式
5黑币
#include<reg51.h>
#include<intrins.h>
#include <ctype.h>       
#include <stdlib.h>       

#define LCD_DATA P0
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
unsigned char dispBuff0[16]={'S','E','T',':',' ','.',' ','V',' ',' ',' ','s',' ',' ',' ',};
unsigned char dispBuff1[16]={'T','E','M','P',':',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};
unsigned char dispBuff2[4]={' ',' ',' ',' ',};
unsigned char dispBuff3[16]={' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',};
unsigned char dispBuff4[16]={'I','N','P','U','T',' ','4','W','E','I',' ','M','I','M','A',};
unsigned char dispBuff5[16]={' ',' ',' ','M','I','M','A',' ','E','R','R','O','R',' ',' ',};

sbit DQ=P2^3;
unsigned int temperature=0;
unsigned int fuhao=0;

sbit LED1=P1^1;
#define off  1
#define on 0

sbit speaker=P1^0;

void Delay20ms() ;
void LCD_WriteDat(unsigned char lcd_dat);
void LCD_WriteCmd(unsigned char lcd_cmd);
unsigned char LCD_ReadStatus(void);
void LCD_Goto(unsigned char x,unsigned char y);
void LCD_Display(unsigned char row,unsigned char *str);

void delay(unsigned int x)
{
        unsigned char j;
        while(x--)
    {
            for(j=0;j<125;j++);
    }
}

void delay1(unsigned int x)
{
           while(--x);
}

char keyscan()
{
        char skey;
        P3 = 0xfe;
        while((P3 & 0xf0) != 0xf0)       
        {
                delay(10);                                
                while((P3 & 0xf0) != 0xf0)       
                {
                        switch(P3)               
                        {
                                case 0xee: skey = '7'; break;
                                case 0xde: skey = '8'; break;
                                case 0xbe: skey = '9'; break;
                                case 0x7e: skey = '+'; break;
                        }
                        while((P3 & 0xf0) != 0xf0);
                }
        }
        P3 = 0xfd;       
        while((P3 & 0xf0) != 0xf0)
        {
                delay(10);
                while((P3 & 0xf0) != 0xf0)
                {   
                        switch(P3)
                        {
                                case 0xed: skey = '4'; break;
                                case 0xdd: skey = '5'; break;
                                case 0xbd: skey = '6'; break;
                                case 0x7d: skey = '-'; break;
                        }
                        while((P3 & 0xf0) != 0xf0);
                }
        }
        P3 = 0xfb;
        while((P3 & 0xf0) != 0xf0)
        {
                delay(10);
                while((P3 & 0xf0) != 0xf0)
                {
                        switch(P3)
                        {
                                case 0xeb: skey = '1'; break;
                                case 0xdb: skey = '2'; break;
                                case 0xbb: skey = '3'; break;
                                case 0x7b: skey = '.'; break;
                        }
                        while((P3 & 0xf0) != 0xf0);
                }
        }
        P3 = 0xf7;
        while((P3 & 0xf0) != 0xf0)
        {
                delay(10);
                while((P3 & 0xf0) != 0xf0)
                {
                        switch(P3)
                        {
                                case 0xe7: skey = '&'; break;
                                case 0xd7: skey = '0'; break;
                                case 0xb7: skey = '*'; break;
                                case 0x77: skey = '#'; break;
                        }
                        while((P3 & 0xf0) != 0xf0);
                }
        }
        return skey;
}

void Delay20ms()
{
        unsigned int tmp = 50000;
        while(tmp--);
}

void LCD_Init(void)
{
        Delay20ms();
        LCD_WriteCmd(0x38);
        LCD_WriteCmd(0x0c);
        LCD_WriteCmd(0x01);
        LCD_WriteCmd(0x06);
        LCD_Goto(0,0);
}

void LCD_WriteDat(unsigned char lcd_dat)
{
        unsigned char tmp;
        tmp = LCD_ReadStatus();
        while((tmp & 0x80))
        {
                tmp = LCD_ReadStatus();
        }
        LCD_RS = 1;
        LCD_RW = 0;
        LCD_DATA = lcd_dat;
        _nop_();
        LCD_EN = 0;
        _nop_();
        _nop_();
        LCD_EN = 1;      
}

void  LCD_WriteCmd(unsigned char lcd_cmd)
{
        unsigned char tmp;
        tmp = LCD_ReadStatus();
        while((tmp & 0x80))
        {
                tmp = LCD_ReadStatus();
        }
        LCD_RS = 0;
        LCD_RW = 0;
        LCD_DATA = lcd_cmd;
        _nop_();
        LCD_EN = 0;
        _nop_();
        _nop_();
        LCD_EN = 1;
}

unsigned char LCD_ReadStatus(void)
{
        unsigned char tmp;
        #if 0
        LCD_RS = 0;
        LCD_RW = 1;
        LCD_EN = 1;
        tmp = LCD_DATA;
        LCD_EN = 0;
        #endif
        LCD_DATA = 0xff;
        LCD_RS = 0;
        LCD_RW = 1;
        LCD_EN = 0;
        _nop_();
        _nop_();
        LCD_EN = 1;
        tmp = LCD_DATA;
        return tmp;
}

void LCD_Goto(unsigned char x,unsigned char y)
{
        unsigned char tmp;
        if(y)
        {
                tmp = 0xc0 + x;
                LCD_WriteCmd(tmp);
        }
    else
    {
                tmp = 0x80 + x;
                LCD_WriteCmd(tmp);
        }               
}

void LCD_Display(unsigned char row,unsigned char *str)
{
        if(row)
        {
                LCD_Goto(0,1);
        }
        else
        {
                LCD_Goto(0,0);
        }
        while(*str != '\0')
        {
                LCD_WriteDat(*str++);
        }
}

int Init_DS18B20()
{
        unsigned char x=0;
        DQ = 1;   
        delay1(1);
        DQ = 0;      
        delay1(30);
        DQ = 1;      
        delay1(5);
        if(DQ==1)
        {
                x=0;
        }
        else
        {
                x=1;
        }
        delay1(30);
        return x;
}

unsigned char ReadOneChar(void)
{
        unsigned char i=0;
        unsigned char dat = 0;
        for (i=8;i>0;i--)
        {
            DQ=1;
                _nop_();
                _nop_();
                _nop_();
                DQ = 0;
            dat>>=1;
                delay(1);
            DQ = 1;
                delay(2);
            if(DQ)
                    dat|=0x80;
            delay(5);
        }
   return(dat);
}

void WriteOneChar(unsigned char dat)
{
        unsigned char i=0;
        for (i=8; i>0; i--)
        {
                DQ = 1;
                _nop_();
                _nop_();
                _nop_();
                DQ = 0;
            DQ = dat&0x01;
            delay(2);
            dat>>=1;
        }
}

void ReadTemperature(void)
{        unsigned char readdata[2]={0,0};
        fuhao=0;
        temperature=0;
        delay(40);
        if(Init_DS18B20()==1)
        {       
                WriteOneChar(0xCC);
                WriteOneChar(0x44);
        }
        delay1(30);
        if(Init_DS18B20()==1)
        {       
                WriteOneChar(0xCC);
                WriteOneChar(0xBE);
        }
        delay1(30);
        readdata[0]=ReadOneChar();
        readdata[1]=ReadOneChar();
        readdata[1]<<=8;
        if (readdata[1]>127)
        {
                readdata[0]^=0xff;
                readdata[1]^=0xff;
                fuhao=1;
        }
        temperature =readdata[1]*256+readdata[0] ;
        temperature =temperature*0.625+0.5;
}

void set()
{
        int i;
        char ckey;
        ckey=keyscan();
        if(ckey=='#')
        {
                delay(10);
                i=1;
                while(1)
                {        ckey=keyscan();
                       
                        if(isdigit(ckey)&&i==1)
                        {
                                 dispBuff2[0]=ckey;
                                i=0;
                                dispBuff0[4]=dispBuff2[0];
                                LCD_Display(0,dispBuff0);       
                        }
                        else if(isdigit(ckey)&&i==0)
                        {
                                dispBuff2[1]=ckey;
                                dispBuff0[6]=dispBuff2[1];
                                LCD_Display(0,dispBuff0);
                                break;       
                        }
                        delay(800);
                }
        }
        if(ckey=='*')
        {
                delay(10);
                i=1;
                while(1)
                {        ckey=keyscan();
                       
                        if(isdigit(ckey)&&i==1)
                        {
                                 dispBuff2[2]=ckey;
                                i=0;
                                dispBuff0[9]=dispBuff2[2];
                                LCD_Display(0,dispBuff0);       
                        }
                        else if(isdigit(ckey)&&i==0)
                        {
                                dispBuff2[3]=ckey;
                                dispBuff0[10]=dispBuff2[3];
                                LCD_Display(0,dispBuff0);
                                break;       
                        }
                        delay(800);
                }
        }               
}

int mima()
{
        int i,a;
        char ckey;
        LCD_Display(0,dispBuff4);
        ckey=keyscan();
        if(ckey=='&')
        {
                delay(10);
                i=0;
                while(1)
                {       
                        ckey=keyscan();
                        if(isdigit(ckey)&&i==0)
                        {
                                 dispBuff2[0]=ckey;
                                i=1;
                                dispBuff3[6]=dispBuff2[0];
                                LCD_Display(1,dispBuff3);       
                        }
                        else if(isdigit(ckey)&&i==1)
                        {
                                dispBuff2[1]=ckey;
                                i=2;
                                dispBuff3[7]=dispBuff2[1];
                                LCD_Display(1,dispBuff3);       
                        }
                        else if(isdigit(ckey)&&i==2)
                        {
                                dispBuff2[2]=ckey;
                                i=3;
                                dispBuff3[8]=dispBuff2[2];
                                LCD_Display(1,dispBuff3);       
                        }
                        else if(isdigit(ckey)&&i==3)
                        {
                                dispBuff2[3]=ckey;
                                i=4;
                                dispBuff3[9]=dispBuff2[3];
                                LCD_Display(1,dispBuff3);
                                break;       
                        }
                        delay(800);
                }
        }
        a=(dispBuff2[0]-'0')*1000+(dispBuff2[1]-'0')*100+(dispBuff2[2]-'0')*10+(dispBuff2[3]-'0');
        return a;
}

void timer0() interrupt 1
{        TH0=254;
        TL0=200;
        speaker=!speaker;
}

void main()
{       
        int a,b,d;
        float c;
        LCD_Init();
        TMOD=0x11;
        TH0=254;
        TL0=200;
        ET0=1;  
        EA=1;
        speaker=1;
        m:d=mima();
        if(d==1234)               
        {        while(1)
                {       
                        delay(10);
                        set();
                        ReadTemperature();
                        if (fuhao)
                        {
                                dispBuff1[5]='-';
                        }
                else
                {
                                dispBuff1[5]='+';
                        }
                        dispBuff1[6]=(temperature/1000)%10+'0';
                        dispBuff1[7]=(temperature/100)%10+'0';
                        dispBuff1[8]=(temperature/10)%10+'0';
                         dispBuff1[9]='.';
                        dispBuff1[10]=(temperature)%10+'0';
                        LCD_Display(0,dispBuff0);
                        LCD_Display(1,dispBuff1);
                        a=dispBuff0[4]-'0';
                        b=dispBuff0[6]-'0';
                        c=a+b*0.1;
                        delay(20);
                        if (temperature>=c*510 && !fuhao)
                        {
                                LED1=on;
                        }
                else
                {
                                LED1=off;
                        }
                        if (temperature>=c*510 && !fuhao)
                {
                                TR0=1;
                        }
                else
                {
                                TR0=0;
                        }
                }
        }
        else
        {       
                LCD_Display(1,dispBuff5);
                goto m;
        }
}



XB]UK4@C2[}C$LMCSY69YZJ.png

最佳答案

查看完整内容

我这个例程是使用过的,没有问题。 有程序main.c: /******************************************************************************* * 实验名 :温度显示实验 * 使用的IO : * 实验效果 :1602显示温度 * 注意 : *******************************************************************************/ #include #include"temp.h" //数码管IO #define DIG P0 sbit LSA=P2^2; sbit LSB=P2^3 ...
回复

使用道具 举报

ID:164602 发表于 2019-6-26 10:26 | 显示全部楼层
我这个例程是使用过的,没有问题。
有程序main.c:
/*******************************************************************************
* 实验名                           :温度显示实验
* 使用的IO             :
* 实验效果       :1602显示温度
*        注意                                         :
*******************************************************************************/

#include<reg51.h>
#include"temp.h"

//数码管IO
#define DIG        P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

unsigned char code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char Num=0;
unsigned int disp[8]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};

void LcdDisplay(int);
void Timer0Configuration();

/*******************************************************************************
* 函数名         : main
* 函数功能                   : 主函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void main()
{
    Timer0Configuration();
        while(1)
        {
                LcdDisplay(Ds18b20ReadTemp());
        }
}

/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能                   : LCD显示读取到的温度
* 输入           : v
* 输出                  : 无
*******************************************************************************/

void LcdDisplay(int temp)          //lcd显示
{

          unsigned char datas[] = {0, 0, 0, 0, 0}; //定义数组
        float tp;  
        if(temp< 0)                                //当温度值为负数
          {
        disp[2] = 0x40;
                //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
                temp=temp-1;
                temp=~temp;
                tp=temp;
                temp=tp*0.0625*100+0.5;       
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上.5,还是在小数点后面。

          }
        else
          {       
        disp[2] = 0;               
                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
                //如果温度是正的那么,那么正数的原码就是补码它本身
                temp=tp*0.0625*100+0.5;       
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。
        }
//    disp[0] = 0;
//    disp[1] = 0;
//    disp[3] = DIG_CODE[temp / 10000];
        disp[4] = DIG_CODE[temp % 10000 / 1000];
        disp[5] = DIG_CODE[temp % 1000 / 100] | 0x80;
        disp[6] = DIG_CODE[temp % 100 / 10];
        disp[7] = DIG_CODE[temp % 10];

}

/*******************************************************************************
* 函数名         : Timer0Configuration()
* 函数功能                   : 设置计时器
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Timer0Configuration()
{
        TMOD=0X02;//选择为定时器模式,工作方式2,仅用TRX打开启动。

        TH0=0X9C;        //给定时器赋初值,定时100us
        TL0=0X9C;       
        ET0=1;//打开定时器0中断允许
        EA=1;//打开总中断
        TR0=1;//打开定时器               
}

/*******************************************************************************
* 函数名         : DigDisplay() interrupt 1
* 函数功能                   : 中断数码管显示
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void DigDisplay() interrupt 1
{
//定时器在工作方式二会自动重装初,所以不用在赋值。
//        TH0=0X9c;//给定时器赋初值,定时1ms
//        TL0=0X00;               
        DIG=0; //消隐
        switch(Num)         //位选,选择点亮的数码管,
        {
                case(7):
                        LSA=0;LSB=0;LSC=0; break;
                case(6):
                        LSA=1;LSB=0;LSC=0; break;
                case(5):
                        LSA=0;LSB=1;LSC=0; break;
                case(4):
                        LSA=1;LSB=1;LSC=0; break;
//                case(3):
//                        LSA=0;LSB=0;LSC=1; break;
//                case(2):
//                        LSA=1;LSB=0;LSC=1; break;
//                case(1):
//                        LSA=0;LSB=1;LSC=1; break;
//                case(0):
//                        LSA=1;LSB=1;LSC=1; break;       
        }
        DIG=disp[Num]; //段选,选择显示的数字。
        Num++;
        if(Num>7)
                Num=4;
}



温度读取程序temp.c:
#include"temp.h"
/*******************************************************************************
* 函数名         : Delay1ms
* 函数功能                   : 延时函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Delay1ms(unsigned int y)
{
        unsigned int x;
        for(y;y>0;y--)
                for(x=110;x>0;x--);
}
/*******************************************************************************
* 函数名         : Ds18b20Init
* 函数功能                   : 初始化
* 输入           : 无
* 输出                  : 初始化成功返回1,失败返回0
*******************************************************************************/

unsigned char Ds18b20Init()
{
        unsigned int i;
    EA = 0;
        DSPORT=0;                         //将总线拉低480us~960us
        i=70;       
        while(i--);//延时642us
        DSPORT=1;                        //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
        i=0;
    EA = 1;
        while(DSPORT)        //等待DS18B20拉低总线
        {
                i++;
                if(i>5000)//等待>5MS
                        return 0;//初始化失败       
        }
        return 1;//初始化成功
}

/*******************************************************************************
* 函数名         : Ds18b20WriteByte
* 函数功能                   : 向18B20写入一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void Ds18b20WriteByte(unsigned char dat)
{
        unsigned int i,j;
    EA = 0;
        for(j=0;j<8;j++)
        {
                DSPORT=0;                        //每写入一位数据之前先把总线拉低1us
                i++;
                DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
                i=6;
                while(i--); //延时68us,持续时间最少60us
                DSPORT=1;        //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
                dat>>=1;
        }
    EA = 1;
}
/*******************************************************************************
* 函数名         : Ds18b20ReadByte
* 函数功能                   : 读取一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/


unsigned char Ds18b20ReadByte()
{
        unsigned char byte,bi;
        unsigned int i,j;
    EA = 0;       
        for(j=8;j>0;j--)
        {
                DSPORT=0;//先将总线拉低1us
                i++;
                DSPORT=1;//然后释放总线
                i++;
                i++;//延时6us等待数据稳定
                bi=DSPORT;         //读取数据,从最低位开始读取
                /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
                byte=(byte>>1)|(bi<<7);                                                  
//                i=4;                //读取完之后等待48us再接着读取下一个数
//                while(i--);
        }
    EA = 1;                               
        return byte;
}
/*******************************************************************************
* 函数名         : Ds18b20ChangTemp
* 函数功能                   : 让18b20开始转换温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void  Ds18b20ChangTemp()
{
        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);                //跳过ROM操作命令                 
        Ds18b20WriteByte(0x44);            //温度转换命令
//        Delay1ms(100);        //等待转换成功,而如果你是一直刷着的话,就不用这个延时了

}
/*******************************************************************************
* 函数名         : Ds18b20ReadTempCom
* 函数功能                   : 发送读取温度命令
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void  Ds18b20ReadTempCom()
{       

        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);         //跳过ROM操作命令
        Ds18b20WriteByte(0xbe);         //发送读取温度命令
}
/*******************************************************************************
* 函数名         : Ds18b20ReadTemp
* 函数功能                   : 读取温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/

int Ds18b20ReadTemp()
{
        int temp=0;
        unsigned char tmh,tml;
        Ds18b20ChangTemp();                                 //先写入转换命令
        Ds18b20ReadTempCom();                        //然后等待转换完后发送读取温度命令
        tml=Ds18b20ReadByte();                //读取温度值共16位,先读低字节
        tmh=Ds18b20ReadByte();                //再读高字节
        temp=tmh;
        temp<<=8;
        temp|=tml;
        return temp;
}



温度读取头文件temo.h:
#ifndef __TEMP_H_
#define __TEMP_H_

#include<reg51.h>

sbit DSPORT=P3^7;

void Delay1ms(unsigned int );
unsigned char Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void  Ds18b20ChangTemp();
void  Ds18b20ReadTempCom();
int Ds18b20ReadTemp();

#endif




适用电路:
1.jpg

1.jpg
1.jpg


回复

使用道具 举报

ID:564898 发表于 2019-6-26 14:32 来自手机 | 显示全部楼层
如果你用的是12M的晶振就把复位里的低电平延时30改成70以上
回复

使用道具 举报

ID:427818 发表于 2019-6-26 23:41 | 显示全部楼层
先占个位置学习
回复

使用道具 举报

ID:207421 发表于 2019-6-27 13:48 | 显示全部楼层
DS18B20 读时序要求特别高,用实际硬件来调调吧,否则都用定时器
回复

使用道具 举报

ID:503048 发表于 2019-6-27 17:44 | 显示全部楼层
青青梓衿 发表于 2019-6-26 14:32
如果你用的是12M的晶振就把复位里的低电平延时30改成70以上

仿真可以读出来温度,但是一烧到单片机上就不行了,单片机是STC89C52
回复

使用道具 举报

ID:503048 发表于 2019-6-27 17:46 | 显示全部楼层
现在仿真可以了,但是同样代码在硬件上不行
回复

使用道具 举报

ID:401564 发表于 2019-6-28 17:03 | 显示全部楼层
仿真是以AT8051的12T指令运行的
STC89C52是6T指令
所有用到延时的延时时间要*2,定时器可以不用改
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表