基于 STM32F103C8T6 的 MS5837-30BA 深度传感器驱动,I2C 采集 → 二阶补偿解算 → 二进制数据帧通过 USART1 输出。
| STM32F103C8T6 | MS5837 | 说明 |
|---|---|---|
| PB6 | SCL | I2C1 时钟 (400kHz) |
| PB7 | SDA | I2C1 数据 |
| PA9 | — | USART1 TX (115200bps, 上位机 RX) |
| PA10 | — | USART1 RX (保留) |
| 3.3V | VDD | 电源 |
| GND | GND | 地 |
每帧 11 字节,小端序,约 28Hz 发送频率(OSR=8192)。
┌──────┬──────┬──────────┬───────────────┬───────────┬──────────┐
│ 0 │ 1 │ 2 3 │ 4 5 6 7 │ 8 9 │ 10 │
│ 0xA5 │ 0x5A │ depth_cm │ pressure_01 │ temp_01c │ checksum │
│ │ │ uint16 │ uint32 │ int16 │ uint8 │
└──────┴──────┴──────────┴───────────────┴───────────┴──────────┘
| 字节 | 字段 | 类型 | 单位 | 说明 |
|---|---|---|---|---|
| 0 | SOF0 | uint8 | — | 帧头固定 0xA5 |
| 1 | SOF1 | uint8 | — | 帧头固定 0x5A |
| 2-3 | depth_cm | uint16 LE | cm | 水深,范围 0-65535 cm |
| 4-7 | pressure_01mbar | uint32 LE | 0.1 mbar | 绝对压力 |
| 8-9 | temp_01c | int16 LE | 0.1 °C | 温度,有符号 |
| 10 | checksum | uint8 | — | 字节 2-9 的 XOR |
import struct
def parse_frame(data: bytes):
"""返回 (depth_m, pressure_mbar, temp_c) 或 None"""
if len(data) != 11 or data[0] != 0xA5 or data[1] != 0x5A:
return None
cksum = 0
for b in data[2:10]:
cksum ^= b
if cksum != data[10]:
return None
d, p, t = struct.unpack('<H I h', data[2:10])
return (d / 100.0, p / 10.0, t / 10.0)# 水深 0.00m, 气压 1013.2mbar, 温度 25.3°C
A5 5A 00 00 F0 27 00 00 FD 00 2D
# 水深 1.23m, 压力 1134.5mbar, 温度 24.8°C
A5 5A 7B 00 D2 2C 00 00 F8 00 AE
- 复位 MS5837 (0x1E),等待 10ms
- 读取 PROM 校准系数 C1-C6
- 大气压校准 — 自动采集 20 帧压力数据取均值作为
P_atm基准(约 0.7 秒) - 进入主循环 — 每周期约 36ms:
D2 温度转换 (0x5A) → 等待 18ms → 读取 D2 ADC
→ D1 压力转换 (0x4A) → 等待 18ms → 读取 D1 ADC
→ 二阶温度补偿 (int64 运算)
→ 深度 = (P_abs - P_atm) / 98.1 (淡水, ρ=1000 kg/m³)
→ 打包二进制帧 → USART1 发送
打开 MDK-ARM/interpreter.uvprojx,编译下载。
用 Embedded IDE 插件打开项目,目标选 interpreter,工具链 AC6 (ARM Compiler 6)。
为了适配 32KB Flash 的芯片(国产克隆片常见),I2C 和 UART 均使用裸寄存器操作替代 HAL 库:
| 移除的 HAL 模块 | 替代方案 |
|---|---|
stm32f1xx_hal_i2c.c (~25KB) |
直接操作 I2C1 寄存器 |
stm32f1xx_hal_uart.c (~9KB) |
USART1 SR/DR 轮询 |
stm32f1xx_hal_dma.c (~3KB) |
不使用 DMA |
编译选项:-Os + MicroLIB。最终二进制约 15-20 KB。
以下宏定义在 Core/Inc/ms5837.h 中可按需修改:
| 宏 | 默认值 | 说明 |
|---|---|---|
WATER_DENSITY_FRESH |
1000.0f |
液体密度 kg/m³,海水改为 1025.0f |
DEPTH_CALIB_SAMPLES |
20 |
上电大气压校准采样帧数 |
MS5837_CONVERT_DELAY |
18 |
ADC 转换等待时间 ms (OSR=8192) |
interpreter/
├── Core/
│ ├── Inc/
│ │ ├── main.h
│ │ ├── ms5837.h ← 传感器驱动头文件
│ │ ├── i2c.h
│ │ └── usart.h
│ └── Src/
│ ├── main.c ← 主循环 + 帧打包发送
│ ├── ms5837.c ← I2C 裸寄存器 + PROM + ADC + 二阶补偿
│ ├── i2c.c ← I2C1 裸寄存器初始化
│ ├── usart.c ← USART1 裸寄存器初始化
│ ├── stm32f1xx_it.c ← 中断服务
│ └── ...
├── Drivers/ ← HAL 库 (仅保留核心模块)
├── MDK-ARM/ ← Keil 工程
├── .eide/ ← EIDE (VSCode) 工程
└── README.md