描述
<h1>EMME_A3.0 — USB 3.0 Type-A 直通式电流表</h1>
<p><img src="https://image.lceda.cn/oshwhub/pullImage/1e86ba56c778460bb66bf9143dbc7674.jpg" alt="正面亮屏.jpg"></p>
<p><span style="color:#C0C0C0;">> <strong>项目代号</strong>:EMME_A3.0_Rev1.0
> <strong>产品类型</strong>:USB 3.0 Type-A 直通式电流表
> <strong>硬件平台</strong>:STM32F103CBT6
> <strong>设计起始</strong>:2026 年 6 月</span></p>
<hr>
<h2>1. 项目功能介绍</h2>
<h3>1.1 项目背景与目标</h3>
<p>本项目 <strong>EMME_A3.0</strong> 是一款 <strong>USB 3.0 Type-A 直通式电流表</strong>,设计目标为:</p>
<ul>
<li><strong>串联测量</strong>:Type-A 公头接入主机(PC/充电器),Type-A 母座接入负载设备,对通过线缆的 <strong>电压、电流、功率</strong> 进行实时测量,USB 差分信号(DP/DN/SSTX/SSRX)全部直通,不干扰正常数据传输。</li>
<li><strong>高精度</strong>:采用 TI INA226 高精度电流传感器 + 10mΩ 采样电阻,配合 16 位 ΔΣ ADC,实现 高精度测量。</li>
<li><strong>本地显示</strong>:内置 1.47 英寸 ST7789 彩屏(172×320, RGB666),以科技风格深色 UI 实时显示测量数据。</li>
<li><strong>电量累计</strong>:支持充电状态的自动检测与 mAh/mWh 累计,方便评估电池实际容量。</li>
<li><strong>温度监测</strong>:板载 TMP112 温度传感器,实时监测模块工作温度。</li>
<li><strong>上位机通信</strong>:通过 USB Type-C 接口(支持正反插两种连接方式)与 PC 通信,配合 Web 上位机实现参数读写、多点校准、数据记录导出等功能。</li>
<li><strong>配置持久化</strong>:校准系数、配置信息、刷新率等参数存入 AT24C02C EEPROM,掉电不丢失。</li>
</ul>
<h3>1.2 解决的问题</h3>
<table>
<tr>
<th>问题场景</th>
<th>EMME_A3.0 的解决方案</th>
</tr>
<tr>
<td>低成本</td>
<td>基于 STM32F103 + INA226 方案,BOM 成本低</td>
</tr>
<tr>
<td>USB 3.0 高速信号传输</td>
<td>完整直通 USB 3.0 差分线(SSTX/SSRX),阻抗匹配 90Ω</td>
</tr>
<tr>
<td>通过Web上位机记录历史数据</td>
<td>配套 Web 上位机,支持 CSV 数据导出</td>
</tr>
<tr>
<td>校准过程复杂,需要专业设备</td>
<td>上位机支持多点校准(最小二乘法线性拟合),使用普通万用表即可完成</td>
</tr>
<tr>
<td>线缆发热但无法感知</td>
<td>板载温度传感器</td>
</tr>
</table>
<h3>1.3 核心功能一览</h3>
<ul>
<li>✅ <strong>实时电压测量</strong>(0~36V,1.25mV 分辨率)</li>
<li>✅ <strong>实时电流测量</strong>(±8.192A,约 0.25mA 分辨率)</li>
<li>✅ <strong>实时功率计算</strong>(电压 × 电流)</li>
<li>✅ <strong>充电累计</strong>(mAh / mWh)</li>
<li>✅ <strong>运行时间统计</strong>(总运行时长 / 充电时长)</li>
<li>✅ <strong>温度监测</strong>(宽温度范围采样)</li>
<li>✅ <strong>USB 线缆插入检测</strong>(DP/DN 电压采样)</li>
<li>✅ <strong>多点校准</strong>(电压增益/偏移、电流增益/偏移,EEPROM 存储)</li>
<li>✅ <strong>UI 可配置</strong>(刷新率、屏幕方向)</li>
<li>✅ <strong>双通道上位机通信</strong>(CH340X 串口 + STM32 USB CDC)</li>
</ul>
<hr>
<h2>2. 项目属性</h2>
<ul>
<li><em>本项目为首次公开</em>:项目此前未在任何公开平台(如 GitHub、Gitee、立创开源平台、电子发烧友等)发布源码或设计文档。</li>
<li><em>项目为完全原创</em>:硬件原理图、PCB 设计、固件代码、上位机软件、UI 设计均由作者独立完成,未复制、引用或改编任何现有开源项目的核心代码或设计。</li>
<li><em>项目未在其他比赛中获奖</em>:项目未参加过任何电子设计竞赛、创客大赛、创新创业比赛等赛事,亦未获得任何奖项。</li>
<li><em>项目未在学校参加过答辩</em>:项目不属于课程设计、毕业设计、科研项目,未在学校或相关机构进行过答辩或评审。</li>
</ul>
<hr>
<h2>3. 开源协议</h2>
<p>本项目采用 <strong><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank">CC BY-NC-SA 4.0</a></strong> 协议开源:</p>
<table>
<tr>
<th>条款</th>
<th>含义</th>
</tr>
<tr>
<td><strong>BY</strong>(署名)</td>
<td>使用时需注明原作者(ElinM)及项目来源</td>
</tr>
<tr>
<td><strong>NC</strong>(非商业性使用)</td>
<td>不得用于任何商业目的,包括但不限于产品销售、商业演示、付费课程等</td>
</tr>
<tr>
<td><strong>SA</strong>(相同方式共享)</td>
<td>基于本项目的衍生作品必须以相同协议(CC BY-NC-SA 4.0)发布</td>
</tr>
</table>
<hr>
<h2>4. 硬件部分</h2>
<h3>4.1 硬件架构概述</h3>
<p>EMME_A3.0 采用 <strong>串联式</strong> 电压电流采样架构:USB Type-A 公头接入信号源(如 PC 或充电器),USB Type-A 母座接入负载设备。VBUS 线路中串联 10mΩ 采样电阻,由 INA226 传感器检测电压降来计算电流,同时测量负载端电压。USB 数据差分线(USB 2.0 DP/DN 和 USB 3.0 SSTX/SSRX)全部直通并通过 90Ω 阻抗匹配。</p>
<pre><code>┌─────────────┐ 10mΩ 采样电阻 ┌─────────────┐
│ USB Type-A │ ─────────────────── │ USB Type-A │
│ 公头 │ ← VBUS 电流路径 → │ 母座 │
│ (主机/电源) │ DP/DN/SSTX/SSRX │ (负载设备) │
└─────────────┘ 全部直通 └─────────────┘
│ │
│ VBUS │ ADC
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ LMR16006Y │ │ INA226 (TI) │
│ 5V → 3.3V │ │ 16-bit ΔΣ ADC │
└──────┬───────┘ └────────┬─────────┘
│ 3.3V │ I²C1
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ STM32F103CBT6 (主控) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐│
│ │ SPI1 │ │ I²C1 │ │ USART3 │ │ USB (CDC FS) ││
│ │ → TFT屏 │ │ ← INA226 │ │ ← CH340X │ │ ← USB Type-C ││
│ │ │ │ ← EEPROM │ │ ← 上位机 │ │ (备用通道) ││
│ │ │ │ ← TMP1xx │ │ │ │ ││
│ │ ADC1 │ └──────────┘ └──────────┘ └──────────────────┘│
│ │ → USB │ │
│ │ 检测 │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────────┘</code></pre>
<h3>4.2 核心模块</h3>
<h4>电源模块</h4>
<p><strong>LMR16006Y</strong>(TI):同步降压转换器,开关频率 2.1MHz,输入范围 4~60V,从 USB VBUS(5V)降压至 3.3V,为全板数字电路供电。采用 4.7μH 功率电感和紧凑的 SOT-23-6 封装。</p>
<h4>电流测量模块</h4>
<p><strong>INA226</strong>(TI):16 位 ΔΣ ADC 数字电流/电压/功率传感器,最高 36V 共模电压,I²C 接口。通过开尔文连接(Kelvin Connection)从 10mΩ 采样电阻(2512 封装,1% 精度)的两端直接引出差分信号,确保高精度测量。</p>
<p><strong>TMP112</strong>:板载温度传感器,12-bit 分辨率(0.0625°C),通过 I²C1 与 INA226 共享总线。</p>
<h4>显示模块</h4>
<ul>
<li><strong>1.47 英寸 TFT LCD</strong>,驱动 IC 为 <strong>ST7789V3</strong>,分辨率 172×320,支持 <strong>RGB666</strong>(18-bit/像素)色彩格式。</li>
<li>通过 <strong>SPI1</strong>(PA5 SCK / PA7 MOSI)以单线模式通信,SPI 时钟 18MHz。</li>
<li>采用 <strong>DMA 双缓冲 Ping-Pong 机制</strong>传输像素数据,CPU 填充缓冲区的同时 DMA 传输上一帧数据,大幅提升屏幕刷新效率。</li>
<li>支持 <strong>FXAA 抗锯齿</strong>颜色混合,实现平滑的圆角矩形和高质量文字渲染。</li>
<li>屏幕驱动采用自定义的 <strong>深色科技风 UI 设计系统</strong>,参考 Composio 设计理念。</li>
</ul>
<h4>通信模块(双通道)</h4>
<ul>
<li><strong>主通道 — CH340X 串口</strong>:USB Type-C 正插时,CH340X(WCH)将 USB 信号转换为 UART 信号,连接 STM32 USART3(PB10 RX / PB11 TX),呈现为标准 COM 端口,兼容几乎所有串口调试工具和 Web Serial API。</li>
<li><strong>备用通道 — STM32 USB CDC</strong>:USB Type-C 反插时,STM32 内置 USB 全速接口(PA11 DM / PA12 DP)直接以 CDC(虚拟串口)模式通信,无需额外芯片。</li>
</ul>
<h4>存储模块</h4>
<p><strong>AT24C02C</strong>(256 字节 EEPROM,SOT23-5),I²C 接口,挂载在 I²C1 总线上(与 INA226/TMP1xx 共用),用于存储校准系数、屏幕亮度、刷新率、显示页面等用户配置。</p>
<h4>USB 线缆检测</h4>
<p>通过 STM32 <strong>ADC1</strong>(PB0 → ADC1_IN8 检测 D-,PB1 → ADC1_IN9 检测 D+)采样 USB 差分线上的电压,任一引脚电压 > 0.8V 即判定 USB 线缆已插入。</p>
<h3>4.3 关键引脚分配</h3>
<table>
<tr>
<th>功能</th>
<th>引脚</th>
<th>说明</th>
</tr>
<tr>
<td>LCD DC</td>
<td>PA3</td>
<td>数据/命令选择</td>
</tr>
<tr>
<td>LCD CS</td>
<td>PA4</td>
<td>片选</td>
</tr>
<tr>
<td>LCD RES</td>
<td>PA6</td>
<td>复位</td>
</tr>
<tr>
<td>LCD BLK</td>
<td>PA1</td>
<td>背光控制</td>
</tr>
<tr>
<td>SPI1_SCK</td>
<td>PA5</td>
<td>SPI 时钟</td>
</tr>
<tr>
<td>SPI1_MOSI</td>
<td>PA7</td>
<td>SPI 数据输出</td>
</tr>
<tr>
<td>I2C1_SCL</td>
<td>PB6</td>
<td>I²C 时钟</td>
</tr>
<tr>
<td>I2C1_SDA</td>
<td>PB7</td>
<td>I²C 数据</td>
</tr>
<tr>
<td>USART3_RX</td>
<td>PB10</td>
<td>串口接收 (CH340X)</td>
</tr>
<tr>
<td>USART3_TX</td>
<td>PB11</td>
<td>串口发送 (CH340X)</td>
</tr>
<tr>
<td>USB_DP</td>
<td>PA12</td>
<td>USB 差分对+</td>
</tr>
<tr>
<td>USB_DM</td>
<td>PA11</td>
<td>USB 差分对-</td>
</tr>
<tr>
<td>ADC1_IN8</td>
<td>PB0</td>
<td>USB D- 检测</td>
</tr>
<tr>
<td>ADC1_IN9</td>
<td>PB1</td>
<td>USB D+ 检测</td>
</tr>
<tr>
<td>OSC_IN/OUT</td>
<td>PD0/PD1</td>
<td>8MHz 晶振</td>
</tr>
<tr>
<td>SWD_IO/CLK</td>
<td>PA13/PA14</td>
<td>调试接口</td>
</tr>
</table>
<hr>
<h2>5. 软件部分</h2>
<h3>5.1 整体架构</h3>
<p>软件采用 <strong>五层分层架构</strong>,从下至上依次为硬件层 → HAL 层 → 驱动层 → 任务层 → 应用层,各层职责清晰、松耦合,便于维护和扩展。</p>
<pre><code>┌─────────────────────────────────────────────────────────────────┐
│ APP 层(应用逻辑) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ 测量任务层 │ │ 显示任务层 │ │ 通信任务层 │ │
│ │ - INA226读取 │ │ - UI 页面渲染 │ │ - 串口命令解析/执行 │ │
│ │ - 温度读取 │ │ - DMA 屏幕刷新│ │ - USB CDC 数据处理 │ │
│ │ - USB检测 │ │ - FXAA抗锯齿 │ │ - 校准协议处理 │ │
│ │ - 电量累计 │ │ - 数值格式化 │ │ - 响应生成 │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ TASK 层(任务调度) │
│ main_task_init() / main_task() │
│ 时间片轮询:10ms 采集 / 50ms 显示 / 10ms 通信 │
├─────────────────────────────────────────────────────────────────┤
│ DRV 层(硬件驱动) │
│ INA226 | NextLCD (ST7789) | AT24C02C | TMP1xx | Protocol │
├─────────────────────────────────────────────────────────────────┤
│ HAL 层(硬件抽象层) │
│ STM32CubeF1 HAL + LL: I2C1, SPI1, USART3, USB, ADC1, DMA1 │
├─────────────────────────────────────────────────────────────────┤
│ 硬件层 │
│ STM32F103CBT6 (72MHz, 128KB Flash, 20KB SRAM) │
└─────────────────────────────────────────────────────────────────┘</code></pre>
<h3>5.2 主循环流程图(时间片轮询)</h3>
<p>本项目不使用 RTOS,而是采用基于 SysTick(<code>HAL_GetTick()</code>)的 <strong>时间片轮询调度</strong> 机制,在 <code>while(1)</code> 主循环中按不同时间间隔执行各任务:</p>
<pre><code>┌────────────────────────────────────────────────────┐
│ while(1) 主循环 │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 每 10ms: 传感器采集任务 │ │
│ │ ├── INA226: 读取电压 → 应用校准系数 │ │
│ │ ├── INA226: 读取电流 → 应用校准系数 │ │
│ │ ├── INA226: 读取功率 │ │
│ │ ├── 电量累计 (mAh/mWh, 充电时累加) │ │
│ │ ├── TMP1xx: 读取温度 (每500ms一次) │ │
│ │ └── ADC1: 采样DP/DN电压 → USB插入检测 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 每 50ms: 显示刷新任务 │ │
│ │ └── UI_RefreshValues() 局部刷新显示数值 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 每 10ms: 串口通信处理任务 │ │
│ │ └── Protocol_Process() 处理 USART3 + USB CDC │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 每 1s: 精确秒计时 │ │
│ │ ├── g_run_seconds++ (总运行时间) │ │
│ │ └── g_charge_seconds++ (充电时间) │ │
│ └──────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘</code></pre>
<h3>5.3 功能模块说明</h3>
<h4>5.3.1 INA226 电流传感器驱动</h4>
<ul>
<li><strong>初始化</strong>:发送复位命令 → 计算并写入 CALIBRATION 寄存器 → 配置 CONFIG 寄存器(PGA 量程、ADC 转换时间、平均次数、运行模式)</li>
<li><strong>关键参数</strong>:10mΩ 采样电阻,最大预期电流 8.192A,PGA=00 (±40mV),256 次平均</li>
<li><strong>计算公式</strong>:
<ul>
<li>电流分辨率 = iMaxExcepted / 32768 = 8.192 / 32768 ≈ 0.25mA/bit</li>
<li>功率分辨率 = 25 × 电流分辨率</li>
<li>Calibration = 0.00512 / (Current_LSB × R_shunt)</li>
</ul></li>
<li><strong>错误处理</strong>:每次读取均检查 HAL 返回值,失败时保持上次有效值并递增 I²C 故障计数器</li>
</ul>
<h4>5.3.2 显示驱动</h4>
<ul>
<li><strong>色彩格式</strong>:RGB666(18-bit/像素),提供 262144 色,远高于普通 RGB565 的 65536 色</li>
<li><strong>DMA 双缓冲 Ping-Pong</strong>:4KB 缓冲区分为两个半区,CPU 与 DMA 交替填充/传输,有效隐藏缓冲区填充开销</li>
<li><strong>FXAA 抗锯齿</strong>:通过 Alpha 混合前景色与背景色,实现平滑的圆角矩形边框和高质量文字渲染</li>
<li><strong>字体</strong>:等距更纱黑体 SCsarasa-mono-sc-regular / GrayBits4</li>
<li><strong>UI 设计</strong>:深色科技风,电压/电流/功率三参数框分别使用柔亮橙/绿/蓝色调,右侧面板显示累计电量和运行时间</li>
</ul>
<h4>5.3.3 EEPROM 配置管理(AT24C02C)</h4>
<p><strong>存储布局</strong>(256 字节):</p>
<table>
<tr>
<th style="text-align:center;">地址</th>
<th>字段</th>
<th style="text-align:center;">类型</th>
<th>说明</th>
</tr>
<tr>
<td style="text-align:center;">0x00~0x01</td>
<td>魔数</td>
<td style="text-align:center;">uint16</td>
<td>0x454D("EM"),数据有效性校验</td>
</tr>
<tr>
<td style="text-align:center;">0x02</td>
<td>版本号</td>
<td style="text-align:center;">uint8</td>
<td>当前为 v3</td>
</tr>
<tr>
<td style="text-align:center;">0x03~0x04</td>
<td>电压增益</td>
<td style="text-align:center;">int16</td>
<td>Q15 定点数</td>
</tr>
<tr>
<td style="text-align:center;">0x05~0x06</td>
<td>电压偏移</td>
<td style="text-align:center;">int16</td>
<td>mV 单位</td>
</tr>
<tr>
<td style="text-align:center;">0x07~0x08</td>
<td>电流增益</td>
<td style="text-align:center;">int16</td>
<td>Q15 定点数</td>
</tr>
<tr>
<td style="text-align:center;">0x09~0x0A</td>
<td>电流偏移</td>
<td style="text-align:center;">int16</td>
<td>mA 单位</td>
</tr>
<tr>
<td style="text-align:center;">0x0B</td>
<td>屏幕亮度</td>
<td style="text-align:center;">uint8</td>
<td>0~100</td>
</tr>
<tr>
<td style="text-align:center;">0x0C</td>
<td>刷新率档位</td>
<td style="text-align:center;">uint8</td>
<td>0~5</td>
</tr>
<tr>
<td style="text-align:center;">0x0D</td>
<td>显示页面</td>
<td style="text-align:center;">uint8</td>
<td>当前选中页</td>
</tr>
<tr>
<td style="text-align:center;">0x0E</td>
<td>过流阈值</td>
<td style="text-align:center;">uint8</td>
<td>A×10</td>
</tr>
<tr>
<td style="text-align:center;">0x0F</td>
<td>过压阈值</td>
<td style="text-align:center;">uint8</td>
<td>V×10</td>
</tr>
<tr>
<td style="text-align:center;">0x10</td>
<td>屏幕方向</td>
<td style="text-align:center;">uint8</td>
<td>0=正向, 1=反向</td>
</tr>
<tr>
<td style="text-align:center;">0x11~0x14</td>
<td>INA226 参数</td>
<td style="text-align:center;">uint8×4</td>
<td>BADC / SADC / AVG / PGA</td>
</tr>
<tr>
<td style="text-align:center;">0x15~0x16</td>
<td>充电参数</td>
<td style="text-align:center;">uint8×2</td>
<td>充电电压阈值 / 迟滞时间</td>
</tr>
</table>
<p>上电时读取魔数进行校验,无效则写入默认配置。</p>
<h4>5.3.4 通信协议</h4>
<p><img src="https://image.lceda.cn/oshwhub/pullImage/497c8d9186db4dd58a47e03de218a142.png" alt="屏幕截图 2026-08-16 222253.png"></p>
<p>协议帧格式:<code>$COMMAND PARAM *CS\r\n</code></p>
<table>
<tr>
<th>字段</th>
<th>说明</th>
</tr>
<tr>
<td><code>$</code></td>
<td>帧起始符(PROTOCOL_HEADER)</td>
</tr>
<tr>
<td><code>COMMAND PARAM</code></td>
<td>命令码 + 参数字符串</td>
</tr>
<tr>
<td><code>*</code></td>
<td>校验和分隔符(PROTOCOL_DELIMITER)</td>
</tr>
<tr>
<td><code>CS</code></td>
<td>2 字节十六进制 XOR 校验和</td>
</tr>
<tr>
<td><code>\r\n</code></td>
<td>帧结束符</td>
</tr>
</table>
<p><strong>支持命令</strong>:</p>
<table>
<tr>
<th>命令</th>
<th>参数</th>
<th>说明</th>
</tr>
<tr>
<td><code>READ VER</code></td>
<td>—</td>
<td>读取固件版本号</td>
</tr>
<tr>
<td><code>READ V</code></td>
<td>—</td>
<td>读取当前电压</td>
</tr>
<tr>
<td><code>READ A</code></td>
<td>—</td>
<td>读取当前电流</td>
</tr>
<tr>
<td><code>READ W</code></td>
<td>—</td>
<td>读取当前功率</td>
</tr>
<tr>
<td><code>READ CONF</code></td>
<td>—</td>
<td>读取配置参数</td>
</tr>
<tr>
<td><code>READ CALI</code></td>
<td>—</td>
<td>读取校准系数</td>
</tr>
<tr>
<td><code>READ TMP</code></td>
<td>—</td>
<td>读取温度</td>
</tr>
<tr>
<td><code>WRIT BRIGHT</code></td>
<td><code>0~100</code></td>
<td>设置屏幕亮度</td>
</tr>
<tr>
<td><code>WRIT REFRESH</code></td>
<td><code>0~5</code></td>
<td>设置刷新率档位</td>
</tr>
<tr>
<td><code>CALI VG</code></td>
<td><code>浮点数</code></td>
<td>设置电压增益</td>
</tr>
<tr>
<td><code>CALI VO</code></td>
<td><code>浮点数</code></td>
<td>设置电压偏移</td>
</tr>
<tr>
<td><code>CALI CG</code></td>
<td><code>浮点数</code></td>
<td>设置电流增益</td>
</tr>
<tr>
<td><code>CALI CO</code></td>
<td><code>浮点数</code></td>
<td>设置电流偏移</td>
</tr>
<tr>
<td><code>CALI SAVE</code></td>
<td>—</td>
<td>保存校准系数到 EEPROM</td>
</tr>
</table>
<p><strong>双重通信通道</strong>:USART3(CH340X)和 USB CDC 均使用相同的协议栈,通过独立的状态机并行处理。</p>
<h4>5.3.5 多点校准机制</h4>
<ol>
<li>连接 Web 上位机,读取当前 INA226 原始值</li>
<li>将设备接入已知基准源(精密万用表),在上位机中填入参考值</li>
<li>至少采集 2 个校准点,上位机使用 <strong>最小二乘法</strong> 计算线性拟合参数(增益和偏移)</li>
<li>将校准系数通过 <code>$CALI</code> 命令下发至 MCU</li>
<li><code>$CALI SAVE</code> 将系数写入 EEPROM,下次上电自动生效</li>
</ol>
<h3>5.4 源码结构</h3>
<pre><code>EMME_A3.0_Rev1.0/
├── Core/
│ ├── Inc/ ← CubeMX 生成的头文件(main.h, i2c.h, spi.h 等)
│ └── Src/
│ ├── main.c ← 主入口:外设初始化 → main_task_init() → 主循环
│ ├── main_task.c ← 任务核心:初始化编排 + 时间片轮询
│ ├── main_task.h ← 任务头文件:全局变量声明 + 函数接口
│ └── stm32f1xx_it.c ← 中断服务函数
├── Software/
│ ├── protocol.c ← 通信协议实现:状态机解析 + 命令执行
│ └── protocol.h ← 协议定义:帧格式 + 命令枚举
├── Hardware/
│ ├── ina226/
│ │ ├── ina226.c ← INA226 驱动:寄存器读写 + 初始化/重配置 + 数据读取
│ │ └── ina226.h ← 寄存器地址 + 配置宏定义
│ ├── at24c02/
│ │ ├── at24c02.c ← EEPROM 驱动:字节/页读写 + 配置管理
│ │ └── at24c02.h ← 存储布局地址 + 配置结构体
│ ├── tmp1xx/
│ │ ├── tmp1xx.c ← 温度传感器驱动
│ │ └── tmp1xx.h
│ └── nextlcd/
│ ├── nextlcd_init.c/.h ← ST7789 屏幕初始化(RGB666 模式配置)
│ ├── nextlcd.c/.h ← 绘图 API(填充、DMA 传输、FXAA、文字显示)
│ └── lcdfont.c/.h ← 字体字库
├── USB_DEVICE/
│ ├── App/
│ │ ├── usb_device.c/.h ← USB 设备初始化
│ │ ├── usbd_desc.c/.h ← USB 设备描述符
│ │ └── usbd_cdc_if.c/.h ← CDC 接口实现(USB 串口收发)
│ └── Target/
│ ├── usbd_conf.c/.h ← USB 底层配置
├── web-serial-tool/ ← Web 上位机(纯前端)
│ ├── index.html ← 页面结构
│ ├── script.js ← 核心逻辑(通信、校准、数据记录)
│ ├── style.css ← 样式(深色科技风)
│ └── README.md ← 使用说明
├── drivers/ ← HAL 库、CMSIS(STM32CubeMX 自动生成)
├── datasheet/ ← 器件数据手册
├── cmake/ ← CMake 构建配置
├── build/ ← 构建输出目录
├── EMME_A3.0_Rev1.0.ioc ← STM32CubeMX 工程配置
├── EMME_A3.0_Rev1.0_HardwareDesign.md ← 硬件设计文档
├── EMME_A3.0_Rev1.0_SoftwareDesign.md ← 软件设计文档
└── design_zh.md ← UI 设计系统规范</code></pre>
<h3>5.5 开发环境与依赖工具</h3>
<table>
<tr>
<th>工具</th>
<th>版本</th>
<th>用途</th>
</tr>
<tr>
<td><strong>STM32CubeMX</strong></td>
<td>6.12.0</td>
<td>外设配置、时钟树生成、初始化代码生成</td>
</tr>
<tr>
<td><strong>STM32CubeF1</strong></td>
<td>V1.8.7</td>
<td>HAL/LL 固件库</td>
</tr>
<tr>
<td><strong>VS Code</strong></td>
<td>—</td>
<td>代码编辑与开发</td>
</tr>
<tr>
<td><strong>CMake</strong></td>
<td>—</td>
<td>构建系统</td>
</tr>
<tr>
<td><strong>ARM GCC</strong></td>
<td>arm-none-eabi-gcc</td>
<td>编译工具链</td>
</tr>
<tr>
<td><strong>Chrome/Edge</strong></td>
<td>89+</td>
<td>运行 Web 上位机(需支持 Web Serial API)</td>
</tr>
</table>
<h3>5.6 程序烧录方法</h3>
<p><strong>SWD 烧录</strong>:</p>
<ul>
<li>使用 ST-Link V2/V3 调试器通过USB Type-C SBU1、SBU2 连接到 MCU 的 SWD 接口(PA13 SWDIO / PA14 SWCLK / 3.3V / GND)</li>
<li>使用STM32CubeProgrammer 烧录 <code>.bin</code>/<code>.hex</code> 文件</li>
</ul>
<h3>5.7 关键算法说明</h3>
<h4>时间片轮询调度</h4>
<pre><code class="language-c">#define TASK_IS_DUE(last, interval) (HAL_GetTick() - (last) >= (interval))</code></pre>
<p>该机制避免了 RTOS 的上下文切换开销,在 STM32F103(20KB SRAM)的资源限制下实现了多任务并发执行。</p>
<h4>INA226 校准计算</h4>
<pre><code>Current_LSB = iMaxExcepted / 32768 = 8.192 / 32768 ≈ 0.25mA/bit
Calibration = 0.00512 / (Current_LSB × R_shunt) = 0.00512 / (0.00025 × 0.01) = 2048
I_measured = Raw_Current_Register × Current_LSB
V_measured = Raw_BusVoltage_Register × 1.25mV</code></pre>
<h4>多点校准(最小二乘法线性拟合)</h4>
<p>设原始测量值为 x,基准参考值为 y,收集 n 组数据点 (xᵢ, yᵢ),则:</p>
<ul>
<li><strong>增益(斜率)</strong>:G = (n·Σ(xᵢyᵢ) − Σxᵢ·Σyᵢ) / (n·Σ(xᵢ²) − (Σxᵢ)²)</li>
<li><strong>偏移(截距)</strong>:O = (Σyᵢ − G·Σxᵢ) / n</li>
</ul>
<p>校准后实际值 = x × G + O,此系数存入 EEPROM,上电自动生效。</p>
<hr>
<h2>6. BOM 清单</h2>
<p>根据硬件设计文档中的网表纲要,核心物料清单如下:</p>
<table>
<tr>
<th style="text-align:center;">序号</th>
<th>器件类别</th>
<th>型号/规格</th>
<th>封装</th>
<th style="text-align:center;">数量</th>
<th>说明</th>
</tr>
<tr>
<td style="text-align:center;">1</td>
<td>主控 MCU</td>
<td><strong>STM32F103CBT6</strong></td>
<td>LQFP48</td>
<td style="text-align:center;">1</td>
<td>Cortex-M3, 128KB Flash, 20KB SRAM</td>
</tr>
<tr>
<td style="text-align:center;">2</td>
<td>电流传感器</td>
<td><strong>INA226AIDGSR</strong> (TI)</td>
<td>MSOP-10</td>
<td style="text-align:center;">1</td>
<td>16-bit ΔΣ ADC, I²C, 36V 共模</td>
</tr>
<tr>
<td style="text-align:center;">3</td>
<td>温度传感器</td>
<td><strong>TMP112/TMP175</strong></td>
<td>SOIC-8</td>
<td style="text-align:center;">1</td>
<td>12-bit I²C 数字温度传感器</td>
</tr>
<tr>
<td style="text-align:center;">4</td>
<td>降压转换器</td>
<td><strong>LMR16006YDDCR</strong> (TI)</td>
<td>SOT-23-6</td>
<td style="text-align:center;">1</td>
<td>2.1MHz, 4~60V 输入, 3.3V/600mA 输出</td>
</tr>
<tr>
<td style="text-align:center;">5</td>
<td>USB 转串口</td>
<td><strong>CH340X</strong> (WCH)</td>
<td>MSOP-10</td>
<td style="text-align:center;">1</td>
<td>USB↔UART 桥接芯片</td>
</tr>
<tr>
<td style="text-align:center;">6</td>
<td>EEPROM</td>
<td><strong>AT24C02C-SSHM-T</strong></td>
<td>SOT23-5</td>
<td style="text-align:center;">1</td>
<td>2Kbit (256B) I²C EEPROM</td>
</tr>
<tr>
<td style="text-align:center;">7</td>
<td>采样电阻</td>
<td><strong>10mΩ, 1%, 2W</strong></td>
<td>2512</td>
<td style="text-align:center;">1</td>
<td>金属合金, 低温漂</td>
</tr>
<tr>
<td style="text-align:center;">8</td>
<td>晶振</td>
<td><strong>8MHz, ±20ppm</strong></td>
<td>5032/3225</td>
<td style="text-align:center;">1</td>
<td>外部高速晶振</td>
</tr>
<tr>
<td style="text-align:center;">9</td>
<td>TFT 屏幕</td>
<td><strong>1.47" ST7789V3, 172×320</strong></td>
<td>FPC 8P</td>
<td style="text-align:center;">1</td>
<td>RGB666 彩色 TFT LCD</td>
</tr>
<tr>
<td style="text-align:center;">10</td>
<td>USB Type-A 公头</td>
<td>3.0 夹板公头</td>
<td>夹板</td>
<td style="text-align:center;">1</td>
<td>0.8mm 板厚</td>
</tr>
<tr>
<td style="text-align:center;">11</td>
<td>USB Type-A 母座</td>
<td>3.0 夹板母座</td>
<td>夹板</td>
<td style="text-align:center;">1</td>
<td>0.8mm 板厚</td>
</tr>
<tr>
<td style="text-align:center;">12</td>
<td>USB Type-C 插座</td>
<td>16P 夹板</td>
<td>沉板0.8mm</td>
<td style="text-align:center;">1</td>
<td>上位机通信</td>
</tr>
<tr>
<td style="text-align:center;">13</td>
<td>电感</td>
<td><strong>4.7μH, 饱和 ≥800mA</strong></td>
<td>1210/2520</td>
<td style="text-align:center;">1</td>
<td>降压转换器功率电感</td>
</tr>
<tr>
<td style="text-align:center;">14</td>
<td>三极管</td>
<td><strong>S8050</strong></td>
<td>SOT-23</td>
<td style="text-align:center;">1</td>
<td>屏幕背光控制</td>
</tr>
<tr>
<td style="text-align:center;">15</td>
<td>电容/电阻</td>
<td>0402/0603 封装</td>
<td>0402/0603</td>
<td style="text-align:center;">若干</td>
<td>去耦、滤波、上拉等</td>
</tr>
</table>
<p>> <strong>注</strong>:以上为 BOM 纲要,完整物料清单以原理图和设计文件为准。</p>
<hr>
<h2>7. 更新日志</h2>
<ul>
<li>20260814 项目首次发布,编写文档</li>
<li>20260816 bin固件、Web上位机发布,文档有误处修正</li>
</ul>
<hr>
<h2>8. 写在最后</h2>
<p>感谢你能读到这里,如果你觉得本项目不错那么欢迎你动手制作;如果你觉得文档中有不清楚的地方欢迎在评论区指出;如果你觉得想要实现某些功能或者发现存在Bug也欢迎在评论区提出,我会尽快修复<span style="color:#C0C0C0;">(也许XD</span></p>
评论(10)