本文记录下使用CH592驱动DS18B20,

以下为ds18b20.c

#include "CH59x_common.h"
#include "ds18b20.h"


// 初始化 DS18B20 传感器
// 此函数用于复位 DS18B20 并检测其是否存在
// 返回值为 0 表示检测到 DS18B20,非 0 表示未检测到
uint8_t DS18B20_Init(void) {
    uint8_t presence;
    // 主机拉低总线 480 - 960us,这里选择 480us
    // 将引脚设置为输出模式
    DS18B20_DQ_H;
    DelayUs(700);
    // 拉低引脚
    DS18B20_DQ_L;
    DelayUs(480);

    // 主机释放总线,等待 15 - 60us,这里选择 60us
    // 将引脚设置为输入模式
    DS18B20_DQ_IN;
    DelayUs(60);

    // 读取总线状态,判断是否有从机响应
    presence = DS18B20_DQ_READ;
    DelayUs(420);

    return presence;
}

// 向 DS18B20 写入一个位
// 参数 bit 为要写入的位值(0 或 1)
void DS18B20_WriteBit(uint8_t bit) {
    if (bit) {
        // 写 1
        // 拉低总线 1us
        DS18B20_DQ_L;
        DelayUs(1);
        // 释放总线,保持 60us
        DS18B20_DQ_IN;
        DelayUs(60);
    } else {
        // 写 0
        // 拉低总线 60us
        DS18B20_DQ_L;
        DelayUs(60);
        // 释放总线
        DS18B20_DQ_IN;
    }
}

// 从 DS18B20 读取一个位
// 返回值为读取到的位值(0 或 1)
uint8_t DS18B20_ReadBit(void) {
    uint8_t bit;
    // 拉低总线 2us
    DS18B20_DQ_L;
    DelayUs(2);
    // 释放总线
    DS18B20_DQ_IN;
    DelayUs(12);
    // 读取总线状态
    bit = DS18B20_DQ_READ;
    DelayUs(50);
    return bit;
}

// 向 DS18B20 写入一个字节
// 参数 byte 为要写入的字节值
void DS18B20_WriteByte(uint8_t byte) {
    for (uint8_t i = 0; i < 8; i++) {
        // 从最低位开始逐位写入
        DS18B20_WriteBit(byte & 0x01);
        byte >>= 1;
    }
}

// 从 DS18B20 读取一个字节
// 返回值为读取到的字节值
uint8_t DS18B20_ReadByte(void) {
    uint8_t byte = 0;
    for (uint8_t i = 0; i < 8; i++) {
        byte >>= 1;
        if (DS18B20_ReadBit()) {
            byte |= 0x80;
        }
    }
    return byte;
}

// 启动 DS18B20 的温度转换
void DS18B20_StartConversion(void) {
    // 复位 DS18B20
    uint32_t start=DS18B20_Init();
    PRINT("start=%x\n",start);
    // 跳过 ROM 操作,适用于单总线只有一个 DS18B20 的情况
    DS18B20_WriteByte(0xCC);
    // 启动温度转换
    DS18B20_WriteByte(0x44);
}

// 读取 DS18B20 的温度值
// 返回值为读取到的温度值,单位为摄氏度
float DS18B20_ReadTemperature(void) {
    uint8_t temp_l, temp_h;
    int16_t temp;
    float temperature;

    // 复位 DS18B20
    DS18B20_Init();
    // 跳过 ROM 操作
    DS18B20_WriteByte(0xCC);
    // 读取温度寄存器
    DS18B20_WriteByte(0xBE);

    // 读取温度值的低 8 位
    temp_l = DS18B20_ReadByte();
    // 读取温度值的高 8 位
    temp_h = DS18B20_ReadByte();

    // 组合高低 8 位得到 16 位温度值
    temp = (temp_h << 8) | temp_l;
    // 根据 DS18B20 的数据格式,将 16 位值转换为实际温度值
    temperature = (float)temp / 16.0;

    return temperature;
}

以下为以下为ds18b20.h

#ifndef __DS18B20_H__
#define __DS18B20_H__

// 定义 DS18B20 连接的引脚
#define DS18B20_PORT  1              //1为GPIOA 0为GPIOB
#define DS18B20_PIN   GPIO_Pin_4

#if (DS18B20_PORT==1)
#define DS18B20_DQ_H  {\
    GPIOA_SetBits(DS18B20_PIN);\
    GPIOA_ModeCfg(DS18B20_PIN, GPIO_ModeOut_PP_5mA);\
}

#define DS18B20_DQ_L  {\
    GPIOA_ResetBits(DS18B20_PIN);\
    GPIOA_ModeCfg(DS18B20_PIN, GPIO_ModeOut_PP_5mA);\
}

#define DS18B20_DQ_IN    GPIOA_ModeCfg(DS18B20_PIN, GPIO_ModeIN_PU);

#define DS18B20_DQ_READ  GPIOA_ReadPortPin(DS18B20_PIN);
#endif

#if (DS18B20_PORT==0)
#define DS18B20_DQ_H  {\
    GPIOB_SetBits(DS18B20_PIN);\
    GPIOB_ModeCfg(DS18B20_PIN, GPIO_ModeOut_PP_5mA);\
}

#define DS18B20_DQ_L  {\
    GPIOB_ResetBits(DS18B20_PIN);\
    GPIOB_ModeCfg(DS18B20_PIN, GPIO_ModeOut_PP_5mA);\
}

#define DS18B20_DQ_IN    GPIOB_ModeCfg(DS18B20_PIN, GPIO_ModeIN_PU);

#define DS18B20_DQ_READ  GPIOB_ReadPortPin(DS18B20_PIN);
#endif

extern uint8_t DS18B20_Init(void);
extern void DS18B20_WriteBit(uint8_t bit);
extern uint8_t DS18B20_ReadBit(void);
extern void DS18B20_WriteByte(uint8_t byte);
extern uint8_t DS18B20_ReadByte(void);
extern void DS18B20_StartConversion(void);
extern float DS18B20_ReadTemperature(void);

#endif

mian函数:

    while (1) {
           // 启动温度转换
           DS18B20_StartConversion();
           // 等待转换完成,最大转换时间为 750ms
           DelayMs(750);
           // 读取温度值
           float temp = DS18B20_ReadTemperature();
           PRINT("TEM=%f\n",temp);
           DelayMs(1000);
       }

 

posted on 2025-05-07 20:26  WCH蓝牙应用分享  阅读(60)  评论(0)    收藏  举报