基于STM32F103C8T6与DS18B20的温度测量系统

基于STM32F103C8T6(Blue Pill开发板)和DS18B20温度传感器的温度测量系统实现

系统概述

这个系统使用STM32F103C8T6单片机读取DS18B20数字温度传感器的数据,并通过串口将温度值发送到电脑或其他设备显示。DS18B20是一款常用的数字温度传感器,具有单总线接口、高精度(±0.5°C)和可编程分辨率等特点。

硬件设计

所需组件

  1. STM32F103C8T6开发板(Blue Pill)
  2. DS18B20温度传感器
  3. 4.7kΩ上拉电阻
  4. 面包板和连接线

电路连接

STM32F103C8T6DS18B20
3.3VVDD
GNDGND
PA0 (或其他GPIO)DQ

在DQ线和3.3V之间连接一个4.7kΩ的上拉电阻。

软件实现

1. 单总线协议实现

首先,我们需要实现DS18B20的单总线通信协议。创建一个ds18b20.h头文件:

#ifndef DS18B20_H
#define DS18B20_H

#include "stm32f1xx_hal.h"

// 定义DS18B20引脚
#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_PIN_0

// 函数声明
void DS18B20_Init(void);
void DS18B20_StartConversion(void);
float DS18B20_ReadTemperature(void);
uint8_t DS18B20_ReadByte(void);
void DS18B20_WriteByte(uint8_t data);
void DS18B20_SetResolution(uint8_t resolution);

#endif

创建ds18b20.c源文件实现单总线协议:

#include "ds18b20.h"
#include "main.h"

// 微秒级延迟函数
static void Delay_us(uint32_t us) {
    us *= (SystemCoreClock / 1000000) / 5;
    while (us--) {
        __NOP();
    }
}

// 初始化DS18B20
void DS18B20_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能GPIOA时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // 配置GPIO引脚
    GPIO_InitStruct.Pin = DS18B20_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
    
    // 设置高电平
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
}

// 发送复位脉冲并检测存在脉冲
uint8_t DS18B20_Reset(void) {
    uint8_t presence = 0;
    
    // 拉低总线480us
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
    Delay_us(480);
    
    // 释放总线
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
    Delay_us(70);
    
    // 检测存在脉冲
    if (!HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)) {
        presence = 1; // 设备存在
    }
    
    Delay_us(410);
    
    return presence;
}

// 从DS18B20读取一个字节
uint8_t DS18B20_ReadByte(void) {
    uint8_t value = 0;
    
    for (uint8_t i = 0; i < 8; i++) {
        // 拉低总线1us
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        Delay_us(1);
        
        // 释放总线
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        Delay_us(10);
        
        // 读取位
        if (HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)) {
            value |= (1 << i);
        }
        
        Delay_us(50);
    }
    
    return value;
}

// 向DS18B20写入一个字节
void DS18B20_WriteByte(uint8_t data) {
    for (uint8_t i = 0; i < 8; i++) {
        // 拉低总线
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        Delay_us(1);
        
        // 如果当前位是1,则释放总线;如果是0,保持低电平
        if (data & (1 << i)) {
            HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        }
        
        Delay_us(60);
        
        // 释放总线
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        Delay_us(1);
    }
}

// 开始温度转换
void DS18B20_StartConversion(void) {
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0x44); // 开始转换命令
}

// 读取温度值
float DS18B20_ReadTemperature(void) {
    uint8_t temp_lsb, temp_msb;
    int16_t temp_raw;
    float temperature;
    
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0xBE); // 读取暂存器命令
    
    // 读取温度值(前两个字节)
    temp_lsb = DS18B20_ReadByte();
    temp_msb = DS18B20_ReadByte();
    
    // 组合温度值
    temp_raw = (temp_msb << 8) | temp_lsb;
    
    // 转换为实际温度值
    temperature = temp_raw * 0.0625;
    
    return temperature;
}

// 设置分辨率
void DS18B20_SetResolution(uint8_t resolution) {
    uint8_t config;
    
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0x4E); // 写暂存器命令
    
    // 写TH和TL寄存器(这里设置为0)
    DS18B20_WriteByte(0x00);
    DS18B20_WriteByte(0x00);
    
    // 写配置寄存器
    switch (resolution) {
        case 9:
            config = 0x1F;
            break;
        case 10:
            config = 0x3F;
            break;
        case 11:
            config = 0x5F;
            break;
        case 12:
        default:
            config = 0x7F;
            break;
    }
    DS18B20_WriteByte(config);
    
    // 保存配置
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM命令
    DS18B20_WriteByte(0x48); // 复制暂存器命令
    Delay_us(100);
}

2. 主程序实现

创建main.c文件:

#include "stm32f1xx_hal.h"
#include "ds18b20.h"
#include <stdio.h>

// 串口句柄
UART_HandleTypeDef huart1;

// 函数声明
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
void Error_Handler(void);

int main(void) {
    float temperature;
    char msg[50];
    
    // HAL库初始化
    HAL_Init();
    
    // 系统时钟配置
    SystemClock_Config();
    
    // 外设初始化
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    
    // DS18B20初始化
    DS18B20_Init();
    
    // 设置DS18B20分辨率为12位
    DS18B20_SetResolution(12);
    
    // 发送欢迎消息
    const char *welcome_msg = "DS18B20 Temperature Monitoring System\r\n";
    HAL_UART_Transmit(&huart1, (uint8_t*)welcome_msg, strlen(welcome_msg), HAL_MAX_DELAY);
    
    while (1) {
        // 启动温度转换
        DS18B20_StartConversion();
        
        // 等待转换完成(最大750ms for 12-bit resolution)
        HAL_Delay(750);
        
        // 读取温度值
        temperature = DS18B20_ReadTemperature();
        
        // 格式化温度字符串
        sprintf(msg, "Temperature: %.2f C\r\n", temperature);
        
        // 通过串口发送温度值
        HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
        
        // 等待1秒
        HAL_Delay(1000);
    }
}

// 系统时钟配置
void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    // 配置HSE振荡器
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    // 配置系统时钟
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}

// USART1初始化
static void MX_USART1_UART_Init(void) {
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart1);
}

// GPIO初始化
static void MX_GPIO_Init(void) {
    // 无需额外GPIO初始化,DS18B20的初始化在DS18B20_Init()中完成
}

// 错误处理函数
void Error_Handler(void) {
    while (1) {
        // 错误处理代码
    }
}

// 重写fputc函数,支持printf
int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
    return ch;
}

3. 添加必要的支持文件

创建stm32f1xx_it.c文件处理中断:

#include "stm32f1xx_it.h"

void NMI_Handler(void) {
}

void HardFault_Handler(void) {
    while (1) {
    }
}

void SVC_Handler(void) {
}

void PendSV_Handler(void) {
}

void SysTick_Handler(void) {
    HAL_IncTick();
}

参考代码 基于STM32F103C8T6单片机与DS18B20温度传感器的温度测量 www.youwenfan.com/contentcsk/56802.html

使用

  1. 按照电路连接图连接STM32F103C8T6和DS18B20
  2. 使用STM32CubeIDE或Keil MDK创建新项目
  3. 将上述代码添加到项目中
  4. 配置项目设置,确保正确选择STM32F103C8T6芯片
  5. 编译并下载程序到开发板
  6. 使用串口调试工具(如Putty、Tera Term等)连接开发板的串口(波特率115200)
  7. 观察温度数据输出

扩展

  1. 多传感器支持:DS18B20支持单总线上连接多个传感器,可以通过读取每个传感器的唯一ROM地址来实现多传感器测量。

  2. 温度报警:可以设置温度上下限,当温度超出范围时触发报警。

  3. LCD显示:添加LCD显示屏,直接显示温度值,而不需要通过串口。

  4. 数据记录:添加SD卡模块,将温度数据记录到文件中。

  5. 无线传输:添加Wi-Fi或蓝牙模块,实现无线温度监控。

随着现代工农业技术的发展及人们对生活环境要求的提高,人们也迫切需要检测控制温湿度,且温湿度是工农业生产的主要环境数据,在工农业生产实践中占有重要地位,比如湿度大温度高的话话会使粮食发芽、腐败,有可能还会导致二氧化碳的增加,如果是密闭的环境还可能导致进入的工人窒息,如果粮食发芽会导致温度升高,从而更加容易产生火灾等安全事故。所以对其进行适时准确的温湿度测量具有重要意义。 温湿度测量在工业生产中有着广泛的应用。通常,要实现温湿度测量和自动控制,监控台现场之间必须铺设电缆,这是一个麻烦的问题,且传统的温湿度传感器需要通过复杂的电路才能将温湿度信号转化为数字信号,且距离传输所造成的损耗会引起误差。本系统采用无线温湿度测量的方案,不必铺设电缆,可以节省费用和时间,采集也更加的方便。该采集系统以STM32F103C8T6为主控芯片,利用数字式温湿度传感器DHT11进行采集,然后将采集的数据传送给单片机,经过处理,单片机将数据通过无线传输模块NRF24L01发射出去,单片机无线模块之间的通信采用SPI方式。控制台那边也是采用STM32F103C8T6作为主控芯片,外部接有无线接收模块NRF24L01和液晶Nokia5110;经过一定距离的无线通信,接收模块接收到数据之后将数据传给主控芯片,主控芯片经过处理后将数据通过液晶显示。至此完成一次温湿度无线采集的发送接收。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值