stm32/sensor/lm75a-i2c-temp.md

温度传感器(LM75A,I2C 数字温度传感器)

知识库 · STM32

温度传感器(LM75A,I2C 数字温度传感器)

2026-08-19 实测验证:Demo00 工程(洋桃1号开发板)温度实时显示 + 历史曲线 + 数码管显示温度,均正常

#一、元信息

字段
芯片/平台STM32F103C8T6(HAL + FreeRTOS)
接口类型I2C(软件模拟,与 OLED 共用总线:SCL=PB6,SDA=PB7)
验证状态✅ 已验证(2026-08-19)
验证环境洋桃1号开发板 / STM32CubeIDE 2.2.0 / OpenOCD / 2026-08-19
驱动方式软件 I2C 读寄存器(i2c_sw.c),12 位分辨率 0.0625℃/LSB

#二、接线表

信号MCU 引脚模块引脚备注
I2C_SCLPB6LM75A SCL(SCK)需上拉(模块自带则免)
I2C_SDAPB7LM75A SDA(SDA)需上拉(模块自带则免)
A0/A1/A2接地或 VCCLM75A 地址选择地址位,见下方地址计算
VCC3.3VLM75A VCC2.8~5.5V(3.3V 标准)
GNDGNDLM75A GND必须共地

#三、踩坑清单

  1. 芯片型号确认:LM75A 不是 DHT11! 本板温度传感器是 LM75A(I2C 数字传感器),不是单总线 DHT11。DHT11 是单总线协议(单根数据线),LM75A 是标准 I2C,接线和协议完全不同,勿混用。
  2. 地址计算:LM75A 的 7 位地址 = 0x48 + A2A1A0(默认全接地时 0x48)。本板实测地址为 0x4F(A2/A1/A0 接 1 的高地址配置)。写入时传 7 位地址(左移 1 位即 8 位地址 0x9E)。可用 I2C 地址扫描遍历 0x48~0x4F 用 ACK 确认。
  3. 温度寄存器:温度值存于寄存器 0x00(2 字节,高字节在前),12 位有效位(上 12 位,低 4 位是符号扩展/小数位)。读取后原始值右移 4 位,LSB=0.0625℃。转换公式:温度 = 原始值 >> 4 × 0.0625℃。要保留两位小数:摄氏度×100 = 原始值 >> 4 × 6.25(本工程用 (int32_t)raw * 625 / 100 得 0.01℃ 精度)。
  4. 分辨率设置:寄存器 0x01 的 bit7:5 可设分辨率(00=9bit/0.5℃、01=10bit/0.25℃、10=11bit/0.125℃、11=12bit/0.0625℃)。本工程设 12bit(写入 0x03)获得最高精度。
  5. I2C 总线共用互斥锁:OLED(0x3C) 与 LM75A(0x4F) 共用同一软件 I2C 总线,多任务访问需互斥锁保护,否则温度采样与屏幕刷新争抢总线会造成画面卡顿/读数异常。

#四、驱动代码(Demo00 工程 temp.c 核心逻辑,已通过验证)

#4.1 temp.h

c#ifndef TEMP_H
#define TEMP_H

#include "main.h"

void temp_init(void);
int16_t temp_read_celsius_tenths(void);   /* 返回 0.01℃ 精度,失败返回 0x7FFF */

#endif

#4.2 temp.c

c#include "temp.h"
#include "i2c_sw.h"

#define LM75A_ADDR  0x4F  /* 7-bit 地址,0x9E >> 1(A2/A1/A0 高位配置) */
#define LM75A_REG_TEMP 0x00
#define LM75A_REG_CONF 0x01

void temp_init(void)
{
  /* 设 12 位分辨率(0x03)→ 0.0625℃/LSB,两位小数精度 */
  uint8_t reg = LM75A_REG_CONF;
  uint8_t conf = 0x03;
  i2c_sw_write(LM75A_ADDR, &reg, 1);
  i2c_sw_write(LM75A_ADDR, &conf, 1);
}

int16_t temp_read_celsius_tenths(void)
{
  uint8_t buf[2] = {0, 0};
  if (i2c_sw_read(LM75A_ADDR, LM75A_REG_TEMP, buf, 2) != 0)
  {
    return 0x7FFF;   /* 读取失败标记 */
  }
  int16_t raw = ((int16_t)buf[0] << 8) | buf[1];
  raw >>= 4;  /* 12-bit 数值,右移去低 4 位 */
  int16_t cents = (int16_t)(((int32_t)raw * 625) / 100);
  return cents;   /* 0.01℃ 精度 */
}

#4.3 i2c_sw.c 读函数(软件 I2C 读寄存器)

cuint8_t i2c_sw_read(uint8_t dev_addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
  /* 写寄存器地址 → 重复起始 → 读数据:完整时序见工程 i2c_sw.c */
  /* 伪码:start() → 写(dev_addr<<1) → 等ACK → 写(reg) → 等ACK → start() → 写((dev_addr<<1)|1) → 读len字节 → stop() */
}

#五、调用示例

c/* main() 初始化顺序 */
HAL_Init();
SystemClock_Config();
i2c_sw_init();   /* 软件 I2C 引脚初始化 PB6/PB7 */
temp_init();     /* LM75A 配置为 12 位分辨率 */

/* 读取温度(每秒采样一次) */
int16_t t = temp_read_celsius_tenths();   /* 如 2531 = 25.31℃ */
if (t != 0x7FFF)
{
  char buf[16];
  snprintf(buf, sizeof(buf), "%d.%02d C", t / 100, t % 100);  /* 显示 25.31 C */
}

#六、参考库/链接

  • LM75A 数据手册:搜索 "LM75A datasheet PDF"(NXP/恩智浦 LM75A 数字温度传感器)
  • 洋桃1号官方例程:D:\学习资料\【用户资料】洋桃1号开发板(2)\B5-教学视频示例程序\(温度传感器示例可参考)
  • 软件 I2C 驱动:本工程 Core/Src/app/i2c_sw.c / i2c_sw.h(SCL=PB6/SDA=PB7)