温度传感器DS18B20的相关介绍以及基于MSP430的驱动程序(附代码)

本文详细介绍了DS18B20温度传感器的工作原理、引脚功能及数据格式,并提供了基于MSP430单片机的初始化、读取温度及数据转换的代码实现。通过发送特定命令序列,实现对DS18B20的控制,并将温度数据显示在LCD1602上。
摘要由CSDN通过智能技术生成

   阅读本文之前请先找到DS18B20的中文手册

   DS18B20数据手册-中文版 - 知乎 (zhihu.com)

  下面先对DS18B20简单进行一些介绍:

   学校课程设计中常见的DS18B20的引脚一般为3脚封装,如下图左侧所示:

        可以看到,DS18B20的引脚为GND,DQ,VDD。其中GND与VDD的引脚分别接地线和电源就好了,而DQ线是主要的数据传输口,它可以接在P1-P6端口的引脚上,因为数据传输主要靠拉高或者拉低电平,再由单片机判断高低电平,所以接哪个口都可以。

        DS18B20测量完温度后会将数据存在温度寄存器中,储存的格式如下:

        可以看到,高五位是S,即SIGN,符号位,而低11位用来储存数据,DS18B20的精度逐渐调低时,由BIT0到高位会逐渐未定义(即BIT0未定义时,精度会下降,精度再下降的话,就是BIT1未定义,因为BIT0-BIT3负责记录小数点后的数据)。这里需要注意的是,温度寄存器的数据同样在DS18B20的ScratchPad中,关于ScratchPad是什么,接下来我会详细讲解。

 DS18B20的具体操作:

        DS18B20存储温度数据时是分两位字节存储的,两字节16位数据中,高五位为符号位,低十一位为数据位。因此,读取DS18B20的数据需要连续进行两次读一字节的操作,先读低八位,后读高八位。在发送读ScratchPad指令后,传感器会由低到高传送共9字节的数据,我们只需要读取两字节即可读出数据。ScratchPad中默认的字节顺序如下:

(此处可以看到ScratchPad其实就是一个存数据的寄存器,我们需要的数据就在它的BYTE0与BYTE1那里)

而访问DS18B20的事件序列如下所示:

第一步:初始化

第二步:ROM命令(紧跟任何数据交换请求)

第三步:DS18B20功能命令(紧跟任何数据交换请求)

       每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DS18B20将不会响应。因此,实现温度转换的具体步骤即为:初始化、发送跳过ROM命令、发送温度转换命令、再次初始化、再次发送跳过ROM命令、读取ScratchPad中头两个字节的数据。(此处可以跳过ROM是因为只有一个传感器,无需通过DS18B20本身的编码来确定是哪个传感器,如果有多个传感器连接在单片机上,则跳过命令会使传回的数据发生错误。)

        通过以上步骤,即可实现对DS18B20的初始化以及开始温度转换,并最终返回存储在ScratchPad中的温度转换后的数据。而此数据在经过函数转化后,便会被存在数组中,之后在LCD上进行输出。

代码部分如下:
//MAKER: JK2001 ZHZ
#include <MSP430.h>
#include<LCD1602.h>
#define uchar unsigned char
#define uint unsigned int 
uchar tem[16]={"The temp is"};
//此部分为时钟的初始化,DS18B20需要极为精确的微秒操作
#define CPU_F ((double)1000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) 
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define DQ0 P2OUT &=~BIT6                //此处定义了DS18B20的端口
#define DQ1 P2OUT |= BIT6
unsigned int value;
uint Init_18B20(){  //18B20初始化
   P2DIR |= BIT6;
   uint i = 9;
   DQ1;             //先上拉电平打断初始化之前的操作
   DQ0;             //拉低电平等待响应
   delay_us(500);
   DQ1;
   P2DIR &= ~BIT6;
   delay_us(80);  
   if(P2IN & BIT6){i=1;P2DIR|=BIT6;} 
   else{i=0;P2DIR|=BIT6;} //如果是低电平,则初始化成功
   delay_us(300);
   return i;
   }
void send_byte(uchar cmd){  //发送一个字节的命令
   uint num=0;
   for(num=0;num<8;num++){  //进行循环以发送每一位的数据
   P2DIR |= BIT6;
   DQ0;
   delay_us(8);
   if(cmd & 0x01){DQ1;}
   delay_us(60);
   DQ1;
   cmd >>= 1;
   }
}
uchar read_byte(void){   //读取一个字节
    uint i;
    uchar data=0;
    for(i=0;i<8;i++){
       data>>=1;         //右移,读取下一位
       DQ0;
       delay_us(5);
       DQ1;      
       delay_us(8);
       P2DIR &= ~BIT6;
       _NOP();
       if(P2IN & BIT6){data|=0x80;} 
       delay_us(50);
       P2DIR |= BIT6;
       DQ1;
       delay_us(10);
    }
    return data;
}
uint read_temp(void){     //读取操作进行两次并将结果合并
   uint low=0;
   uint high=0;
   uint temp = 0;
   low = read_byte();
   high= read_byte();
   temp = (high*256) | low; 
   return temp;
}
void skip(void){         //向18B20发送跳过ROM命令
   send_byte(0xcc);}
void zh(void){
   send_byte(0x44);      //温度转换命令
   }
void read_sp(void){      //读取ScratchPad命令
   send_byte(0xbe);}
uint do1zh(void){        //做一次转换
    uchar i=0; 
    do{i = Init_18B20();}   //初始化
    while(i);
    skip();                 //跳过ROM
    zh();                   //转换
    delay_ms(800);          //转换时延时,12位精度最少需要750ms
    do{i = Init_18B20();}   //初始化
    while(i);
    skip();                 //跳过ROM命令
    read_sp();              //读取数据 
    return read_byte();     //返回数据
}   
uchar dN[6]={"000000"};     //初始化dN数组
void Disp_Numb(uint temper){       //通过温度转换函数转换数据
    uchar i;    
    for(i = 0;i < 6;i++) dN[i] = 0; //初始化显示变量
    if(temper & BIT0) 
    {dN[0] = 5;dN[1] = 2;dN[2] = 6;} //0.0625
    if(temper&BIT1)     
    {dN[1] += 5;dN[2] += 2;dN[3] += 1;} //0.125
    if(temper & BIT2)        //0.25
{
dN[2] += 5;dN[3] += 2;
        if(dN[2] >= 10)
        {dN[2] -= 10;dN[3] += 1;}
    }
    if(temper & BIT3)       //0.5
    {dN[3] += 5;}
    if(temper & BIT4)
    {dN[4] += 1;}
    if(temper & BIT5)     
    {dN[4] += 2;}
    if(temper & BIT6)
    {dN[4] += 4;}
    if(temper & BIT7)     
    {dN[4] += 8;
        if(dN[4] >= 10)
        {dN[4] -= 10;dN[5] += 1;}
    }
    if(temper& BIT8)
    {dN[4] += 6;dN[5] += 1;
        if(dN[4] >= 10)
        {dN[4] -= 10;dN[5] += 1;}
    }
    if(temper & ~BIT9)
    {dN[4] += 2;dN[5] += 3;
        if(dN[4] >= 10)
        {dN[4] -= 10;dN[5] += 1;}
    }
    if(temper & ~BITA)
    {dN[4] += 4;dN[5] += 6;
        if(dN[4] >= 10)
        {dN[4] -= 10;dN[5] += 1;}
        if(dN[5] >= 10)
        {dN[5] -= 10;}
}   
}
//此处的主函数实现的主要功能是将测试温度显示在LCD上
int main (void)
 { 
    WDTCTL = WDTPW + WDTHOLD;
    P2DIR |= BIT6;
    P2OUT |= BIT6;
    Port_init();
    LCD_init();
    LCD_Desk();
    LCD_Write_str(0,0,tem);  //输出temp is,此处和下处调用了头文件
    while (1){  
       Disp_Numb(do1zh());   
       LCD_Write_char(0x09,1,dN[5]+0x30);   //0X30是ASCII码转换
       LCD_Write_char(0x0a,1,dN[4]+0x30);
       LCD_Write_char(0x0b,1,0x2e);       //0x2e是小数点的ASCII码值
       LCD_Write_char(0x0c,1,dN[3]+0x30);
       LCD_Write_char(0x0d,1,dN[2]+0x30);
       LCD_Write_char(0x0e,1,dN[1]+0x30);
       LCD_Write_char(0x0f,1,dN[0]+0x30);
       }
 }

        以上代码除了DS18B20本身的代码外,其余部分使用了LCD1602的头文件,这个并不难,所以不再赘述,有必要说明的是,DS18B20的各种操作可以参照51单片机关于DS18B20的操作,这里给出的是我自己基于MSP430修改的版本。

        此版本代码是确认无误的,如果有问题,那反正不是我的问题

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值