锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

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

时间:2023-06-04 16:07:00 sp2801传感器传感器zh30104

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

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

下面先对DS18B简单介绍一下:

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

可以看到,DS18B20的引脚为GND,DQ,VDD。其中GND与VDD引脚分别接地线和电源,DQ线是主要的数据传输口,可以连接P1-P在6端口的引脚上,由于数据传输主要依靠拉高或拉低电平,然后由单片机判断,因此可以连接任何端口。

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

可见高五位是S,即SIGN,用于存储数据的符号位较低,DS18B当20的精度逐渐降低时,从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  #include #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();                   //转换     dely_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修改的版本。

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

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章