DS18B20测量温度


一、DS18B20读取温度步骤

一般在使用DS18B20时会按照以下步骤进行温度转换并读取:
1、主机发送复位脉冲
2、DS18B20响应
3、发送0xCC命令跳过ROM命令
4、发送功能命令
5、发送功能命令0x44启动温度转换
6、判断温度转换是否完成(为读取1Bit数据为1表示完成)
7、下一个初始化序列开始读取温度
8、然后按照序号1、2、3、4的顺序执行一遍,发送功能命令0xBE
9、读取温度
在这里插入图片描述

在这里插入图片描述

二、初始化复位时序

在这里插入图片描述

/** 
 * @brief 开始时序
 * @param OneWire_TypeDef *pOneWire
 * @retval: 
 */
static uint8_t OneWire_StartPulse(OneWire_TypeDef * const pOneWire)
{
    HAL_GPIO_SetOutput(&pOneWire->DIO);//产生复位时序 >480us
    HAL_GPIO_Low(&pOneWire->DIO);
    Delay_us(500);
    HAL_GPIO_SetInput(&pOneWire->DIO);//等待读取应答信号 等待时间15us~60us
    for (uint8_t i = 0; i <= 60; i++)
    {
        if (HAL_GPIO_Read(&pOneWire->DIO) == 0)
        {
            break;
        }
        if(i == 60)
        {
            return 1;
        }
        Delay_us(1);
    }
    for (uint8_t i = 0; i <= 240; i++)//等待DS18B20释放总线 应答时间60us~240us
    {
        if (HAL_GPIO_Read(&pOneWire->DIO) == 1)
        {
            break;
        }
        if(i == 240)
        {
            return 2;
        }
        Delay_us(1);
    }
    return 0;
}

2.发送一个字节

从图中可以看到发送逻辑0为拉低总线60~120us,逻辑1为拉低总线后拉高总线整个时序要大于60us。
在这里插入图片描述

/** 
 * @brief 发送一个字节数据
 * @param OneWire_TypeDef *pOneWire
 * @param uint8_t dat
 * @retval: 
 */
static void OneWire_SendByte(OneWire_TypeDef * const pOneWire, uint8_t dat)
{
    HAL_GPIO_SetOutput(&pOneWire->DIO);
    for (uint8_t i = 0; i < 8; i++)
    {
        HAL_GPIO_Low(&pOneWire->DIO);
        Delay_us(10);
        if (dat & 0x01)//发送1 时序为拉低1us~15us 然后释放总线,时序大于60us
        {
            HAL_GPIO_High(&pOneWire->DIO);
            Delay_us(60);
        }
        else//发送0 时序是拉低60us~120us 然后释放总线要大于1us,时序大于60us
        {
            Delay_us(60);
            HAL_GPIO_High(&pOneWire->DIO);
            Delay_us(5);
        }
        dat >>= 1;
    }    
}

二、读取数据

在这里插入图片描述

1、读取一个Bit

从图中可以看到主机拉低总线1~15us后释放总线,然后主机读取总线数据。

/** 
 * @brief 接收一个位数据
 * @param OneWire_TypeDef *pOneWire
 * @retval: 
 */
static uint8_t OneWire_ReadBit(OneWire_TypeDef * const pOneWire)
{
    uint8_t Bit = 0;
    HAL_GPIO_SetOutput(&pOneWire->DIO);//读取时序 主机将总线拉低1~15us,然后释放总线,在15us后读取数据,时序大于60us
    HAL_GPIO_Low(&pOneWire->DIO);
    Delay_us(5);
    HAL_GPIO_SetInput(&pOneWire->DIO);
    Delay_us(10);
    Bit = HAL_GPIO_Read(&pOneWire->DIO);
    Delay_us(60);
    return Bit;
}

2、读取一个字节

读取一个字节数据将读一个Bit循环8次就可以了。

/** 
 * @brief 从OneWire读取一个字节 
 * @param OneWire_TypeDef *pOneWire
 * @retval: 
 */
static uint8_t OneWire_ReadByte(OneWire_TypeDef * const pOneWire)
{
    uint8_t dat = 0;
    for (uint8_t i = 0; i < 8; i++)
    {
        dat >>= 1;
        dat |= OneWire_ReadBit(pOneWire);
    }
    return dat;
}

三、启动温度转换

/** 
 * @brief 启动一个温度转换
 * @param DS18B20_TypeDef *pDS18B20
 * @retval 0:成功 1:失败
 */
uint8_t DS18B20_Convert(DS18B20_TypeDef * const pDS18B20)
{
    uint8_t result = 0;
    result = OneWire_StartPulse(&pDS18B20->DQ);
    if (result)
        return result;
    OneWire_SendByte(&pDS18B20->DQ, 0xCC);//发送跳过ROM命令
    OneWire_SendByte(&pDS18B20->DQ, 0x44);//发送转换命令
    return 0;
}

四、判断转换完成

/** 
 * @brief 检测温度转换是否完成
 * @param DS18B20_TypeDef *pDS18B20
 * @retval 0:转换中 1:转换完成
 */
uint8_t DS18B20_IsConvertFinish(DS18B20_TypeDef * const pDS18B20)
{
    return OneWire_ReadBit(&pDS18B20->DQ);
}

五、读取温度

/** 
 * @brief 读取温度值
 * @param DS18B20_TypeDef *pDS18B20
 * @param float *temperature 温度值
 * @retval 0:成功 1:失败
 */
uint8_t DS18B20_ReadTemperature(DS18B20_TypeDef * const pDS18B20, float *temperature)
{
    uint8_t result = 0;
    uint8_t TL,TM;
    result = OneWire_StartPulse(&pDS18B20->DQ);
    if (result)
        return result;
    OneWire_SendByte(&pDS18B20->DQ, 0xCC);//发送跳过ROM命令
    OneWire_SendByte(&pDS18B20->DQ, 0xBE);//发送读取命令
    TL = OneWire_ReadByte(&pDS18B20->DQ);//读取温度高位
    TM = OneWire_ReadByte(&pDS18B20->DQ);//读取温度低位
    if ((TM & 0xF8) == 0)//正数
    {
        *temperature = ((int16_t)((TM << 8) | TL)) * 0.0625f;
    }
    else//负数
    {
        *temperature = -((~(int16_t)((TM << 8) | TL)) + 1) * 0.0625f;
    }
    return 0;
}

程序地址


版权声明:本文为weixin_43908815原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。