配置DS18B20温度传感器

配置初始化函数

DS18B20的通信协议为单总线通信协议

cubemx 温度传感器_单片机

首先由主机发送一个复位脉冲约480-960us;然后总线被拉高;在15-60us之后传感器向单片机发送一个约60-240us的存在脉冲,然后总线被拉高。

uint8_t DS18B20_Rst(void)
{
    DS18B20_GPIO_Config ();
    DS18B20_DQ_1;
    DS18B20_Mode_Out_PP();
    DS18B20_DQ_0;
    Delay_us(750);
    DS18B20_DQ_1;
    DS18B20_Mode_IPU();
    Delay_us(70);
    if(DS18B20_DQ_IN() == 0)
    {
        Delay_us(240);
        if(DS18B20_DQ_IN() == 1)
            return 0;
    }
    else 
        return 1;
}

配置写函数

当主机将数据线从高逻辑级别拉到低逻辑级别时,将启动写入时隙。有两种类型的写时槽:写1时槽和写0时槽。所有写入时隙的持续时间必须至少为60µs,且每个写入周期之间的恢复时间至少为1µs以上。在DQ线下降后,DS18B20在15µs到60µs的窗口中对DQ线进行采样。

如果DQ为高,则会出现Write1。如果DQ为低低,则会出现Write0。

  1. 要使主机生成写1时隙,必须将数据线拉到逻辑低级别,然后释放,允许数据线在写时隙开始后的15µs内拉到高级别。
  2. 要使主机生成写0时隙,必须将数据线拉到逻辑低级别,并在低级别保持60µs。

cubemx 温度传感器_嵌入式硬件_02

void Write_Byte(uint8_t dat)
{
    uint8_t tem = 0,i = 0;
    DS18B20_Mode_Out_PP();
    for(i = 0; i < 8;i++)
    {
        tem = dat & 0x01;
        dat = dat >> 1;
        if(tem == 0)
        {
            DS18B20_DQ_0;
            Delay_us(70);
            DS18B20_DQ_1;
            Delay_us(5);
        }
        if(tem == 1)
        {
            DS18B20_DQ_0;
            Delay_us(5);
            DS18B20_DQ_1;
            Delay_us(60);
        }
    }
}

配置读函数

当要从DS18B20读取数据时,主机生成读取时隙。当主机将数据线从逻辑高级级别到逻辑低级别时,启动读取时隙。数据线必须保持在低逻辑级别至少1µs;来自DS18B20的输出数据在读取时隙边缘下降后15µs有效。因此,主机必须将DQ引脚拉低,以便从读取槽的开始读取其15µs的状态。在读取时隙结束时,DQ引脚将通过外部上拉电阻重新拉高。所有读取时间槽的持续时间必须至少为60µs,每个读取时间槽之间的恢复时间至少为1-µs。

cubemx 温度传感器_单片机_03

uint8_t Read_Byte(void)
{
    uint8_t dat = 0,num = 0,i = 0;
    for(i = 0; i < 8;i++)
    {
        uint8_t num = 0;
        DS18B20_Mode_Out_PP();
        DS18B20_DQ_0;
        Delay_us(15);
        DS18B20_Mode_IPU();
        if(DS18B20_DQ_IN() == 0)
            num = 0;
        else
            num = 1;
        Delay_us(50);
        dat = (num << i) | dat;
    }
    return dat;
}

供电配置

要搭配硬件电路使用

void Power_Select(uint8_t value)
{
    DS18B20_WriteByte(0xB4);
    if(value == 1)
		DS18B20_WriteByte(1);
    if(value == 0)
        DS18B20_WriteByte(0);
}

读取芯片ID

void DS18B20_ReadId ( uint8_t * ds18b20_id )
{
    uint8_t uc;
    DS18B20_WriteByte(0x33);	//发送读取ID的命令
    for ( uc = 0; uc < 8; uc ++ )
        ds18b20_id [ uc ] = DS18B20_ReadByte();
}

跳过匹配ROM

static void DS18B20_SkipRom ( void )
{
	DS18B20_Rst();	   	 
	DS18B20_WriteByte(0XCC);
}

匹配ROM

static void DS18B20_MatchRom ( void )
{
	DS18B20_Rst();	   
	DS18B20_WriteByte(0X55);
}

读取温度的两种模式

匹配ROM的情况下

cubemx 温度传感器_嵌入式硬件_04

float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id )
{
    uint8_t tem_h, tem_l, i;
    short s_tem;
    float f_tem;
	
    //匹配ROM
    DS18B20_Rst();	   
	DS18B20_WriteByte(0X55);
    for(i=0;i<8;i++)
        DS18B20_WriteByte ( ds18b20_id [ i ] );	

    DS18B20_WriteByte(0X44);	//启动温度转换。
   
    //匹配ROM
    DS18B20_Rst();	   
	DS18B20_WriteByte(0X55);	
    for(i = 0; i < 8; i++)
        DS18B20_WriteByte ( ds18b20_id [ i ] );	

    DS18B20_WriteByte(0XBE);	//从暂存器中读取字节和CRC字节。	

    tem_l = DS18B20_ReadByte();	//tem_l接受低八位 
    tem_h = DS18B20_ReadByte(); //tem_h接受高八位

    s_tem = tem_h << 8;
    s_tem = s_tem | tem_l;		//s_tem存储温度的初始值
	
    //将温度转换为float型、摄氏度
    if( s_tem < 0 )	
        f_tem = (~s_tem+1) * 0.0625;	
    else
        f_tem = s_tem * 0.0625;
	
    //返回温度的值
    return f_tem; 	
}

不匹配ROM的情况下

cubemx 温度传感器_stm32_05

float DS18B20_GetTemp_SkipRom ( void )
{
    uint8_t tem_h, tem_l;
    short s_tem;
    float f_tem;

    DS18B20_SkipRom ();
    DS18B20_WriteByte(0X44);		//启动温度转换。

    DS18B20_SkipRom ();
    DS18B20_WriteByte(0XBE);		

    tem_l = DS18B20_ReadByte();		 
    tem_h = DS18B20_ReadByte(); 

    s_tem = tem_h << 8;
    s_tem = s_tem | tem_l;

    if( s_tem < 0 )		
        f_tem = (~s_tem + 1) * 0.0625;	
    else
        f_tem = s_tem * 0.0625;

    return f_tem; 	
}

配置主函数

int main(void)
{	
	uint8_t uc, ucDs18b20Id [ 8 ];
    
	SysTick_Init();
	LED_GPIO_Config();
	DS18B20_GPIO_Config();
	USART_Config();
	
	while( DS18B20_Rst() == 1)	
		printf("\r\n DS18B20初始化成功 \r\n");	
	printf("\r\n DS18B20初始化失败 \r\n");
	
	DS18B20_ReadId ( ucDs18b20Id  );           //读取序列号
	printf("\r\n序列号为:0x");

	for ( uc = 0; uc < 8; uc ++ )             //打印序列号
	 printf ( "%.2x", ucDs18b20Id [ uc ] );
	
	while(1)
	{	
		printf ( "温度为: %.1f\r\n", DS18B20_GetTemp_MatchRom ( ucDs18b20Id ) );
		Delay_ms(1000);	
    }
}