找回密码
 立即注册

QQ登录

只需一步,快速开始

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

使用AVR来驱动MAXIN的DS18B20

[复制链接]
跳转到指定楼层
楼主
ID:51090 发表于 2014-9-17 02:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
   我最近正在研究使用AVR来驱动MAXIN的DS18B20,琢磨了几天,终于把它的驱动程序写好了.
   使用IAR C++编译器
#ifndef DS18B20_H
#define DS18B20_H
/****************************************只需在源程序里定义以下宏
#define seDDS()  (seDB0())
#define clDDS()  (clDB0())
#define seDS()   (sePB0())
#define clDS()   (clPB0())
#define GetDS()  (GetPB0())
*********************************************/
/***********************************   函数说明  *********************
void DS18B20::DS18B20(void) 构造函数
void DS18B20::init()初始化DS18B20
char DS18B20::GetID()读取器件ID,成功返回1,并且器件的64位id号保存到DS18B20.id[4],里,失败返回0
char DS18B20::convter()读取温度,成功返回1,并且温度值保存到DS18B20.temp里,未就绪返回0。此程序需要调用数次才能正确转换
                       调用周期不得低于2ms
char DS18B20::GetPower()读取总线供电模式,正常返回1,寄生返回0
char DS18B20::SearchAlarm()读取报警,有报警返回1,没有返回0

****************************************************/
#define DS_ReadROM     0x33
#define DS_CopyROM     0x48
#define DS_MatchROM    0x55
#define DS_SkipROM     0xCC
#define DS_SearchROM   0xF0
#define DS_AlarmSearch 0xEC
#define DS_Convert     0x44
#define DS_ReadRAM     0xBE
#define DS_WriteRAM    0x4E
#define DS_ReadPower   0xB4
#define DS_9BIT           0
#define DS_10BIT          1
#define DS_11BIT          2
#define DS_12BIT          3
#include "c:\inc\status.h"
#include "c:\inc\crc8.c"
#include "c:\inc\delay.c"
#include "c:\inc\format.h"
#include <stdio.h>

class DS18B20
{
public:

  float temp;//           温度  
  int rel;//              温度偏移量
  char id[8];//           器件ID号
  char mode;//            转换模式9-12bit
  unsigned char TH;//     预警温度上限
  unsigned char TL;//     预警温度下限
  char power;//           0:寄生供电  1:电源供电
  char status;//          单线总线状态0: 无连接  1:已连接
  char sbuf[10];

private:

  char setup;
/****************************************复位总线***********************/
  char Reset_DS()
  {
    unsigned int x;
    seDS();
    seDDS();
    DELAY_80us();
    if(GetDS())
    {
      clDS();
      DELAY_600us();
      seDS();
      clDDS();
      for(x=0;x<30;)
      {
        if(GetDS())x++;
        else
        {
          for(x=0;x<30;)
          {
     if(GetDS())
            {
        seDDS();
        DELAY_600us();//
        return 1;
     }
     else
       x++;
            DELAY_10us();
   }
   clDDS();
   return 0;
        }
        DELAY_10us();//
      }
    }
    clDDS();
    return 0;
  }
/**************************************************写总线*******************/
  void Write_DS(unsigned dat,unsigned char wide)// dat:数据  wide:数据宽度(位数)
  {
    unsigned char i,sreg;
    seDDS();
    for(i=0;i<wide;i++)
    {
      sreg=SREG;
      SREG&=0x7F;//                      关中断
      if(dat&0x01)
      {
        clDS();
        DELAY_10us();
seDS();
        DELAY_80us();
      }
      else
      {
        clDS();
        DELAY_80us();
seDS();
        DELAY_10us();
      }
      SREG=sreg;//                       恢复中断 发生的中断将依次执行
      dat>>=1;
    }
  }
/***************************************************读总线*******************/
  unsigned char Read_DS(unsigned char wide)
  {
    unsigned char dat,i,sreg;
    for(i=dat=0;i<wide;i++)
    {
      if(GetDS())
      {
        sreg=SREG;
        SREG&=0x7F;
        clDS();
        seDDS();
        DELAY_10us();
        seDS();
        clDDS();
        dat>>=1;
        DELAY_10us();
        if(GetDS())dat|=0x80;
        seDDS();
        SREG=sreg;
        DELAY_80us();
      }
      else
      {
        setup=0;
      }
    }
    return dat;
  }

  char getid()
  {
    char i;
    for(i=0;i<sizeof(id);i++)
      if(id)
        return 1;
    return 0;
  }
public:
  char convert()//                           本程序调用周期至少2ms或以上
  {
    static unsigned char sbuf[9];
    static unsigned int i;
    switch(setup)
    {
    case 0:
      if(Reset_DS())//                   开始
      {
        status=1;
        setup++;
      }
      else
status=0;
      break;
    case 1:
      if(getid())
      {
        Write_DS(DS_MatchROM,8);//       匹配ROM
        for(i=0;i<8;i++)
          Write_DS(id,8);
      }
      else
      {
        Write_DS(DS_SkipROM,8);//       跳过匹配
      }
      Write_DS(DS_Convert,8);//         启动转换
      i=power?0:500;//         选择电源方式,以达到最快速度
      setup++;
      break;
    case 2:
      if(i)//                           延时
      {
        i--;
      }
      else if(Read_DS(8)==0xFF)//       等待转换结束
      {
        Reset_DS();
        if(getid())
        {
          Write_DS(DS_MatchROM,8);//    匹配ROM
          for(i=0;i<8;i++)
            Write_DS(id,8);
        }
        else
          Write_DS(DS_SkipROM,8);
        Write_DS(DS_ReadRAM,8);
        i=0;
        setup++;
      }
      break;
    case 3:
      sbuf=Read_DS(8);
      if(i>=9)
      {
        Reset_DS();
        if(GetCRC8(sbuf,8)==sbuf[8])//                    校验CRC
        {
          int i;
          i=sbuf[1]*0x100+sbuf[0];
          i+=rel;
          temp=i/16+(i%16)*0.125;
          setup=0;
          status=1;
          return 1;
        }
        setup=0;
      }
      break;
    }
    return 0;
  }
  char GetPower()
  {
    unsigned char x;
    if(Reset_DS())
    {
      Write_DS(DS_SkipROM,8);
      Write_DS(DS_ReadPower,8);
      x=Read_DS(8);
      Reset_DS();
      if(x)
        return 1;
    }
    return 0;
  }
/*************************************预警搜索****************************/
  char SearchAlarm()
  {
    if(Reset_DS())
    {
      Write_DS(DS_AlarmSearch,8);
      if(Read_DS(2)==0x80)//      读两个位
      {
        Reset_DS();
return 1;
      }
    }
    Reset_DS();
    return 0;
  }
//TH:高温限制  TL:低温限制   
//mode:转换模式  0:9bit(93.75ms)  1:10bit(187.5ms)  2:11bit(375ms)  3:12bit(750ms)  
//power:总线的电源模式
//ID:器件ID号
  char init()
  {
    unsigned char i,sbuf[9];
    if(Reset_DS())
    {
      if(getid())
      {
Write_DS(DS_MatchROM,8);
for(i=0;i<8;i++)
   Write_DS(id,8);
      }
      else
        Write_DS(DS_SkipROM,8);
      Write_DS(DS_WriteRAM,8);
      Write_DS(TH,8);
      Write_DS(TL,8);
      Write_DS(((mode&0x03)<<5)|0x1F,8);
      Reset_DS();
      if(getid())
      {
Write_DS(DS_MatchROM,8);
        for(i=0;i<8;i++)
   Write_DS(id,8);
      }
      else
        Write_DS(DS_SkipROM,8);
      Write_DS(DS_ReadRAM,8);
      for(i=0;i<9;i++)
        sbuf=Read_DS(8);
      if(GetCRC8(sbuf,8)==sbuf[8])//  校验CRC
      {
        if(sbuf[2]==TH&&sbuf[3]==TL)
        {
          Reset_DS();
          if(getid())
          {
            Write_DS(DS_MatchROM,8);
            for(i=0;i<8;i++)
                Write_DS(id,8);
          }
          else
            Write_DS(DS_SkipROM,8);
          Write_DS(DS_CopyROM,8);
          DELAY_200ms();
          Reset_DS();
          power=GetPower();
          Reset_DS();
          return 1;//                 完成
        }
      }
    }
    return 0;
  }
/*********************************************读取DS18B20的64位ROM******************/
  char GetID()
  {
    unsigned char i;
    unsigned char sbuf[8];
   if(Reset_DS())
   {
     Write_DS(DS_ReadROM,8);
     for(i=0;i<8;i++)
     {
       sbuf=Read_DS(8);
     }
     Reset_DS();
     if(GetCRC8(sbuf,7)==sbuf[7])//   校验CRC
     {
       for(i=0;i<8;i++)
         id=sbuf;//    拷贝数据到ROM
       return 1;
     }
   }
   return 0;
  }

  char* disp(char width=0)
  {
    int i=(int)temp;
    int j=(int)(temp*10);
    j%=10;
    if(temp<0)
      j=0-j;
    switch(width)
    {
    case 2:
      sprintf(sbuf,"%2d.%d",i,j);
      break;
    case 3:
      sprintf(sbuf,"%3d.%d",i,j);
      break;
    default:
      sprintf(sbuf,"%d.%d",i,j);
      break;
    }
    return sbuf;
  }

  DS18B20()
  {
    format(id,sizeof(id),0);
    mode=DS_12BIT;
    TH=100;
    TL=0;
    power=0;
    rel=0;
    status=0;
    setup=0;
    seDDS();
    seDS();
  }
};
#endif

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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