当前位置:技术文章首页 >> 单片机源码 >> 1-wire总线

1-wire总线

1970-01-01 08:00:00  作者:jjmgj  来源:本站原创  浏览次数:666  文字大小:【】【】【

#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的温度了,

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

责任编辑:


相关文章
 

最新文章

更多

· 最新10位数字温度传感器...
· AT45D081/AT45DB021/AT4...
· X24C44一款老的EEPROM,(...
· 93C46/93c06/93c46/93c5...
· 128x64液晶KS0108控制器...
· 本站液晶程序里使用的ab...
· DS1302驱动程序(C51)
· 学习GCC Complete Refer...
· 农历转换函数(C语言版)
· 基于WinAVR的DS18B20源程序

推荐文章

更多

· 最新10位数字温度传感器...
· AT45D081/AT45DB021/AT4...
· X24C44一款老的EEPROM,(...
· 93C46/93c06/93c46/93c5...
· 128x64液晶KS0108控制器...
· 本站液晶程序里使用的ab...
· DS1302驱动程序(C51)
· 学习GCC Complete Refer...
· 农历转换函数(C语言版)
· 基于WinAVR的DS18B20源程序

热点文章

更多

01-01·[接口与通讯] 红外遥控系统原理及单片机软... (3804)
01-01·[单片机技术] 温度传感器PT100的应用 (2424)
09-17·[可编程逻辑] 基于VHDL语言的智能密码锁设计 (1984)
09-08·[可编程逻辑] 基于FPGA的QPSK调制解调电路... (1973)
09-08·[单片机技术] AT89S52的中文简介及资料下载 (1909)
11-24·[电子基础] 与初学者谈电子制作(电子入门) (1789)
09-09·[电源技术] 基于DSP的三相SPWM波发生软件... (1789)
10-24·[传感与控制] MODBUS RTU通讯协议在S7-200... (1612)
12-01·[单片机技术] 基于ARM智能家居控制器设计与... (1612)
11-24·[单片机技术] 常用LED数码管驱动电路2(单 ... (1601)
09-08·[电源技术] 能延长电池寿命的单节电池升... (1537)
09-11·[仪器与仪表] 应用ADuC847芯片设计压力及温... (1520)