cpubbs论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

LabVIEW+单片机学习套件全套教程资料下载[免费]LabVIEW论坛精华列表贴USB0816数据采集卡《LabVIEW宝典》
LabWindows/CVI论坛精华贴NET0816以太网数据采集卡RC0210远程设备授权系统 关闭关停锁定打开设备 户外分布式数据采集
NET1624低速高精度以太网数据采集卡WIFI0824SD无线WIFI网络数据采集卡脱机运行 SD存储 小尺寸微型 串口采集远程采集 安卓 手持移动采集 纪录仪
查看: 3073|回复: 6

请版主指点:使用第一代开发板 学习使用DS18B20,可是每次读数是16度。请看代码

[复制链接]
发表于 2007-8-24 12:46:29 | 显示全部楼层 |阅读模式
反复调试了很多遍,就是没有发现错误.
估计主要问题 自己用的延时与 开发者使用的延时程序不一致...
请版主指点.


//当主机把数据线从高逻辑电平拉至低逻辑电平时产生写时间片有两种类型的写时间片写
//1 时间片和写0 时间片所有时间片必须有最短为60 微秒的持续期在各写周期之间必须有最短
//为1 微秒的恢复时间
//在I/O 线由高电平变为低电平之后DS1820 在15 s 至60 s 的窗口之间对I/O 线采样如果
//线为高电平写1 就发生如果线为低电平便发生写0

#include <AT89X55.H>                        //单片机头文件包含文件
#include <absacc.h>                        //单片机头文件包含文件
#include <intrins.h>                        //单片机头文件包含文件
#define uchar unsigned char
#define uint unsigned int
uchar flag=1;
//#define ulong unsigned long
sbit DQ =P3^6;                                 //定义通信端口
uchar temp_command;                        //接受上位机命令
uchar data_convert[4];
//_______________________
void delay(uchar x)
{while(--x);                                //延时 xus
}
//若参数采用uchar那么调度为2us
//delay(0):延时518us 518-2*256=6
//delay(1):延时7us
//delay(10):延时25us 25-20=5
//delay(20):延时45us 45-40=5
//delay(100):延时205us 205-200=5
//delay(200):延时405us 405-400=5
//_________________________
void init_ds18b20(void)//从高拉低保持至少480us,然后再拉高保持15us-60us;ds18b20发出低电平存在脉冲60-240us
{//        uchar x;
        DQ=1;
        delay(5);//delay for a slight while
        DQ=0;
        delay(0);        //518us
        DQ=1;
        delay(14);
        flag=DQ;                //        判定是否初始成flag?=0,则成功
        delay(20);

}
uchar read_onechar_ds18b20(void)                //读指令,是拉高再拉底至少保持1us,再拉高;实现读
{
        uchar tdata=0;
        uchar i=0;
//        DQ=1;
        for(i=8;i>0;i--)
        {
        DQ=1;
        delay(1);
        DQ=0;
        tdata>>=1;
        DQ=1;                                        //再次拉高
        if (DQ)
                tdata|=0x80;                //右移,与高位or,执行8次后,第一位移到最低位了
        delay(4);
        }                        //读指令之间需要 建立时间
        return(tdata);
}
void write_onechar_ds18b20(uchar command_data)        //?/数据线从高电平拉至低电平,产生写起始信号。15ms之内将所需写的位送到数据据线上
{
        uchar i=0;
        DQ=1;
        for(i=8;i>0;i--)
        {
                DQ=0;                        //拉低
                //delay(1);                //相当于7us
                DQ=command_data & 0x01;
                delay(15);                //保持一定时?0us
                DQ=1;                        //拉高
                command_data>>=1;                        //右移灰晃?
        //        delay(4);                //写指令间需要恢复时间
}

}
uchar read_temp(void)
{
        uchar templow;
        uchar temphigh;
        uchar tt;
        //float t;                        //温度值
        init_ds18b20();                        //初始化
//        if(flag)                                //若未初始化成功,继续初始化
//                {
//                init_ds18b20();
//                while(flag<>0)
//                {
//                init_ds18b20();
//                }
//                }

        write_onechar_ds18b20(0xCC);        //单片操作,跳出读序列号操作
        write_onechar_ds18b20(0x44);        //启动温度转换
        delay(125);                                                //convert needs time
        init_ds18b20();                        //复位
        write_onechar_ds18b20(0xCC);
        write_onechar_ds18b20(0xBE);        //读温度寄存器,分高位和低位
        templow=read_onechar_ds18b20();//read lsb
        temphigh=read_onechar_ds18b20();//read msb
        //t=(temphigh*256+templow)*0.0625;//温度转化
        tt=temphigh;
        tt=tt<<8 ;
        tt|=templow;
        return(tt);
}
void s_data_convert(uint data_to_convert)//转换数据便于发送给上位机
{        data_convert[0]=(uchar)((data_to_convert&0xf000)>>12);
        data_convert[1]=(uchar)((data_to_convert&0x0f00)>>8);
        data_convert[2]=(uchar)((data_to_convert&0x00f0)>>4);
        data_convert[3]=(uchar)(data_to_convert&0x000f);
}
void init_serial(void)
//串口初始化
{
        TMOD=0x20;                                //model 2,T1
        TH1=0xfd;                                //baud rate is 9600,11.0592HZ
        TL1=0xfd;
//        TCON=0x40;                                //start T1
        SCON=0x50;                                //receive permission
        PCON=0x00;
//        IE=0x99;                                //enable EA,ES,ET1,EX0
    ES=1;     
        EA=1;
        TR1=1;
}
void read_serial(void) interrupt 4
{
        RI =0;                                        //RI=0接受数据
        ES=0;                                        //关闭所有中断
        temp_command=SBUF;                        //接受命令,是否开始转换温度
        ES=1;                                        //接受完,打开所有中断
}

void main(void)
{        uint temp;
        uchar i;
        init_serial();
while(1)
{
       
        while(temp_command!=0x11);        //0x11定义为开始标志
        temp_command=0;                        //清楚标志;
        temp=read_temp();                //读温度
        s_data_convert(temp);       
        for(i=0;i<4;i++)
                {
                        SBUF=data_convert;
                        while(TI==0);        //等待传送数据
                        TI =0;
                }
}
}
发表于 2007-8-24 12:57:04 | 显示全部楼层
您好,单总线的时序要求非常严格,延时稍作改变也会导致不能工作,包括晶振也不能更换不同频率的,只要注意好这二点,用我们学习套件是肯定能工作的,您放心,另外兄弟这个问题可以发到咱们的产品区,这个CPUVIEW区是图形化单片机区,呵呵,发到产品区更易于解答,谢谢您,好运!
 楼主| 发表于 2007-8-24 13:40:10 | 显示全部楼层
哈哈,
谢谢。。 才上论坛。 麻烦版主移到另外区域。
时许,我也是按照ds18b20来写的。
只是采用的延时程序不同。
你们给的程序是可以实现功能,但是我自己修改了,结果就出错。。。
不知道错在哪里。。 ??
发表于 2007-8-24 14:01:09 | 显示全部楼层
如果兄弟您改变了延时,哪应该就是延时的问题,您还是不要修改了,这个程序的确要求较为严格,改变的意义不大,直接用这个已经调试好的即可,因为这个时间是能适合的,您放心使用的兄弟!
 楼主| 发表于 2007-8-25 09:48:42 | 显示全部楼层
那请教您程序中一些具体细节:
(1)
void delay(unsigned int i)                //延时函数
{
        while(i--);
}
这个程序没执行一次 延时多少us??
(2)
在您的延时程序中
delay(80);                         //精确延时 大于 480us
为什么delay(80) 就可以延时> 480us,难道delay这个函数 每调度一次 耗 6--8us? 那么后面 读写的时序如何保证呢???

(3)关于读ds18b20
应是拉高再拉低至少保持1us,再拉高;实现读
您的程序如下,为什么没有一个从高到低再到高的过程??
__

uchar ReadOneChar(void)                        //读一个字节
{
        unsigned char i=0;
        unsigned char dat = 0;
        for (i=8;i>0;i--)
        {
                DQ = 0;                 // 给脉冲信号
                dat>>=1;
                DQ = 1;                 // 给脉冲信号
                if(DQ)
                dat|=0x80;
                delay(4);
        }
        return(dat);
}

(4)关于写ds18b20. 应是拉高 再拉低,再写 0 或者1
为什么您的程序 没有一个初始化 拉高呢?
请看您的程序
void WriteOneChar(unsigned char dat)        //写一个字节
{
        unsigned char i;
        for (i=8; i>0; i--)
        {
                DQ = 0;
                DQ = dat&0x01;
                delay(5);
                DQ = 1;
                dat>>=1;
        }
        //delay(4);
}


     偶是初学者,没有使用过 数字化的产品,所以在读时序存在很多疑问;请指教。

如果能指出我程序中的问题,那就太感谢您了。
发表于 2007-8-25 14:17:36 | 显示全部楼层
兄弟,这个程序有些部分是直接用他们提供的汇编,然后对照着弄过来的(当时大学实验室有一个项目,其中一个组员去弄的),兄弟没有必要去再重新弄一次的,这样浪费您学习更多东西的时间!好运!如果您的时间调得不对,这样就不能操作的,您可以将它汇编成汇编语言就能看到它有多少条指令,就知道它的时间了!好运!

[ 本帖最后由 cpubbs 于 2007-8-25 18:20 编辑 ]
发表于 2007-10-10 21:29:42 | 显示全部楼层
你好兄弟,我插个题外话。试用一下CPUVIEW,你会有意外的收获。C51和CPUVIEW的区别就象早期的Baice语言和VBasice(VB,可视化编程)一样。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cpubbs论坛. ( 粤ICP备09171248号 )

GMT+8, 2024-5-18 20:25 , Processed in 0.480913 second(s), 8 queries , Gzip On, File On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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