STM32 HAL库 DS18B20驱动实现

一、DS18B20 简介

DS18B20 是由 Dallas Semiconductor 公司生产的单总线数字温度传感器。它具有以下特点:

  • 单总线接口:仅需一个引脚即可与微控制器进行通信,减少了硬件连接的复杂度。
  • 数字输出:直接输出数字温度值,无需额外的模数转换电路。
  • 精度高:可编程分辨率为 9 - 12 位,对应的温度精度分别为 0.5°C、0.25°C、0.125°C 和 0.0625°C。
  • 宽温度范围:测量范围为 -55°C 到 +125°C。

二、硬件连接

在使用 STM32F407 与 DS18B20 进行连接时,需要将 DS18B20 的数据线(DQ)连接到 STM32F407 的一个 GPIO 引脚。同时,DS18B20 的电源引脚(VDD)接 3.3V 或 5V,接地引脚(GND)接地。为了保证通信的稳定性,通常需要在 DQ 引脚上拉一个 4.7KΩ 的电阻到电源。

三、驱动代码实现

1. 初始化 GPIO 引脚

首先,需要初始化与 DS18B20 连接的 GPIO 引脚。以下是使用 STM32Cube HAL 库进行初始化的代码:

复制代码
#include "stm32f4xx_hal.h"

#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_PIN_0

void DS18B20_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = DS18B20_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
}
2. 单总线复位脉冲

DS18B20 的通信需要先发送一个复位脉冲,以检测设备是否存在。以下是复位脉冲的代码实现:

复制代码
uint8_t DS18B20_Reset(void) {
    uint8_t presence;

    // 拉低总线480 - 960us
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
    HAL_Delay(1);

    // 释放总线,等待15 - 60us
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
    HAL_Delay(1);

    // 读取DS18B20的存在脉冲
    presence = HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN);
    HAL_Delay(4);

    return presence;
}
3. 写一位数据

向 DS18B20 写入一位数据的代码如下:

复制代码
void DS18B20_WriteBit(uint8_t bit) {
    if (bit) {
        // 写1
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        __asm("nop");
        __asm("nop");
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        HAL_Delay(1);
    } else {
        // 写0
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        HAL_Delay(1);
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        __asm("nop");
        __asm("nop");
    }
}
4. 读一位数据

从 DS18B20 读取一位数据的代码如下:

复制代码
uint8_t DS18B20_ReadBit(void) {
    uint8_t bit;

    // 拉低总线1 - 15us
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
    __asm("nop");
    __asm("nop");

    // 释放总线,等待1 - 15us后读取数据
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
    __asm("nop");
    __asm("nop");
    bit = HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN);
    HAL_Delay(1);

    return bit;
}
5. 写一个字节数据

向 DS18B20 写入一个字节数据的代码如下:

复制代码
void DS18B20_WriteByte(uint8_t byte) {
    uint8_t i;

    for (i = 0; i < 8; i++) {
        DS18B20_WriteBit(byte & 0x01);
        byte >>= 1;
    }
}
6. 读一个字节数据

从 DS18B20 读取一个字节数据的代码如下:

复制代码
uint8_t DS18B20_ReadByte(void) {
    uint8_t i, byte = 0;

    for (i = 0; i < 8; i++) {
        byte >>= 1;
        if (DS18B20_ReadBit()) {
            byte |= 0x80;
        }
    }

    return byte;
}
7. 启动温度转换

启动 DS18B20 进行温度转换的代码如下:

复制代码
void DS18B20_StartConversion(void) {
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM操作
    DS18B20_WriteByte(0x44); // 启动温度转换
}
8. 读取温度值

读取 DS18B20 的温度值的代码如下:

复制代码
float DS18B20_ReadTemperature(void) {
    uint8_t temp_l, temp_h;
    int16_t temp;
    float temperature;

    DS18B20_StartConversion();
    HAL_Delay(750); // 等待转换完成

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

    temp_l = DS18B20_ReadByte();
    temp_h = DS18B20_ReadByte();

    temp = (temp_h << 8) | temp_l;
    temperature = (float)temp / 16.0;

    return temperature;
}

四、测试代码

以下是一个简单的测试代码,用于在主函数中调用 DS18B20 驱动函数并打印温度值:

复制代码
#include "stm32f4xx_hal.h"
#include <stdio.h>

#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_PIN_0

// 前面定义的驱动函数

int main(void) {
    HAL_Init();
    DS18B20_GPIO_Init();

    while (1) {
        float temperature = DS18B20_ReadTemperature();
        printf("Temperature: %.2f °C\n", temperature);
        HAL_Delay(1000);
    }
}

五、代码解释

  1. GPIO 初始化:将与 DS18B20 连接的 GPIO 引脚初始化为开漏输出模式,以适应单总线通信的要求。
  2. 复位脉冲:通过拉低总线一段时间,然后释放总线,等待 DS18B20 返回存在脉冲,以检测设备是否正常工作。
  3. 读写位和字节:通过控制总线的高低电平,实现向 DS18B20 写入一位或一个字节的数据,以及从 DS18B20 读取一位或一个字节的数据。
  4. 启动温度转换:发送特定的命令字节,启动 DS18B20 进行温度转换。
  5. 读取温度值:在温度转换完成后,读取温度寄存器的值,并将其转换为实际的温度值。

六、注意事项

  • 延时时间 :DS18B20 的通信协议对延时时间要求较高,需要确保延时时间的准确性。在上述代码中,使用了HAL_Delay()函数进行延时,实际应用中可以根据需要进行调整。
  • 上拉电阻:为了保证通信的稳定性,需要在 DQ 引脚上拉一个 4.7KΩ 的电阻到电源。
  • 温度转换时间:DS18B20 的温度转换时间与分辨率有关,最高分辨率(12 位)下的转换时间为 750ms。在读取温度值之前,需要等待转换完成。

七、总结

通过以上代码,你可以实现基于 STM32F407 HAL 库的 DS18B20 驱动。该驱动代码可以方便地集成到你的项目中,用于实时监测环境温度。在实际应用中,你可以根据需要对代码进行优化和扩展,例如添加错误处理、多设备支持等功能。

希望以上内容对你有所帮助。如果你在使用过程中遇到任何问题,可以随时进行提问。

相关推荐
SundayBear9 小时前
零基础入门MQTT协议
c语言·单片机
嗯嗯=9 小时前
STM32单片机学习篇9
stm32·单片机·学习
小范馆14 小时前
ESP各模组的引脚图-小智接线图
stm32
松涛和鸣14 小时前
DAY63 IMX6ULL ADC Driver Development
linux·运维·arm开发·单片机·嵌入式硬件·ubuntu
想放学的刺客17 小时前
单片机嵌入式试题(第23期)嵌入式系统电源管理策略设计、嵌入式系统通信协议栈实现要点两个全新主题。
c语言·stm32·单片机·嵌入式硬件·物联网
猫猫的小茶馆18 小时前
【Linux 驱动开发】五. 设备树
linux·arm开发·驱动开发·stm32·嵌入式硬件·mcu·硬件工程
YouEmbedded18 小时前
解码内部集成电路(IIC)与OLED屏
stm32·0.96寸oled·硬件iic·软件模拟iic·图片取模·汉字取模
jghhh0119 小时前
基于上海钜泉科技HT7017单相计量芯片的参考例程实现
科技·单片机·嵌入式硬件
恶魔泡泡糖19 小时前
51单片机外部中断
c语言·单片机·嵌入式硬件·51单片机
意法半导体STM3219 小时前
【官方原创】如何基于DevelopPackage开启安全启动(MP15x) LAT6036
javascript·stm32·单片机·嵌入式硬件·mcu·安全·stm32开发