51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机源码 > 详细内容
1-wire总线 (C51)
发布时间:2009/6/2  阅读次数:1102  字体大小: 【】 【】【

作者:jjmgj    来源:本站

#include<reg52.h>
#include<absacc.h>
#include <string.h>
#include <stdio.h>
#include<math.h>
///////////////////////
/*自定义结构变量说明 */
#define uint unsigned int
#define uchar unsigned char
//sbit DQ=P1^0;//DS2450
sbit lcd_en=P2^7;//液晶片选控制信号线

/*系统数据线和变量定义*/
sbit DQ=P1^1;       //DS18b20通信线

uchar tplsb,tpmsb;  // 温度值低位、高位字节 缓存区
bit fhao ;//保存温度是正数还是负数
uchar TMP[5]; //四个温度数据的缓存区

uchar code serial_number[4][8]={0x28,0x08,0x85,0x11,0x01,0x00,0x00,0xba, //一号18b20ROM号
                                                               0x28,0xbe,0x86,0xe9,0x00,0x00,0x00,0x87, //二号
                           0x28,0x11,0xc4,0xe9,0x00,0x00,0x00,0x95,//三号
                                                               0x28,0xf5,0x12,0x0c,0x01,0x00,0x00,0xc1,//四号
                           }; //四个18b20的八字节序列号数据

/*************************/
/* 延时t毫秒子程序 */
/* 延迟 tms 在11。0592M晶正时候
/**************************/
void delay(uint t)
{
       uchar i;//这里不可以改为uint

  while(t--)
  {
    /* 对于11.0592M时钟,约延时1ms */
    for (i=0;i<123;i++)
                     ;
  }//
}

//****************************************/
//功能:复位单总线并且检测应答脉冲/
//有响应则返回0,否则进入死循环
//****************************************/
bit TxReset1(void)
{
       bit presence;     //检测存在脉冲位缓寸位
      
       uchar i;         //延迟循环变量,这里也不可以改为uint 类型
  DQ = 0;         //数据位

  /* 拉低约502us */
  i = 250;                 //keilc里通过定时器测定 502us
  while (i>0)  i--;  

       DQ = 1;  // 产生上升沿释放总线

       while(DQ);         //检测器件拉低信号,如果没有拉低则等待,拉低则往下走

       presence=DQ;       //读取总线响应低电平
    
       i=200;                 //主机接受存在脉冲保证480us
   while (i>0)  i--;   //keil c 的定时器测得约为482us
      
  return (presence);


}

/**********************************/
/*   作用:返回单总线上读取的一位数据/
/**********************************/
bit RdBit(void)
{
  uchar   i;
  bit b;
  DQ = 0;               //拉低总线开始读时隙
  i++;                     //   medwin li 2us
       DQ=1;                   //主机释放总线后, 单线器件立即输出数据
       i++;i++;       // 读时隙下降沿后15us内,DS18B20输出数据才是有效的,过后就没有效果了
                                     //上面这两句i++ 没有也可以,测试通过 ,有这两句是给单线器件一个准备间隙
                                     //这两句在 medwin 里延时间 4us
  b = DQ;               //主机读取总线上数据 ,主机必须在15us内 完成: 大于1 us 的拉低总线(开始时隙)
  i = 30;               //并且释放总线后(单线器件开始输出数据) 读取单线器件输出的数据    
  while(i>0) i--;//一个读时隙至少持续60us
                                     //i=30 keil c中约为62us
  return (b);

}


/***********************************/
/* 读取数据的一个字节
/*作用:从单总线器件读取一个字节
/*所有的单总线协议操作的命令和
/*控制字都是低位字节在前面的
/** *******************************/
uchar RdByte(void)
{
  uchar i,j,b;
  b = 0;
  for (i=1;i<=8;i++)
  {
    j = RdBit();
    b = (j<<7)|(b>>1); //读取一位存储到b的的最高位,8次后得一字节数据
                               /*按照上面的原则每次读取一位后放到b的最高位 ,8次后获得一个字节 */
  }
  return(b);
}


/********************************************/
/*本程序实现空制器向单总线写一个字节*********/
/* 写数据的一个字节,满足写1和写0的时隙要求 */
/********************************************/
void WrByte(uchar b)
{
  uchar i;
  uchar j;
  bit btmp;
  for(j=1;j<=8;j++)
  {
    btmp = b&0x01;
    b = b>>1;    // 取下一位(由低位向高位)
    if (btmp)
    {
      /* 写1 */
      DQ = 0;
      i++;i++;  // 延时,使得15us以内拉高
      DQ = 1;
      i =35;
      while(i>0) i--;  // 整个写1时隙不低于60us
                                     //keil c里72us
         }
    else
    {
      /* 写0 */
      DQ = 0;       
      i =35;       //keil c 里为72us
      while(i>0) i--;  // 保持低在60us到120us之间
      DQ = 1;
      i++;
      i++;
    }
  }
}

/******************/
/* 启动温度转换 */
/*****************/
void convert(void)
{
       while(TxReset1());     //检测存在脉冲
       delay(1);      // 延时   延迟时间也可以的
  WrByte(0xcc);    // skip rom 命令
  WrByte(0x44);    // convert T 命令
}


/**********************/
/* 读取温度值 ********/
/*保存于两个全局变量中
/**********************/
void RdTemp(void)
{
  
  while(TxReset1());   //检测存在脉冲
  delay(1);      // 延时1ms     不延迟时间也测试通过
  WrByte(0xcc);    // skip rom 命令
  WrByte(0xbe);    // read scratchpad 命令
  tplsb = RdByte();  // 温度值低位字节(其中低4位为二进制的“小数”部分)
  tpmsb = RdByte();  // 高位值高位字节(其中高5位为符号位)    
}


/*************************************************/
/* 本程序的作用是把从DS18B20读出的两字节的二进制数值
/* 合并为一个字节是十进制数值并且返回合并的结果
/**************************************************/

uchar   bian_to_dec(void)
  {
    
     uchar temp1,temp2,temp3;
     uchar t; //存返回结果的变量
    
     temp1=tplsb ;//温度的低8位数据
     temp2=tpmsb; //温度高8位数据
     temp3=tpmsb;//温度高8位数据
     temp3=temp3>>4;//取得温度的符号位数据
    
     //*********************************
     //两个字节数据合并处理
     //将两个自字节数据合并为一个字节数据
     ///********************************
   if(temp3==0)//温度为正
   {
     fhao=0;
       t=((temp1>>4)|(temp2<<4));
       temp1=(temp1&0x0f);//取得温度数值的小数部分
       if(temp1>8)
       t=t+1;  
  
   }
  else
   {
     fhao=1;//温度为负数
   temp1=temp1>>4;
   temp2=temp2<<4;
   t=temp1|temp2;
   t=~t+1;//反码加一为原码
    
   }
  
  return t;
    
  }

////////////////////读取一根线上的四个18B20的温度////////////////////
////
//// 功能: 读取P1.0口上的四个18B20的温度,保存在全局数组TMP中
////
////////////////////////////////////////////////////////////////////
void read_4_18b20()
{

   uchar i,j;
   while(TxReset1());   //返回1 则继续复位,直到检测到低电平的应答脉冲则向下执行
   WrByte(0xcc);//SKIP ROM,不发送ROM命令则要发送跳过ROM命令(0xcc)
   WrByte(0x44);//命令单总线上的所有器件开始转换
   delay(3); //一般转换要750us,这里等待3ms足够
  
  for(j=0;j<4;j++) //读取转换后的四个温度
   {
       while(TxReset1());       //返回1 则继续复位,直到检测到低电平的应答脉冲则向下执行
       //delay(1);
       WrByte(0x55);//ROM匹配
       for(i=0;i<8;i++)
         WrByte(serial_number[j][i]);//ROM匹配
         ///注意:发送序列号后,只有匹配的18B20才会对接下来的命令响应
               WrByte(0xbe);  // read scratchpad 命令
    tplsb = RdByte();  // 温度值低位字节(其中低4位为二进制的 小数部分
    tpmsb = RdByte();  // 高位值高位字节(其中高5位为符号位)
    TMP[j]=bian_to_dec();   //读取第二个18b20的温度
     }
  }

//主程序调用就可以读到比较准确的温度了。

//这里只是拷贝了一个文件,不过这样可以读取一个或者多个DS18B20的温度了,

我也是刚刚学单总线的,希望高手指导。

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号