当前位置: 首页 > news >正文

手把手教你用STM32F103C8T6驱动DS18B20,附完整代码和LCD1602显示教程

基于STM32F103的智能温度监测系统开发实战

在嵌入式开发领域,温度监测是最基础也最实用的应用场景之一。对于刚接触STM32系列单片机的开发者来说,如何将传感器数据采集、处理与显示完整实现,是一个极具学习价值的项目。本文将使用STM32F103C8T6这款性价比极高的MCU,搭配DS18B20数字温度传感器和LCD1602显示屏,构建一个实时温度监测系统。

1. 硬件准备与电路连接

1.1 核心器件选型与特性

STM32F103C8T6作为本项目的核心控制器,是一款基于ARM Cortex-M3内核的微控制器,具有以下优势:

  • 72MHz主频,性能足够处理传感器数据
  • 64KB Flash和20KB SRAM,满足程序存储需求
  • 丰富的GPIO和外设接口
  • 广泛的社区支持和开发资源

DS18B20是一款数字温度传感器,其特点包括:

  • 单总线接口,仅需一个GPIO即可通信
  • 测量范围:-55°C至+125°C
  • 精度:±0.5°C(-10°C至+85°C范围内)
  • 内置12位ADC,分辨率可达0.0625°C

LCD1602作为显示模块,具有:

  • 16字符×2行的显示能力
  • 支持标准4位或8位并行接口
  • 低功耗,易于集成

1.2 硬件连接方案

以下是推荐的连接方式(基于4位数据模式):

STM32引脚连接目标备注
PA0DS18B20 DATA需接4.7kΩ上拉电阻
PB0-PB3LCD1602 D4-D7数据线
PB4LCD1602 RS寄存器选择
PB5LCD1602 RW读写控制
PB6LCD1602 E使能信号
3.3VLCD1602 VCC电源
GNDLCD1602 GND地线

注意:DS18B20的数据线必须接4.7kΩ上拉电阻至3.3V,否则无法正常通信。

2. 开发环境配置

2.1 工具链搭建

推荐使用以下开发工具:

  • STM32CubeIDE:官方集成开发环境,包含编译器、调试器和硬件配置工具
  • STM32CubeMX:图形化引脚配置工具(已集成在CubeIDE中)
  • 串口调试助手:用于调试输出

安装步骤:

  1. 从ST官网下载并安装STM32CubeIDE
  2. 创建新工程,选择STM32F103C8T6作为目标芯片
  3. 通过CubeMX配置时钟树和引脚功能

2.2 工程基础配置

关键配置参数:

  • 系统时钟:72MHz(外部8MHz晶振倍频)
  • GPIO模式:
    • DS18B20数据引脚:推挽输出/浮空输入
    • LCD控制引脚:推挽输出
  • 调试接口:SWD(Serial Wire Debug)

时钟配置代码示例:

void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 配置主PLL RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_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); }

3. DS18B20驱动实现

3.1 单总线协议解析

DS18B20采用单总线通信协议,其基本时序包括:

  1. 初始化序列:主机发送复位脉冲,从机回应存在脉冲
  2. ROM命令:如跳过ROM(0xCC)或匹配ROM(0x55)
  3. 功能命令:如启动温度转换(0x44)或读取暂存器(0xBE)

关键时序参数(单位:微秒):

操作最小值典型值最大值
复位脉冲480480960
从机响应1560240
写0时间6060120
写1时间11515
读采样时间1-15

3.2 驱动程序实现

以下是核心驱动函数的实现:

// 初始化DS18B20 uint8_t DS18B20_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 配置GPIO为输出模式 GPIO_InitStruct.Pin = DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); // 发送复位脉冲 HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET); delay_us(480); HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); // 切换为输入模式等待响应 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); delay_us(60); uint8_t response = HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN); delay_us(420); return response; // 0表示设备存在,1表示无设备 } // 写入一个字节 void DS18B20_WriteByte(uint8_t data) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); for(uint8_t i=0; i<8; i++) { HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET); delay_us(2); if(data & 0x01) { HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); } delay_us(60); HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); data >>= 1; delay_us(2); } } // 读取一个字节 uint8_t DS18B20_ReadByte(void) { uint8_t data = 0; GPIO_InitTypeDef GPIO_InitStruct = {0}; for(uint8_t i=0; i<8; i++) { GPIO_InitStruct.Pin = DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET); delay_us(2); HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); delay_us(8); data >>= 1; if(HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)) { data |= 0x80; } delay_us(50); } return data; }

3.3 温度读取与处理

完整的温度读取流程:

  1. 初始化DS18B20
  2. 发送跳过ROM命令(0xCC)
  3. 发送启动温度转换命令(0x44)
  4. 等待转换完成(典型750ms)
  5. 再次初始化DS18B20
  6. 发送跳过ROM命令(0xCC)
  7. 发送读取暂存器命令(0xBE)
  8. 读取两个字节的温度数据
  9. 将原始数据转换为实际温度值

温度转换代码示例:

float DS18B20_GetTemp(void) { uint8_t tempL, tempH; int16_t temp; float temperature; DS18B20_Init(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0x44); // 启动转换 HAL_Delay(750); // 等待转换完成 DS18B20_Init(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0xBE); // 读取暂存器 tempL = DS18B20_ReadByte(); // LSB tempH = DS18B20_ReadByte(); // MSB temp = (tempH << 8) | tempL; temperature = temp * 0.0625; // 12位分辨率 return temperature; }

4. LCD1602显示驱动

4.1 LCD初始化与基本指令

LCD1602的4位接口初始化序列:

  1. 等待15ms(上电稳定时间)
  2. 发送函数设置命令(0x28) - 4位模式,2行显示,5x8点阵
  3. 发送显示开关控制(0x0C) - 显示开,光标关,闪烁关
  4. 发送清屏命令(0x01)
  5. 发送输入模式设置(0x06) - 地址自动递增,不移位

初始化代码实现:

void LCD_Init(void) { HAL_Delay(15); // 上电等待 // 切换到4位模式 LCD_WriteCmd(0x33); LCD_WriteCmd(0x32); // 函数设置 LCD_WriteCmd(0x28); // 4位,2行,5x8 // 显示控制 LCD_WriteCmd(0x0C); // 显示开,光标关 // 清屏 LCD_WriteCmd(0x01); HAL_Delay(2); // 输入模式 LCD_WriteCmd(0x06); // 地址自增 }

4.2 数据写入与字符串显示

核心写入函数实现:

// 写入命令 void LCD_WriteCmd(uint8_t cmd) { HAL_GPIO_WritePin(LCD_RS_PORT, LCD_RS_PIN, GPIO_PIN_RESET); // 命令模式 HAL_GPIO_WritePin(LCD_RW_PORT, LCD_RW_PIN, GPIO_PIN_RESET); // 写操作 // 高4位 HAL_GPIO_WritePin(LCD_D4_PORT, LCD_D4_PIN, (cmd >> 4) & 0x01); HAL_GPIO_WritePin(LCD_D5_PORT, LCD_D5_PIN, (cmd >> 5) & 0x01); HAL_GPIO_WritePin(LCD_D6_PORT, LCD_D6_PIN, (cmd >> 6) & 0x01); HAL_GPIO_WritePin(LCD_D7_PORT, LCD_D7_PIN, (cmd >> 7) & 0x01); LCD_Enable(); // 低4位 HAL_GPIO_WritePin(LCD_D4_PORT, LCD_D4_PIN, (cmd >> 0) & 0x01); HAL_GPIO_WritePin(LCD_D5_PORT, LCD_D5_PIN, (cmd >> 1) & 0x01); HAL_GPIO_WritePin(LCD_D6_PORT, LCD_D6_PIN, (cmd >> 2) & 0x01); HAL_GPIO_WritePin(LCD_D7_PORT, LCD_D7_PIN, (cmd >> 3) & 0x01); LCD_Enable(); HAL_Delay(1); } // 写入数据 void LCD_WriteData(uint8_t data) { HAL_GPIO_WritePin(LCD_RS_PORT, LCD_RS_PIN, GPIO_PIN_SET); // 数据模式 HAL_GPIO_WritePin(LCD_RW_PORT, LCD_RW_PIN, GPIO_PIN_RESET); // 写操作 // 高4位 HAL_GPIO_WritePin(LCD_D4_PORT, LCD_D4_PIN, (data >> 4) & 0x01); HAL_GPIO_WritePin(LCD_D5_PORT, LCD_D5_PIN, (data >> 5) & 0x01); HAL_GPIO_WritePin(LCD_D6_PORT, LCD_D6_PIN, (data >> 6) & 0x01); HAL_GPIO_WritePin(LCD_D7_PORT, LCD_D7_PIN, (data >> 7) & 0x01); LCD_Enable(); // 低4位 HAL_GPIO_WritePin(LCD_D4_PORT, LCD_D4_PIN, (data >> 0) & 0x01); HAL_GPIO_WritePin(LCD_D5_PORT, LCD_D5_PIN, (data >> 1) & 0x01); HAL_GPIO_WritePin(LCD_D6_PORT, LCD_D6_PIN, (data >> 2) & 0x01); HAL_GPIO_WritePin(LCD_D7_PORT, LCD_D7_PIN, (data >> 3) & 0x01); LCD_Enable(); HAL_Delay(1); } // 使能信号 void LCD_Enable(void) { HAL_GPIO_WritePin(LCD_E_PORT, LCD_E_PIN, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(LCD_E_PORT, LCD_E_PIN, GPIO_PIN_RESET); delay_us(100); }

4.3 温度显示实现

在LCD上显示温度值的完整流程:

  1. 清屏
  2. 设置显示位置(第一行)
  3. 显示静态文本(如"Temperature:")
  4. 设置显示位置(第二行)
  5. 将浮点温度值转换为字符串
  6. 显示温度值和单位

实现代码:

void LCD_DisplayTemp(float temp) { char buffer[16]; LCD_WriteCmd(0x01); // 清屏 HAL_Delay(2); LCD_SetCursor(0, 0); // 第一行 LCD_PrintStr("Temperature:"); LCD_SetCursor(0, 1); // 第二行 sprintf(buffer, "%.2f C", temp); LCD_PrintStr(buffer); } // 设置光标位置 void LCD_SetCursor(uint8_t x, uint8_t y) { uint8_t addr; if(y == 0) { addr = 0x80 + x; } else { addr = 0xC0 + x; } LCD_WriteCmd(addr); } // 打印字符串 void LCD_PrintStr(char *str) { while(*str) { LCD_WriteData(*str++); } }

5. 系统集成与优化

5.1 主程序架构

一个典型的主循环实现:

int main(void) { HAL_Init(); SystemClock_Config(); LCD_Init(); DS18B20_Init(); float temperature; while(1) { temperature = DS18B20_GetTemp(); LCD_DisplayTemp(temperature); HAL_Delay(1000); // 每秒更新一次 } }

5.2 常见问题排查

DS18B20无响应

  • 检查上拉电阻是否连接(4.7kΩ)
  • 确认时序延迟准确,特别是复位脉冲
  • 验证电源电压稳定(3.0-5.5V)

LCD显示异常

  • 检查对比度调节电位器设置
  • 确认4位/8位模式设置正确
  • 验证使能信号(E)的脉冲宽度足够

温度读数不稳定

  • 确保DS18B20远离热源和散热器
  • 考虑添加软件滤波(如移动平均)
  • 检查电源噪声,必要时增加滤波电容

5.3 进阶优化方向

  1. 低功耗设计

    • 使用STM32的睡眠模式
    • 降低采样频率
    • 关闭不必要的外设时钟
  2. 多传感器支持

    • 实现DS18B20的ROM搜索算法
    • 支持多个传感器在同一总线上
  3. 温度报警功能

    • 设置上下限阈值
    • 触发蜂鸣器或LED报警
  4. 数据记录

    • 添加EEPROM存储历史数据
    • 实现简单的温度变化曲线显示

在实际项目中,我发现DS18B20的响应时间会随环境温度变化,在极端温度下转换时间可能超过标准值,因此建议将等待转换完成的时间设置为800ms以确保可靠性。

http://www.jsqmd.com/news/855320/

相关文章:

  • 在i.MX6UL嵌入式Linux上部署ncnn:轻量级AI推理实践与优化
  • 2026年5月热门的上海代办德国子公司注册口碑推荐厂家推荐榜,全流程代办、法务税务合规、签证支持型厂家选择指南 - 海棠依旧大
  • 深度测评2026年日本工程塑料厂家最佳代理服务排行榜,解锁高精尖材料新选择
  • 手把手教你用PlatformIO给ESP32添加蓝牙HID功能(从库缺失到成功编译的全过程)
  • 合同系统业务功能
  • 从原始数据到实际物理量:手把手教你处理MPU6050的加速度和角速度数据
  • 用STM32F407的ADC+DMA,做个PS2摇杆的“读心术”,实时读取X/Y轴电压变化
  • 别再被C++的拷贝构造坑了!用移动语义和std::move让你的程序快起来(附实战避坑指南)
  • 深入ARM Cortex-M内核:除了性能参数,这些设计细节才是嵌入式稳定的关键
  • 2026年5月广西工程咨询公司哪家强?商业计划书编制机构推荐榜,可行性研究报告、项目建议书、资金申请报告厂家选择指南 - 海棠依旧大
  • TG电报登录收不到短信验证码?关于 SMS fee 我是这样搞定的!
  • 2026年绵阳育儿嫂机构评测:5家服务商核心实力对比 - 优质品牌商家
  • 别再死记硬背了!华为交换机ACL配置实战:从精确匹配IP到限制网页访问,保姆级避坑指南
  • 【c++面向对象编程】第35篇:构造函数与异常:如何避免资源泄露?
  • 【范式转换】从 XPath 定位到意图驱动:AI 视觉是如何重塑 UI 操作的?
  • 2026年Q2华东区域专业热喷涂服务商排行盘点:湖州,杭州,嘉兴,抗氧化热喷涂/电弧喷涂/电弧热喷涂/等离子热喷涂/选择指南 - 优质品牌商家
  • 2026年一人公司创业指南:OPC模式如何稳健起步
  • 别再手动补面了!ANSA Topo_CONS命令实战:从Paste到Project,5分钟搞定复杂几何修复
  • 2026年知名的铜陵全屋定制家居/铜陵橱柜全屋定制靠谱公司推荐 - 品牌宣传支持者
  • 2026年浙江门窗实测评测:乐道优品、乐道优品门窗、佛山120系列门窗、佛山别墅系统门窗、佛山封阳台门窗、佛山抗台风门窗选择指南 - 优质品牌商家
  • 实战解析:如何利用WRFDA的da_update_bc.exe正确更新WRF边界条件(以4DVAR为例)
  • 2026年5月评价高的海口工地砂石源头厂家哪家好厂家推荐榜,河沙、机制砂、碎石、加气砖、水泥砖厂家选择指南 - 海棠依旧大
  • 五月的风温柔细碎
  • 2026杭州狗主粮选购技术指南:杭州通用型狗粮、通用型狗粮、杭州100%鲜肉狗粮、杭州专用狗粮、杭州中型犬狗粮选择指南 - 优质品牌商家
  • Alist启动报错?别慌!手把手教你用Windows命令排查并解决5244端口占用问题
  • 不止于建模:用AnyLogic仿真优化地铁早高峰限流方案,我的参数调试心得
  • 研一开学前,我用这份保姆级时间表3个月搞定CV基础(附Python/PyTorch/OpenCV避坑指南)
  • GEFFEN格芬智能云控分布式电源管理系统GF-SPMS8
  • 通过Python SDK将Taotoken大模型能力嵌入自动化数据处理脚本
  • Windows进程注入技术全解析:从DLL注入到反射加载与APC机制