美文网首页硬件设计
DS18B20数字传感器学习笔记

DS18B20数字传感器学习笔记

作者: Jane_123 | 来源:发表于2016-05-01 21:00 被阅读1267次

    DS18B20是一种半双工单总线通信方式,它共有6中信号:复位脉冲,应答脉冲,写0,写1,读0和读1。所有这些信号,除了应答脉冲以外,都是由主机发出同步信号,并且发送所有的命令和数据都是字节的低位在前。

    复位脉冲

    单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,以产生复位脉冲,接着主机释放总线,4.7K的上拉电阻将总线拉高,延时15~16us,并进入接收模式。

    //复位DS18B20
    
    void DS18B20_Rst(void)
    
    {                 
    
        DS18B20_IO_OUT(); //设置为输出模式
    
        DS18B20_DQ_OUT=0; //拉低DQ
    
        delay_us(750);    //拉低750us(至少480us)
    
        DS18B20_DQ_OUT=1; //DQ=1拉高释放总线
    
        delay_us(15);     //15US
      
    }
    

    此时进入接收模式,等待应答信号。

    应答信号

    将DS18B20总线拉低60~240us,产生低电平应答脉冲。

    等待DS18B20的回应

    //返回1:未检测到DS18B20的存在
    
    //返回0:存在
    
    u8 DS18B20_Check(void)
    
    {   
        u8 retry=0;
        DS18B20_IO_IN();//SET PA0INPUT
        while(DS18B20_DQ_IN&&retry<200)// DS18B20_DQ_IN的作用为读引脚,观察其是否为低电平
        {
            retry++;//如果为高电平,则retry++
            delay_us(1);
        }
        if(retry>=200)//未检测到18B20
        {
          return 1;
        }
        else
        {
            retry=0;
        }
        while(!DS18B20_DQ_IN&&retry<240)
        {
            retry++;//低电平时retry++
            delay_us(1);
        }
        if(retry>=240)return1;//由于拉低总线的时间在60~240us,大于240则没检测到18B20    
        return 0;
    }
    

    写时序

    写时序包括写0时序和写1时序。所有写时序至少需要60us,且在两次独立的写时序之间需要1us的恢复时间,两种写时序均起始于主机拉低总线。

    写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。

    写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。

    
    //写一个字节到DS18B20
    //dat:要写入的字节
    void DS18B20_Write_Byte(u8 dat)     
    {             
        u8 j;
        u8 testb;
        DS18B20_IO_OUT();//设置IO口为输出
        for (j=1;j<=8;j++) //八位数据,一位一位写
        {
            testb=dat&0x01;//取第一位数据
            dat=dat>>1;//移位
            if (testb) //输出高
            {
                DS18B20_DQ_OUT=0;//主机输出低电平
                delay_us(2);//延时2us                            
                DS18B20_DQ_OUT=1;
                delay_us(60);     //延时60us
            }
            else//输出低
            {
                DS18B20_DQ_OUT=0;//主机输出低电平
                delay_us(60);             
                DS18B20_DQ_OUT=1;//释放总线
                delay_us(2);                          
            }     
        }
    }
    

    读时序

    单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能传输数据。

    所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。

    典型的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us。

    //从DS18B20读取一个位
    //返回值:1/0
    u8 DS18B20_Read_Bit(void)
    {
        u8 data;
        DS18B20_IO_OUT();//设置IO口为输出
        DS18B20_DQ_OUT=0; //输出低电平2us
        delay_us(2);
        DS18B20_DQ_OUT=1; //拉高释放总线
        DS18B20_IO_IN();//设置IO口为输入
        delay_us(12);//延时12us
        if(DS18B20_DQ_IN)data=1;//读取总线数据(当前电平)
        else data=0;
        delay_us(50);//延时50us           
        return data;
    
    }
    
     
    
    //从DS18B20读取一个字节
    //返回值:读到的数据
    u8 DS18B20_Read_Byte(void)   
    {        
        u8 i,j,dat=0;
        for (i=1;i<=8;i++)
        {
            j=DS18B20_Read_Bit();
            dat=(j<<7)|(dat>>1);
        }
        return dat;
    }
    

    DS18B20是如何读取

    现在我们来看看DS18B20是怎么读取温度的,DS18B20的典型温度读取过程为:复位->发SKIP ROM命令(0XCC)->发开始转换命令(0X44)->延时->复位->发送SKIP ROM命令(0XCC)->发读存储器命令(0XBE)->连续读出两个字节数据(即温度)->结束。

    
    //从ds18b20得到温度值
    //精度:0.1C
    //返回值:温度值(-550~1250)
    short
    DS18B20_Get_Temp(void)
    {
       u8 temp;
       u8 TL,TH;
       short tem;
       DS18B20_Start ();                    // ds1820 start convert
       DS18B20_Rst();//复位
       DS18B20_Check();
       DS18B20_Write_Byte(0xcc);// skip rom
       DS18B20_Write_Byte(0xbe);//convert
       TL=DS18B20_Read_Byte();// LSB   
       TH=DS18B20_Read_Byte();// MSB  
       if(TH>7)//(TH>xxxxx111)温度为负
       {
           TH=~TH;TL=~TL;
           temp=0; 
       }
       else  temp=1;//温度为正
       tem=TH;//获得高八位
       tem<<=8;    
       tem+=TL;//获得底八位
       tem=(float)tem*0.625;//转换
       if(temp) return tem; //返回温度值
       else  return -tem;    
    }
    

    其中

    void
    DS18B20_Start(void)// ds1820 start convert
    
    {     
        DS18B20_Rst();
        DS18B20_Check();
        DS18B20_Write_Byte(0xcc);// skip rom
        DS18B20_Write_Byte(0x44);// convert
    }
    
    

    紧接着我们来讲后面有关温度计算的问题,首先,我们用DS18B20_Read_Byte()函数读取两个字节的温度,先低后高。

    DS18B20 能够提供两个字节的温度数据,共16位数。但是因为18B20是单总线的,数据都是一位一位传输的。每次读出的操作,DS18B20 仅仅送出8位数。必须读出两次,才能完整的读出16位数。两次读出时,DS18B20 先输出的是低八位,后输出的是高八位。这是器件本身的特性。

    1.jpg

    转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测得的数值乘以0.0625即可得到实际温度;如果温度小于0,这五位为1,检测到的数值需要取反加1再乘以0.0625即可得到实际温度。(源码中0.625是因为要保证精度,在主函数中温度有除以10,所以相当于0.0625)

    2.jpg

    由上图可以看出前五位为符号位。

    主函数中初始化DS18B20的函数如下:

    //初始化DS18B20的IO口DQ 同时检测DS的存在
    //返回1:不存在
    //返回0:存在
    u8 DS18B20_Init(void)
    {
        GPIO_InitTypeDef  GPIO_InitStructure;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PORTA时钟
    
        GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0;//PORTA0 推挽输出
        GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
        GPIO_SetBits(GPIOA,GPIO_Pin_0);    //输出1
    
        DS18B20_Rst();
        return DS18B20_Check();//未检测到DS18B20则返回1
    }
    

    既然学到了这里,想必大家对这个都十分熟悉,这里我就不再多说。

    以上,DS18B20读取温度的方式就讲完了。学会使用这些函数,就可以在主函数中调用他们来读取外界温度。

    相关文章

      网友评论

        本文标题:DS18B20数字传感器学习笔记

        本文链接:https://www.haomeiwen.com/subject/brxlrttx.html