基于STM32F103C8T6(Blue Pill开发板)和DS18B20温度传感器的温度测量系统实现
系统概述
这个系统使用STM32F103C8T6单片机读取DS18B20数字温度传感器的数据,并通过串口将温度值发送到电脑或其他设备显示。DS18B20是一款常用的数字温度传感器,具有单总线接口、高精度(±0.5°C)和可编程分辨率等特点。
硬件设计
所需组件
- STM32F103C8T6开发板(Blue Pill)
- DS18B20温度传感器
- 4.7kΩ上拉电阻
- 面包板和连接线
电路连接
| STM32F103C8T6 | DS18B20 |
|---|---|
| 3.3V | VDD |
| GND | GND |
| 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
使用
- 按照电路连接图连接STM32F103C8T6和DS18B20
- 使用STM32CubeIDE或Keil MDK创建新项目
- 将上述代码添加到项目中
- 配置项目设置,确保正确选择STM32F103C8T6芯片
- 编译并下载程序到开发板
- 使用串口调试工具(如Putty、Tera Term等)连接开发板的串口(波特率115200)
- 观察温度数据输出
扩展
-
多传感器支持:DS18B20支持单总线上连接多个传感器,可以通过读取每个传感器的唯一ROM地址来实现多传感器测量。
-
温度报警:可以设置温度上下限,当温度超出范围时触发报警。
-
LCD显示:添加LCD显示屏,直接显示温度值,而不需要通过串口。
-
数据记录:添加SD卡模块,将温度数据记录到文件中。
-
无线传输:添加Wi-Fi或蓝牙模块,实现无线温度监控。
1万+

被折叠的 条评论
为什么被折叠?



