PIC/MSP430 单片机实战:DS18B20 温度采集(附代码)

在工业控制现场,温度是最常见也是最关键的参数之一。精准可靠的温度采集是系统稳定运行的保证。

历经多个工业项目,我发现在多路测温、布线复杂的场景中,DS18B20这款单总线数字温度传感器展现出独特优势。今天,我将分享如何用PICMSP430单片机稳定读取DS18B20,并提供经过现场验证的完整代码。

一、 为什么在工业场景中选择DS18B20

DS18B20的三大优势:

  1. 单总线结构:仅需一根口线即可实现双向通信,极大节省单片机I/O资源,特别适合多路温度采集。
  2. 全数字化:直接输出数字温度值,无需ADC转换,避免模拟信号传输过程中的衰减和干扰。
  3. 高精度宽量程-55°C+125°C的测量范围,±0.5°C的精度,满足大多数工业现场需求。

实战中的注意事项:

  • 传输距离不宜过长(建议<20米),长距离需加强驱动和屏蔽
  • 单总线上挂载多个传感器时,需通过ROM ID区分
  • 严格的时序要求是可靠读取的关键

二、 MSP430F415驱动DS18B20完整代码

以下是经过多个项目验证的MSP430F415驱动程序,可直接集成到您的项目中。

#include  <msp430x41x.h>

#define DQ1 P2OUT|=BIT4            //DQ=1

#define DQ0 P2OUT&=~BIT4       //DQ=0

#define DQIO_OUT P2DIR|=BIT4    //设为输出

#define DQIO_IN  P2DIR &= ~BIT4 //设为输入

#define positive 0x0f           //正温系数

//定义

unsigned char Error = 0;

float   Temper=0.0;        //真正有效温度值

int     temperature=0;          //读取两字节温度数据

unsigned char symbol = 1 ;      //温度正负符号

//******************************************************************************

//功能:us 级别延时

// n=10,则延时10*5+6=56uS

//******************************************************************************

void DelayNus(unsigned int n)

 {

    while(n--){};

 }

//******************************************************************************

//功能:写18B20

//******************************************************************************

void Write_18B20(unsigned char n)

{

    unsigned char i;

    for(i=0;i<8;i++)

    {

        DQ0;

        _NOP();_NOP();           //延时5us

        _NOP();_NOP();_NOP();

        if((n&0X01)==0X01)      //DQ=1

         DQ1;

        else

         DQ0;                   //DQ=0

        n=n>>1;                    //下一位

        DelayNus(18);            //延时50us 以上  //6->18

        DQ1;

    }

}

//******************************************************************************

//功能:读取18B20

//******************************************************************************

unsigned char Read_18B20(void)

{

    unsigned char i;

    unsigned char temp;

    for(i=0;i<8;i++)

    {

        temp=temp>>1;              //移向下一位

        DQ0;                   

        _NOP();                //延时1us

        DQ1;

        _NOP();_NOP();           //延时5us

        _NOP();  _NOP();

         _NOP();   _NOP();

        DQIO_IN;             //DQ口设为输入

      if((P2IN&BIT4)==0)      //DQ是否等于0

          {

            temp=temp&0x7F;    //读入DQ0

          }

      else

        {

         temp=temp|0x80;    //读入DQ1

        }

      DelayNus(15);        //延时40us        //5->20

      DQIO_OUT;                     //DQ口设为输出

      DQ1;                //DQ输出1

    }

    return    temp;        //返回一个数据

}

//******************************************************************************

//复位说明:复位要求主CPU将数据线下拉500us,然后释放,

//DS18B20收到信号后等待1660us左右,后发出60240微秒的存在低脉冲,

//CPU收到此信号表示复位成功。

//初始化DS18B20

void Init (void)

{

    DQ0;                   

    DelayNus(100);          //延时500us       //50->100

    DQ1;

    DelayNus(30);            //延时1660us    //10-30

    DQIO_IN;                     //DQ为输入

    if((P2IN&BIT4)==BIT4)        //1000 0000b=1f,DQ是否为1

     {

      Error =1;              //失败1

      DQIO_OUT;                     //DQ为输输出

     }

    else

     {

      Error = 0;         //初始化成功

      DQIO_OUT;                     //DQ为输输出

      DQ1;

     }

}

//******************************************************************************

//指令描述:跳过ROM命令,指定代码为CCH,忽略64ROM地址,直接向DS1820发温度变换

//命令,适用于单片机工作.

void Skip(void)

{

    Write_18B20(0xcc);

}

//******************************************************************************

//指令描述:温度转换命令,指定代码为44H.启动DS1820进行温度转换,12位转换时最长

//750ms(9位为93.75ms).结果存入内部9字节RAM.

 void Convert (void)

 {

    Write_18B20(0x44);

  }

//******************************************************************************

//指令描述:读暂存器,指定代码为BEH.读内部RAM9字节的内容.

  void ReadDo (void)

  {

    Write_18B20(0xbe);

  }

//******************************************************************************

//读取温度值

void ReadTemp (void)

 {

    char temp_low,  temp_high;        //温度值

    temp_low = Read_18B20();    //读低位

    temp_high = Read_18B20(); //读高位

    if((temp_high|positive)==positive)

        symbol=1;                //测到的温度为正

    else

        symbol=0;                //测到的温度为负

    temperature=(temp_high&0x0f);//屏蔽高4

    temperature<<=8;           //temp_high部分数据移到temperature8

    temperature|=temp_low; //将高低两字节内部合并成一个16位数据

    if(symbol==0)                       //是否为负温度

     { temperature = (~temperature)+1;   //将其取反后加1

     }

    Temper=temperature*0.0625;       //计算真实温度值

 }

//******************************************************************************

//MCUDS18B20进行温度转换时,其操作必须满足以下过程:

// 1- 每一次读写之前都要对DS18B20进行复位.

// 2- 完成复位后发送一条ROM命令到DS18B20.

// 3- 最后发送一条RAM命令到DS18B20.

// 以上系列动作是根据DS18B20的通讯协议所得.

//读取温度

void GetTemp(void)

 {

        Init();                   //DS1820初始化

        Skip();                  //跳过64ROM(ROM命令)

        Convert();            //转换(RAM命令)

        DelayNus(60000);        //60000x5us=0.3s

        DelayNus(60000);        //0.3s

        DelayNus(60000);      //0.3s

        DelayNus(10000);

        Init();                   //DS1820初始化

        Skip();                  //跳过64ROM

        ReadDo();           //读暂存器

        ReadTemp();              //读取温度值

 }

三、 PIC单片机移植要点

将代码移植到PIC单片机只需修改端口定义,时序逻辑完全通用:

#include<pic16f1947.h>

#define DQ1 PORTF|=0x04            //DQ=1

#define DQ0 PORTF&=0xfb   //DQ=0

#define DQIO_OUT TRISF2=0    //设为输出

#define DQIO_IN  TRISF2=1 //设为输入

以下两个子程序和MSP430略有区别

//功能:读取18B20

//******************************************************************************

unsigned char Read_18B20(void)

{

    unsigned char i;

    unsigned char temp;

    for(i=0;i<8;i++)

    {

        temp=temp>>1;              //移向下一位

        DQ0;                   

        DelayNus(4);                     //延时1us

        DQ1;

        DelayNus(16);

        DQIO_IN;             //DQ口设为输入

      if((PORTF&0x04)==0)   //DQ是否等于0

          {

            temp=temp&0x7F;    //读入DQ0

          }

      else

        {

         temp=temp|0x80;    //读入DQ1

        }

      DelayNus(160);             //延时40us        //5->20

      DQIO_OUT;                     //DQ口设为输出

      DQ1;                //DQ输出1

    }

    return    temp;        //返回一个数据

}

//******************************************************************************

//复位说明:复位要求主CPU将数据线下拉500us,然后释放,

//DS18B20收到信号后等待1660us左右,后发出60240微秒的存在低脉冲,

//CPU收到此信号表示复位成功。

//初始化DS18B20

void Init (void)

{

       DQIO_OUT;                 //DQ为输输出

       DelayNus(4);                     //延时1us

    DQ0;                   

    DelayNus(1900);        //延时500us       //50->100

    DQ1;

    DelayNus(900);          //延时1660us    //10-30

    DQIO_IN;                     //DQ为输入

    if((PORTF&0x04)==0x04)        //1000 0000b=1f,DQ是否为1

     {

      Error =1;              //失败1

      DQIO_OUT;                     //DQ为输输出

     }

    else

     {

      Error = 0;         //初始化成功

      DQIO_OUT;                     //DQ为输输出

      DQ1;

     }

}

后面的子程序和MSP430单片机的基本一样,延时函数里的取值大小和PIC单片机的主频有关。

四、 工业应用中的实战经验

1. 抗干扰设计

  • DQ线并联4.7kΩ-10 kΩ上拉电阻
  • 长距离传输时采用双绞线,外层加屏蔽
  • 电源端增加0.1μF去耦电容

2. 多传感器应用

必须通过ROM ID区分传感器

3. 故障诊断

  • 初始化失败:检查接线、电源、上拉电阻
  • 读数异常:检查时序精度、电源稳定性
  • 通信中断:检查总线冲突、电磁干扰

五、 常见问题与解决方案

Q1: 读取温度始终为85°C
A: 这是DS18B20的上电默认值,说明温度转换命令未正确执行,检查转换等待时间是否足够。

Q2: 传输距离受限?
A: 可通过总线驱动器扩展传输距离,或改用RS485接口的温度变送器。

结语

DS18B20以其简洁的单总线接口和可靠的性能,在工业温度监测中占据一席之地。掌握其严格的时序要求,配合正确的硬件设计,就能构建稳定可靠的温度采集系统。

本文提供的代码模板已在我多个工业项目中稳定运行数年,您可以直接使用或根据需求修改。在工业控制中,往往是最基础的技术,决定了整个系统的可靠性上限。

你你在工业温度采集中遇到过哪些问题?欢迎在评论区留言!

后续干货不断,咱们一起在单片机的世界里,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值