搜索
bottom↓
回复: 3

关于DS18B20的驱动,请各位前辈斧正,小菜鸟一枚

[复制链接]

出0入0汤圆

发表于 2012-11-8 15:13:39 | 显示全部楼层 |阅读模式
本帖最后由 czp123123 于 2012-11-8 15:18 编辑

DS18B20的时隙非常重要,我有点把握不好,在什么时候延时多长时间有点糊涂,请大家斧正下面的驱动程序,主要是延时和延时函数,每个延时函数各延时多长时间也是蒙的,
给点好的建议,本人在校学生,希望在做项目的前辈们给点建议,谢谢大家了。。。/********************************************************************/
/********************************************************************/
/********************************************************************/

#include<iom16v.h>
#include<macros.h>
/*****一些宏定义*******/
#define DS18B20_PIN                 PD4
//PA7输出
#define        DS18B20_PIN_SET_OUT()        DDRD|=(1<<DS18B20_PIN)   
//PA7输入
#define DS18B20_PIN_SET_IN()        DDRD&=~(1<<DS18B20_PIN)
//PA7拉高   
#define        DS18B20_WR1()                        PORTD|=(1<<DS18B20_PIN)       
//PA7拉低
#define        DS18B20_WR0()                        PORTD&=~(1<<DS18B20_PIN)
  //读取PA7的电平
#define        R_DS18B20()                                PIND&(1<<DS18B20_PIN)       
//跳过ROM
#define        SKIP_ROM                                0xCC      
//转换温度
#define        CONVERT_TEM                                0X44
//读取暂存器RAM
#define        READ_RAM                                0XBE


/***延时函数us级***/
void delay_us(unsigned int i)
{
         while(i--);
}


/***延时函数ms级*******/
void delay_ms(unsigned int i)
{
         unsigned int a;
         unsigned char b;
         for(a=0;a<i;a++)
                 for(b=1;b;b++);
}


/****DS18B20的复位初始化****/
void DS18B20_start()
{
         unsigned char i;
         DS18B20_PIN_SET_OUT;                    //置位输出口
         DS18B20_WR0;                        //总线产生下降沿,初始化开始
         for(i=0;i<20;i++)delay_us(25);        //总线保持低电平在480—960微妙之间
         
         DS18B20_WR1();                         //总线拉高,主机释放总线,准备接收DS18B20的应答脉冲
         DS18B20_PIN_SET_IN();                  //配置为输入
         
         delay_us(20);                           //DS18B20检测到总线上升沿后等待15—60微秒
         while(R_DS18B20);                     //等待DS18B20发出应答脉冲
         while(!R_DS18B20);                       //DS18B20发出存在脉冲,持续60—240微妙
         delay_us(20);
         
         DS18B20_PIN_SET_OUT();                 //置为输出口
         DS18B20_WR1();                         //主机释放总线
}


/********向DS18B20中写入一字节的数据或命令**************/
void DS18B20_send(unsigned char temp)
{
         unsigned char i;
         for(i=0;i<8;i++)
         {
                  DS18B20_WR0();                   //总线拉低,启动“写时间片”
                delay_us(2);                        //延时大于1微秒
                if(temp&0x01)DS18B20_WR1();           //该位为1的话就拉高总线写1
               
                delay_us(22);                     //延时至少60微秒,使写入有效
                delay_us(22);
                delay_us(22);
               
                DS18B20_WR1();                     //总线拉高,释放总线,准备启动下一个“写时间片”
                temp>>1;                            //右移一位
                delay_us(1);               
         }
}


/***********从DS18B20中读取一个字节的数据*****************/       
void DS18B20_read()
{
         unsigned char temp;
         for(i=0;i<8;i++)
         {
                  temp>>1;                           //表明从高位读取
                DS18B20_PIN_SET_OUT();             //置为输出口
                DS18B20_WR0;                      //总线拉低,启动读时间片
                delay_us(2);                 
               
                DS18B20_WR1();                      //总线拉高,主机释放总线,接下来2-15微秒读有效
                DS18B20_PIN_SET_IN();               //端口置为输入
                delay_us(2);
               
                if(R_DS18B20())temp|=0x80;            //先读高位,为1的话就置1,为零的话不动,循环的时候右移了
                delay_us(20);                        //60微秒后读完成
                delay_us(22);
                delay_us(22);
               
                DS18B20_WR1();                      //总线拉高,主机释放总线,准备启动下一个“读时间片”
         }
         return temp;
}               

/*********初始化DS18B20**************/
void init_DS18B20()
{
         DS18B20_start();                     //复位
         DS18B20_send(SKIP_ROM);              //跳过rom匹配
         DS18B20_send(0X4e);                  //设置写模式
         DS18B20_send(0x64);                  //设置温度的上限为100度
         DS18B20_send(0x8a);                  //设置温度的下线为-10度
         DS18B20_send(0x7f);                  //12bit
}


/************读取并计算要输出的温度****************************/
unsigned int ReadTem_DS18B20()
{
     unsigned char i;
         unsigned char TL;
         unsigned int  TH;
         
         DS18B20_start();                     //复位
         delay_ms(1);
         DS18B20_send(SKIP_ROM);               //跳过序列号检测命令
         DS18B20_send(CONVERT_TEM);            //命令DS18B20开始转换温度
         for(i=0;i<20;i++)delay_ms(10);          //延时200ms等待转换完成
       
         DS18B20_start();
         delay_ms(1);
         DS18B20_send(SKIP_ROM);                //跳过序列号检测命令
         DS18B20_send(READ_RAM);                //发读取温度数据命令
         TL=DS18B20_read();                     //先读低8位温度数据
         TH=ds18B20_read()<<8;                  //再读高8位温度数据
         
         DS18B20_start();                      //不需要其他数据,初始化DS18B20结束读取
         return(TH|TL)*10>>4;                  //温度放大了10倍,*0.0625=1/16=>>4
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-11-8 15:57:12 | 显示全部楼层
//mega128 8M晶振
const uchar CrcTable[256]=
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};

uchar CRC_OK1(uchar *p1,uchar num)
{
    uchar OutData1;
    uchar countbyte1;
                 OutData1=0;
         for(countbyte1=1;countbyte1<num;countbyte1++)
          {
             OutData1=CrcTable[OutData1^*p1];
                  p1++;
          }
        p1-=(num-1);
   return(OutData1);
}


void delay2(unsigned int x)  //1.5us左右
{
     while(x)
    {
       x--;
    }
}
void init_1820(void)
{   DDRB|=0x04;
    DS18B20_SET;  
        delay2(25);  ///
    DS18B20_CRL;
    delay2(500);    //480us以上
    DS18B20_SET;
        delay2(45);  ///
    DDRB&=~(1<<PB2);
    delay2(40);     //15~60us
    while(PINB&(1<<PB2))
    {  
           ;
   }
    DDRB|=(1<<PB2);
    DS18B20_SET;
    delay2(160);   //60~240us
}
void write_1820(unsigned char x)
{   
     unsigned char m;
    for(m=0;m<8;m++)
    {   DDRB|=(1<<PB2);
         DS18B20_CRL;
       if(x&(1<<m))    //写数据,从低位开始
          DS18B20_SET;
       else
         DS18B20_CRL;
       delay2(40);   //15~60us
       DS18B20_SET;
    }
     DS18B20_SET;
}
unsigned char read_1820(void)
{     
    unsigned char temp,k,n;
           temp=0;
    for(n=0;n<8;n++)
       { DDRB|=(1<<PB2);  
      DS18B20_CRL;
    //  delay(20);  //     
      DS18B20_SET;
    //  delay(30);  //   
      DDRB&=~(1<<PB2);
      k=(PINB&(1<<PB2));    //读数据,从低位开始
      if(k)
      temp|=(1<<n);
      else
      temp&=~(1<<n);
      delay2(80); //60~120us     
      DDRB|=(1<<PB2);
   }
   return (temp);
}  
//读取温度
ReadTemperature()
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
static unsigned char ErrorT=0;
static unsigned int    LastT;

      init_1820();        //复位18b20
      write_1820(0xcc);   // 发出转换命令
      write_1820(0x44);
      delay2(400);
          init_1820();
      write_1820(0xcc);  //发出读命令
      write_1820(0xbe);
Buf18B20[0]=read_1820();
Buf18B20[1]=read_1820();
t=(unsigned int)((Buf18B20[1]*256+Buf18B20[0]));  //计算具体温度
Buf18B20[2]=read_1820();
Buf18B20[3]=read_1820();
Buf18B20[4]=read_1820();
Buf18B20[5]=read_1820();
Buf18B20[6]=read_1820();
Buf18B20[7]=read_1820();
Buf18B20[8]=read_1820();
if((CRC_OK1(Buf18B20,10)!=0)||(Buf18B20[5]!=0xFF))  { if(ErrorT<10) ErrorT++; } else {  if(ErrorT>0)  ErrorT--; LastT=t; }
if(ErrorT==10)    t=0x0640;    else  t=LastT;          //传感器检测错误时,返回温度值100度
return(t);
}

出0入0汤圆

发表于 2012-11-8 21:54:53 | 显示全部楼层
coleyao 发表于 2012-11-8 15:57
//mega128 8M晶振
const uchar CrcTable[256]=
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32,  ...

CRC是做什么用的?

出0入0汤圆

发表于 2012-11-9 05:59:32 | 显示全部楼层
slayer_ni 发表于 2012-11-8 21:54
CRC是做什么用的?

CRC校验,增加读取温度数据的可靠性:
        在某些应用场合,读取的温度数据可靠性不高,为了增加温度数据的可信度,对读取数据进行CRC校验,符合的通过,不符合则丢弃(如实时性要求高则沿用上一次读取数据,然后再重复下一次读取),经过这样的处理,读取温度数据的可信度可得到大幅提高。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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