找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1657|回复: 2
打印 上一主题 下一主题
收起左侧

这个程序问题出在哪里?

[复制链接]
跳转到指定楼层
楼主
ID:105153 发表于 2016-2-17 14:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ds18b20测温,串口发出,但是数据一直不对
#include "INTRINS.H"
#include "REG52.H"       
#define u8 unsigned char
#define u16  unsigned int
typedef unsigned short ushort;
sbit DQ = P2^5;                     //DS18B20的数据口位P2.5
u8 TPH,t,tt;                           //存放温度值的高字节
u8 TPL;                           //存放温度值的低字节
u16 wendu,temp;
void DelayXus(u8 n);
void DS18B20_Reset();
void DS18B20_WriteByte(u8 dat);
u8 DS18B20_ReadByte();



sfr AUXR   =   0x8E;   //0000,0000 辅助寄存器
//****************************************
//函数声明
//****************************************
void delay_x1ms(u16 t);
void InitUART(void);
void Send_UART(u8 send_data);

//****************************************
//                串口初始化
//****************************************
void Delay100ms()                //@11.0592MHz
{
        unsigned char i, j, k;

        _nop_();
        _nop_();
        i = 5;
        j = 52;
        k = 195;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

//9600波特率,无校验,STC15@11M
//不接收,无发送中断,占用T1定时器
//sfr AUXR   =   0x8E;   //0000,0000 辅助寄存器
void UartInit(void)                //9600bps@12.000MHz
{
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
        TL1 = 0xC7;                //设定定时初值
        TH1 = 0xFE;                //设定定时初值
        ET1 = 0;                //禁止定时器1中断
        TR1 = 1;                //启动定时器1
         EA = 1;                 //总中断
        ES = 1;  
}

//****************************************
//                串口发送
//****************************************
void Send_UART(u8 send_data)        //        Send_UART();
{
    SBUF=send_data;
    while(!TI);
    TI=0;
}

//*********************************************************
//主程序
//*********************************************************


void UARTInterrupt(void) interrupt 4
{
    if(RI)
    {
        RI = 0;
    }
    else
        TI = 0;
}





void main()
{        UartInit() ;
   TPL=0;
   while(1)
   {
    DS18B20_Reset();                //设备复位
    DS18B20_WriteByte(0xCC);        //跳过ROM命令
    DS18B20_WriteByte(0x44);        //开始转换命令
    while (!DQ);                    //等待转换完成
    DS18B20_Reset();                //设备复位
    DS18B20_WriteByte(0xCC);        //跳过ROM命令
    DS18B20_WriteByte(0xBE);        //读暂存存储器命令
    TPL = DS18B20_ReadByte();       //读温度低字节
    TPH = DS18B20_ReadByte();       //读温度高字节
        wendu =TPH;                      //先把高八位有效数据赋于wendu
wendu <<= 8;                    //把以上8位数据从wendu低八位移到高八位
wendu = wendu|TPL;                //两字节合成一个整型变量
tt = wendu*0.0625;              //得到真实十进制温度值
                                //因为DS18B20可以精确到0.0625度
                                //所以读回数据的最低位代表的是0.0625度
wendu = tt*10+0.5;               //放大十倍
                             //这样做的目的将小数点后第一位也转换为可显示数字
                                //同时进行一个四舍五入操作。
        Send_UART(wendu);
        Delay100ms();
   Delay100ms();
} }

/**************************************
延时X微秒(STC12C5A60S2@12M)
不同的工作环境,需要调整此函数
此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
**************************************/
void DelayXus(u8 n)
{
    while (n--)
    {
        _nop_();
        _nop_();
    }
}

/**************************************
复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
    CY = 1;
    while (CY)
    {
        DQ = 0;                     //送出低电平复位信号
        DelayXus(240);              //延时至少480us
        DelayXus(240);
        DQ = 1;                     //释放数据线
        DelayXus(60);               //等待60us
        CY = DQ;                    //检测存在脉冲
        DelayXus(240);              //等待设备释放数据线
        DelayXus(180);
    }
}

/**************************************
从DS18B20读1字节数据
**************************************/
u8 DS18B20_ReadByte()
{
    u8 i;
    u8 dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        dat >>= 1;
        DQ = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        DQ = 1;                     //准备接收
        DelayXus(1);                //接收延时
        if (DQ) dat |= 0x80;        //读取数据
        DelayXus(60);               //等待时间片结束
    }

    return dat;
}

/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte(u8 dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        DQ = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        dat >>= 1;                  //送出数据
        DQ = CY;
        DelayXus(60);               //等待时间片结束
        DQ = 1;                     //恢复数据线
        DelayXus(1);                //恢复延时
    }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:105146 发表于 2016-2-18 01:05 | 只看该作者
很少有人能有时间看完这么长的程序,DS18B20的时序要求很严格,自己多调整一下延时时间试试吧!
回复

使用道具 举报

板凳
ID:74145 发表于 2016-2-19 13:28 | 只看该作者
同意楼上  一步一一步调试  DS18b20的时序要求较为严格。网上的例程也有很多  参考一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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