czp123123 发表于 2012-11-8 15:13:39

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

本帖最后由 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 intTH;
       
       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
}

coleyao 发表于 2012-11-8 15:57:12

//mega128 8M晶振
const uchar CrcTable=
{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;
              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=read_1820();
Buf18B20=read_1820();
t=(unsigned int)((Buf18B20*256+Buf18B20));//计算具体温度
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
if((CRC_OK1(Buf18B20,10)!=0)||(Buf18B20!=0xFF)){ if(ErrorT<10) ErrorT++; } else {if(ErrorT>0)ErrorT--; LastT=t; }
if(ErrorT==10)    t=0x0640;    elset=LastT;          //传感器检测错误时,返回温度值100度
return(t);
}

slayer_ni 发表于 2012-11-8 21:54:53

coleyao 发表于 2012-11-8 15:57 static/image/common/back.gif
//mega128 8M晶振
const uchar CrcTable=
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32,...

CRC是做什么用的?

coleyao 发表于 2012-11-9 05:59:32

slayer_ni 发表于 2012-11-8 21:54 static/image/common/back.gif
CRC是做什么用的?

CRC校验,增加读取温度数据的可靠性:
      在某些应用场合,读取的温度数据可靠性不高,为了增加温度数据的可信度,对读取数据进行CRC校验,符合的通过,不符合则丢弃(如实时性要求高则沿用上一次读取数据,然后再重复下一次读取),经过这样的处理,读取温度数据的可信度可得到大幅提高。
页: [1]
查看完整版本: 关于DS18B20的驱动,请各位前辈斧正,小菜鸟一枚