3.8 ds18b20温度传感器实验

DS18B20是常用的数字温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。DS18B20 单线数字温度传感器,即“一线器件”,其具有独特的优点:
1,采用单总线的接口方式 与微处理器连接时仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
2,测量温度范围宽,测量精度高 DS18B20 的测量范围为 -55 ℃ ~+ 125 ℃ ; 在 -10~+ 85°C范围内,精度为 ± 0.5°C 。
3,在使用中不需要任何外围元件。
4,持多点组网功能多个 DS18B20 可以并联在惟一的单线上,实现多点测温。
5,供电方式灵活 DS18B20 可以通过内部寄生电路从数据线上获取电源。因此,当数据线上的时序满足一定的要求时,可以不接外部电源,从而使系统结构更趋简单,可靠性更高。
6,测量参数可配置 DS18B20 的测量分辨率可通过程序设定 9~12 位。
7,负压特性电源极性接反时,温度计不会因发热而烧毁。
8,掉电保护功能 DS18B20 内部含有 EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
 DS18B20 具有体积更小、适用电压更宽、更经济、可选更小的封装方式,更宽的电压适用范围,适合于构建自己的经济的测温系统,因此也就被设计者们所青睐。
  DS18B20内部结构:
  主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X8+X5+X^4+1)。 ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。
首先创建读取ds18b20的任务:

define TASK_SIZE 256

static OS_STK ds18b20_task_stk[TASK_SIZE];
void UserMain(void)
{

tls_os_task_create(NULL, NULL,
ds18b20_task,
NULL,
(void *)ds18b20_task_stk,
TASK_SIZE * sizeof(u32),
32,
0);
}
在任务中初始化DS18B20,并获取DS18B20序列号后读取温度值。
static void ds18b20_task(void *data)
{
uint8_t uc, ucDs18b20Id [ 8 ];
int i;
printf(" this is a ds18b20 test demo ");

while( DS18B20_Init() )
{
	for(i=0;i<1000;i++)
	{
		us_delay(1000);
	}


printf("
 ds18b20 exit 
");
}
printf("
 ds18b20 ok  
");
 DS18B20_ReadId ( ucDs18b20Id  );           // 读取 DS18B20 的序列号

 printf("
DS18B20: 0x");

 for ( uc = 0; uc < 8; uc ++ )             // 打印 DS18B20 的序列号
  printf ( "%.2x", ucDs18b20Id [ uc ] );

for( ; ; )
{

	 printf ( "
temperature: %.1f
", DS18B20_GetTemp_MatchRom ( ucDs18b20Id ) );		// 打印通过 DS18B20 序列号获取的温度值
	 DS18B20_DELAY_MS(1000);
}

}
其它函数:

/**

  • @brief DS18B20 初始化函数

  • @param 无

  • @retval 无
    */
    uint8_t DS18B20_Init(void)
    {
    DS18B20_GPIO_Config ();

    DS18B20_DQ_1;

    DS18B20_Rst();

return DS18B20_Presence ();

}
/*

  • 函数名:DS18B20_GPIO_Config

  • 描述 :配置DS18B20用到的I/O口

  • 输入 :无

  • 输出 :无
    */
    static void DS18B20_GPIO_Config(void)
    {

    tls_gpio_cfg(DS18B20_DQ_GPIO_PORT, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);//配置为上拉输出
    }

/*

  • 函数名:DS18B20_Mode_IPU
  • 描述 :使DS18B20-DATA引脚变为输入模式
  • 输入 :无
  • 输出 :无
    */
    static void DS18B20_Mode_IPU(void)
    {
    tls_gpio_cfg(DS18B20_DQ_GPIO_PORT, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);//配置为上拉输出
    }

/*

  • 函数名:DS18B20_Mode_Out_PP
  • 描述 :使DS18B20-DATA引脚变为输出模式
  • 输入 :无
  • 输出 :无
    */
    static void DS18B20_Mode_Out_PP(void)
    {
    tls_gpio_cfg(DS18B20_DQ_GPIO_PORT, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);//配置为上拉输出
    }

/*
*主机给从机发送复位脉冲
/
static void DS18B20_Rst(void)
{
/
主机设置为推挽输出 */
DS18B20_Mode_Out_PP();

DS18B20_DQ_0;
 /* 主机至少产生480us的低电平复位信号 */
 us_delay(750);

 /* 主机在产生复位信号后,需将总线拉高 */
 DS18B20_DQ_1;

 /*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
 us_delay(15);

}

/*

  • 检测从机给主机返回的存在脉冲

  • 0:成功

  • 1:失败
    */
    static uint8_t DS18B20_Presence(void)
    {
    uint8_t pulse_time = 0;

    /* 主机设置为上拉输入 */
    DS18B20_Mode_IPU();

    /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号

    • 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
      /
      while( DS18B20_DQ_IN() && pulse_time<100 )
      {
      pulse_time++;
      us_delay(1);
      }
      /
      经过100us后,存在脉冲都还没有到来*/
      if( pulse_time >=100 )
      return 1;
      else
      pulse_time = 0;

    /* 存在脉冲到来,且存在的时间不能超过240us */
    while( !DS18B20_DQ_IN() && pulse_time<240 )
    {
    pulse_time++;
    us_delay(1);
    }
    if( pulse_time >=240 )
    return 1;
    else
    return 0;
    }

/*

  • 从DS18B20读取一个bit
    */
    static uint8_t DS18B20_ReadBit(void)
    {
    uint8_t dat;

    /* 读0和读1的时间至少要大于60us /
    DS18B20_Mode_Out_PP();
    /
    读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
    DS18B20_DQ_0;
    us_delay(10);

    /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
    DS18B20_Mode_IPU();
    //us_delay(2);

    if( DS18B20_DQ_IN() == SET )
    dat = 1;
    else
    dat = 0;

    /* 这个延时参数请参考时序图 */
    us_delay(45);

    return dat;
    }

/*

  • 从DS18B20读一个字节,低位先行
    */
    static uint8_t DS18B20_ReadByte(void)
    {
    uint8_t i, j, dat = 0;

    for(i=0; i<8; i++)
    {
    j = DS18B20_ReadBit();
    dat = (dat) | (j<<i);
    }

    return dat;
    }

/*

  • 写一个字节到DS18B20,低位先行
    */
    static void DS18B20_WriteByte(uint8_t dat)
    {
    uint8_t i, testb;
    DS18B20_Mode_Out_PP();

    for( i=0; i<8; i++ )
    {
    testb = dat&0x01;
    dat = dat>>1;
    /* 写0和写1的时间至少要大于60us /
    if (testb)
    {
    DS18B20_DQ_0;
    /
    1us < 这个延时 < 15us */
    us_delay(8);

     	DS18B20_DQ_1;
     	us_delay(58);
     }
     else
     {
     	DS18B20_DQ_0;
     	/* 60us < Tx 0 < 120us */
     	us_delay(70);
    
     	DS18B20_DQ_1;
     	/* 1us < Trec(恢复时间) < 无穷大*/
     	us_delay(2);
     }
    

    }
    }

/**

  • @brief 跳过匹配 DS18B20 ROM

  • @param 无

  • @retval 无
    */
    static void DS18B20_SkipRom ( void )
    {
    DS18B20_Rst();

    DS18B20_Presence();

    DS18B20_WriteByte(0XCC); /* 跳过 ROM */

}

/**

  • @brief 执行匹配 DS18B20 ROM

  • @param 无

  • @retval 无
    */
    static void DS18B20_MatchRom ( void )
    {
    DS18B20_Rst();

    DS18B20_Presence();

    DS18B20_WriteByte(0X55); /* 匹配 ROM */

}

/*

  • 存储的温度是16 位的带符号扩展的二进制补码形式

  • 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位

  •     |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|
    
  • 低字节 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |

  •     |-----符号位:0->正  1->负-------|-----------整数-----------|
    
  • 高字节 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |

  • 温度 = 符号位 + 整数 + 小数*0.0625
    /
    /
    *

  • @brief 在跳过匹配 ROM 情况下获取 DS18B20 温度值

  • @param 无

  • @retval 温度值
    */
    float DS18B20_GetTemp_SkipRom ( void )
    {
    uint8_t tpmsb, tplsb;
    short s_tem;
    float f_tem;

    DS18B20_SkipRom ();
    DS18B20_WriteByte(0X44); /* 开始转换 */

    DS18B20_SkipRom ();
    DS18B20_WriteByte(0XBE); /* 读温度值 */

    tplsb = DS18B20_ReadByte();
    tpmsb = DS18B20_ReadByte();

    s_tem = tpmsb<<8;
    s_tem = s_tem | tplsb;

    if( s_tem < 0 ) /* 负温度 */
    f_tem = (~s_tem+1) * 0.0625;
    else
    f_tem = s_tem * 0.0625;

    return f_tem;

}

/**

  • @brief 在匹配 ROM 情况下获取 DS18B20 温度值

  • @param ds18b20_id:用于存放 DS18B20 序列号的数组的首地址

  • @retval 无
    */
    void DS18B20_ReadId ( uint8_t * ds18b20_id )
    {
    uint8_t uc;

    DS18B20_WriteByte(0x33); //读取序列号

    for ( uc = 0; uc < 8; uc ++ )
    ds18b20_id [ uc ] = DS18B20_ReadByte();

}

/**

  • @brief 在匹配 ROM 情况下获取 DS18B20 温度值

  • @param ds18b20_id:存放 DS18B20 序列号的数组的首地址

  • @retval 温度值
    */
    float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id )
    {
    uint8_t tpmsb, tplsb, i;
    short s_tem;
    float f_tem;

    DS18B20_MatchRom (); //匹配ROM

for(i=0;i<8;i++)
DS18B20_WriteByte ( ds18b20_id [ i ] );

DS18B20_WriteByte(0X44);				/* 开始转换 */


DS18B20_MatchRom ();            //匹配ROM

for(i=0;i<8;i++)
	DS18B20_WriteByte ( ds18b20_id [ i ] );

DS18B20_WriteByte(0XBE);				/* 读温度值 */

tplsb = DS18B20_ReadByte();
tpmsb = DS18B20_ReadByte();


s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;

if( s_tem < 0 )		/* 负温度 */
	f_tem = (~s_tem+1) * 0.0625;
else
	f_tem = s_tem * 0.0625;

return f_tem;

}
编译下载到开发板运行:

原文地址:https://www.cnblogs.com/doiting/p/14108991.html