文章目录

  • 一、DS18B20读取温度步骤
  • 二、初始化复位时序
  • 2.发送一个字节
  • 二、读取数据
  • 1、读取一个Bit
  • 2、读取一个字节
  • 三、启动温度转换
  • 四、判断转换完成
  • 五、读取温度
  • 程序地址

  • 一、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;
    }
    
    

    程序地址

    物联沃分享整理
    物联沃-IOTWORD物联网 » DS18B20测量温度

    发表评论