使用HAL库驱动DS18B20温度传感器的STM32教程

1、STM32CubeMx配置IO口


因为DS18B20是单总线,数据接收发送都是这根线,所以单片机配置为开漏上拉输出。

2、定时器配置

因为DS18B20对时序要求比较严格,建议用定时器延时获得微秒延时函数。

总线为48M,分频48,获得1us定时时基。

3、头文件

#ifndef __DS18B20_H
#define __DS18B20_H

#include "main.h"

// 定义DS18B20相关命令
#define DS18B20_CMD_SKIP_ROM        0xCC
#define DS18B20_CMD_CONVERT_T       0x44
#define DS18B20_CMD_READ_SCRATCHPAD 0xBE

void DS18B20_Init(void);
uint8_t DS18B20_Reset(void);
void DS18B20_StartConv(void);
float DS18B20_GetTemp(void);

#endif

4、C文件

#include "ds18b20.h"
#include "tim.h"

#define DS18B20_Set(x) 		HAL_GPIO_WritePin(DS18B20_GPIO_Port, DS18B20_Pin, (GPIO_PinState)(x))
#define DS18B20_Get()	 	HAL_GPIO_ReadPin(DS18B20_GPIO_Port, DS18B20_Pin)

void DS18B20_WriteByte(uint8_t byte);
uint8_t DS18B20_ReadByte(void);


/*****************************************************************************
* 说明:DS18B20的微秒延时函数
* 输入:_usTime时间
* 输出:无
*****************************************************************************/
static void DS18B20_DelayUs(uint16_t _usTime)
{
	__HAL_TIM_SetCounter(&htim1,0);
	__HAL_TIM_ENABLE(&htim1);
	while(__HAL_TIM_GetCounter(&htim1) < _usTime);
	__HAL_TIM_DISABLE(&htim1);
}

/*****************************************************************************
* 说明:复位并检测DS18B20的存在
* 主机和DS18B20做任何通讯前都需要对其初始化。
* 初始化期间,总线控制器拉低总线并保持480us以上挂在总线上的器件将被复位,
* 然后释放总线,等到15-60us,此时18B20将返回一个60-240us之间的低电平存在信号。
* 输入:无
* 输出:1=存在,0=不存在
*****************************************************************************/
uint8_t DS18B20_Reset(void)
{
    uint8_t presence = 0;
    // 拉低总线
    DS18B20_Set(0);
    DS18B20_DelayUs(600);
    
    // 释放总线
    DS18B20_Set(1);
    DS18B20_DelayUs(60);
    
    // 检测DS18B20响应
    presence = DS18B20_Get();
    DS18B20_DelayUs(240);
    
    return !presence;
}

/*****************************************************************************
* 说明:复位DS18B20

* 输入:无
* 输出:无
*****************************************************************************/
void DS18B20_Init(void)
{
    // 复位DS18B20
    DS18B20_Reset();
    
    // 发送跳过ROM命令
    DS18B20_WriteByte(DS18B20_CMD_SKIP_ROM);
}



/*****************************************************************************
* 说明:发送一个字节给DS18B20
* 1.总线控制器要产生一个写时序,必须将总线拉低最少1us,
* 2.产生写0时序时总线必须保持低电平60~120us之间,然后释放总线,
* 3.产生写1时序时在总线产生写时序后的15us内允许把总线拉高。
* 4.注意:2次写周期之间至少间隔1us
* 输入:无
* 输出:无
*****************************************************************************/
void DS18B20_WriteByte(uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++)
    {
        // 发送低位
        DS18B20_Set(0);
        DS18B20_DelayUs(2);
        
        // 发送高位,根据byte的第i位来决定
        if (byte & (1 << i))
        {
            DS18B20_Set(1);
        }
        
        DS18B20_DelayUs(60);
        
        // 释放总线
        DS18B20_Set(1);
    }
}
 

/*****************************************************************************
* 说明:从DS18B20读取一个字节
* 1.总线控制器要产生一个读时序,必须将总线拉低至少1us,
* 2.然后释放总线,在读信号开始后15us内总线控制器采样总线数据,读一位数据至少保持在60us以上。
* 3.注意:2次读周期之间至少间隔1us
* 输入:无
* 输出:无
*****************************************************************************/
uint8_t DS18B20_ReadByte(void)
{
    uint8_t byte = 0;
    
    for (uint8_t i = 0; i < 8; i++)
    {
        // 发送低位
        DS18B20_Set(0);
        DS18B20_DelayUs(2);
        
        // 释放总线
        DS18B20_Set(1);
        DS18B20_DelayUs(8);
        
        // 读取高位数据
        if (DS18B20_Get())
        {
            byte |= (1 << i);
        }
        
        DS18B20_DelayUs(50);
    }
    
    return byte;
}

/*****************************************************************************
* 说明:启动DS18B20转换
* 输入:无
* 输出:无
*****************************************************************************/
void DS18B20_StartConv(void)
{
	DS18B20_Init();
    // 发送温度转换命令
    DS18B20_WriteByte(DS18B20_CMD_CONVERT_T);	
}

/*****************************************************************************
* 说明:读取DS18B20温度
* 1.温度精度及转换时间表
--------------------------------------
R1	R0	精度	最大转换时间	温度LSB
--------------------------------------
0	0	9bit	93.75ms			0.5℃
0	1	10bit	187.5ms			0.25℃
1	0	11bit	375ms			0.125℃
1	1	12bit	750ms			0.0625℃
--------------------------------------
* 输入:无
* 输出:浮点型温度数据
*****************************************************************************/
float DS18B20_GetTemp(void)
{
    
    // 复位DS18B20并跳过ROM
    DS18B20_Init();
    
    // 发送读取寄存器命令
    DS18B20_WriteByte(DS18B20_CMD_READ_SCRATCHPAD);
    
    // 读取温度数据
    uint8_t tempLow = DS18B20_ReadByte();
    uint8_t tempHigh = DS18B20_ReadByte();
    
    // 计算温度值
    int16_t temp = (tempHigh << 8) | tempLow;
    float temperature = (float)temp / 16.0f;/*0.0625℃*/
    
    return temperature;
}


5、使用方法

使用“void DS18B20_StartConv(void)”函数启动转换,因为转换时间需要750ms(12Bit精度),所以隔1秒后,使用“float DS18B20_GetTemp(void)”函数获取温度。

物联沃分享整理
物联沃-IOTWORD物联网 » 使用HAL库驱动DS18B20温度传感器的STM32教程

发表评论