Files
stc32g128k/Docs/docs/implementation_plan.html

323 lines
27 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>手环端开发计划书 (V1.2) - 纯法语 UI & 幻彩 RGB LED</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #0B0F19;
color: #E2E8F0;
margin: 0;
padding: 40px 20px;
line-height: 1.6;
}
.container {
max-width: 1000px;
margin: 0 auto;
}
h1 {
font-size: 2.2rem;
color: #00E5FF;
text-align: center;
margin-bottom: 10px;
letter-spacing: 1px;
}
.subtitle {
text-align: center;
color: #94A3B8;
font-size: 1.1rem;
margin-bottom: 40px;
}
.section-title {
font-size: 1.5rem;
color: #FFB74D;
border-bottom: 2px solid #334155;
padding-bottom: 8px;
margin-top: 50px;
margin-bottom: 24px;
}
.card {
background-color: #1E293B;
border-radius: 12px;
padding: 24px;
margin-bottom: 30px;
border: 1px solid #334155;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.95rem;
margin-top: 10px;
}
th, td {
text-align: left;
padding: 10px 14px;
border-bottom: 1px solid #334155;
}
th {
color: #94A3B8;
font-weight: bold;
background-color: #0F172A;
}
td {
color: #E2E8F0;
}
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.8rem;
font-weight: bold;
}
.badge-red { background-color: #7f1d1d; color: #fca5a5; }
.badge-green { background-color: #064e3b; color: #6ee7b7; }
.badge-blue { background-color: #1e3a8a; color: #93c5fd; }
.badge-orange { background-color: #7c2d12; color: #ffedd5; }
.alert {
border-left: 4px solid #00E5FF;
background-color: #0F172A;
padding: 16px 20px;
border-radius: 4px;
margin-bottom: 25px;
}
.alert-title {
font-weight: bold;
color: #FFFFFF;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.alert-title span {
color: #00E5FF;
}
.task-list {
list-style: none;
padding: 0;
}
.task-item {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 14px;
font-size: 1rem;
}
.task-checkbox {
margin-top: 5px;
width: 16px;
height: 16px;
cursor: pointer;
}
.task-text {
flex: 1;
}
.task-text b {
color: #FFFFFF;
}
</style>
</head>
<body>
<div class="container">
<h1>手环端开发计划书 (V1.2)</h1>
<div class="subtitle">STC32G12K128 核心手环系统开发及 UI 渲染方案说明(法语及单线 RGB 版)</div>
<!-- System Architecture Block -->
<div class="card" style="background-color: #0D111A; border: 1px solid #1E293B;">
<div style="font-size: 1.2rem; font-weight: bold; color: #FFB74D; text-align: center; margin-bottom: 15px;">手环系统硬件接口与数据流拓扑图</div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 360" width="100%" height="auto">
<defs>
<filter id="boxShadow" x="-5%" y="-5%" width="110%" height="110%">
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#000000" flood-opacity="0.4"/>
</filter>
<marker id="arrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#64748B"/>
</marker>
</defs>
<rect width="800" height="360" rx="8" fill="#0D111A"/>
<!-- Left: Inputs -->
<g transform="translate(40, 40)" filter="url(#boxShadow)">
<rect width="180" height="280" rx="8" fill="#1E293B" stroke="#334155" stroke-width="1"/>
<text x="90" y="24" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">INPUTS / 输入与按键</text>
<!-- Keys Sub-box -->
<rect x="15" y="45" width="150" height="90" rx="6" fill="#0F172A" stroke="#00E5FF" stroke-width="1"/>
<text x="90" y="65" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">按键输入 (▲ / ▼ / SOS)</text>
<text x="25" y="90" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P0.1: KEY_UP (▲)</text>
<text x="25" y="108" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P0.3: KEY_DOWN (▼)</text>
<text x="25" y="124" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P0.2: KEY_SOS</text>
<!-- RF Rx Sub-box -->
<rect x="15" y="160" width="150" height="90" rx="6" fill="#0F172A" stroke="#FF9800" stroke-width="1"/>
<text x="90" y="180" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">LR690L 433MHz 接收</text>
<text x="25" y="205" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P2.1: RF_RX_DATA</text>
<text x="25" y="222" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P2.2: SHUT (低使能)</text>
<text x="25" y="239" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P3.7: RF_RX 电源开关</text>
</g>
<!-- Middle: Processing (MCU Core) -->
<g transform="translate(310, 40)" filter="url(#boxShadow)">
<rect width="180" height="280" rx="8" fill="#1E293B" stroke="#00E5FF" stroke-width="2"/>
<text x="90" y="24" fill="#00E5FF" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">MCU / 核心业务逻辑</text>
<!-- State Machine -->
<rect x="15" y="45" width="150" height="90" rx="6" fill="#0F172A" stroke="#334155" stroke-width="1"/>
<text x="90" y="65" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">主程序状态机</text>
<text x="25" y="90" fill="#00E5FF" font-family="system-ui, sans-serif" font-size="9">● STATE_NORMAL (时钟/待机)</text>
<text x="25" y="105" fill="#FFB74D" font-family="system-ui, sans-serif" font-size="9">● STATE_PAIR (对码配对)</text>
<text x="25" y="120" fill="#FF1744" font-family="system-ui, sans-serif" font-size="9">● STATE_ALARM (告警响应)</text>
<!-- Timers & Storage -->
<rect x="15" y="160" width="150" height="90" rx="6" fill="#0F172A" stroke="#334155" stroke-width="1"/>
<text x="90" y="180" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">时间片调度与存储</text>
<text x="25" y="205" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">Timer 1: 1ms 消抖与时钟</text>
<text x="25" y="222" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">模拟 LED / 马达时序控制</text>
<text x="25" y="239" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">IAP Flash: 保存对码数据</text>
</g>
<!-- Right: Outputs -->
<g transform="translate(580, 40)" filter="url(#boxShadow)">
<rect width="180" height="280" rx="8" fill="#1E293B" stroke="#334155" stroke-width="1"/>
<text x="90" y="24" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">OUTPUTS / 交互与显示</text>
<!-- Screen -->
<rect x="15" y="45" width="150" height="90" rx="6" fill="#0F172A" stroke="#00E5FF" stroke-width="1"/>
<text x="90" y="65" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">OLED 局部刷新渲染</text>
<text x="25" y="90" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">RM69310 (CS/RST/DCX/SPI)</text>
<text x="25" y="108" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">ASCII 8x16 & 16x32</text>
<text x="25" y="124" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">全法语 UI 显示界面</text>
<!-- Indicators -->
<rect x="15" y="160" width="150" height="90" rx="6" fill="#0F172A" stroke="#FF1744" stroke-width="1"/>
<text x="90" y="180" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" font-weight="bold" text-anchor="middle">物理反馈警报输出</text>
<text x="25" y="205" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">单线 RGB (P0.0: WS2812 DIN)</text>
<text x="25" y="222" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">800Kbps 归零码串行驱动</text>
<text x="25" y="239" fill="#94A3B8" font-family="system-ui, sans-serif" font-size="10">P2.5: 振动马达驱动</text>
</g>
<!-- Connectors -->
<path d="M 220 100 L 310 100" stroke="#64748B" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 220 210 L 310 210" stroke="#64748B" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 490 100 L 580 100" stroke="#64748B" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 490 210 L 580 210" stroke="#64748B" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
</svg>
</div>
<!-- Code Flowchart -->
<div class="section-title">📊 代码逻辑运行流程图</div>
<div class="card" style="background-color: #0D111A; border: 1px solid #1E293B;">
<div style="font-size: 1.2rem; font-weight: bold; color: #00E5FF; text-align: center; margin-bottom: 15px;">主循环与 Timer1 中断、RF 双模解码流程</div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 680" width="100%" height="auto"> <defs> <filter id="shadow" x="-5%" y="-5%" width="110%" height="110%"> <feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#000000" flood-opacity="0.4"/> </filter> <marker id="arrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse"> <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#64748B"/> </marker> </defs> <rect width="800" height="680" rx="8" fill="#0D111A"/> <!-- Main Loop Column (Left) --> <g transform="translate(40, 20)"> <text x="120" y="25" fill="#00E5FF" font-family="system-ui, sans-serif" font-size="14" font-weight="bold" text-anchor="middle">主程序运行流程 main()</text> <!-- Step 1: Init --> <rect x="20" y="45" width="200" height="40" rx="4" fill="#1E293B" stroke="#00E5FF" stroke-width="1.5" filter="url(#shadow)"/> <text x="120" y="69" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" text-anchor="middle">系统初始化 (时钟/GPIO/Timer1/OLED)</text> <!-- Step 2: Read EEPROM --> <rect x="20" y="115" width="200" height="40" rx="4" fill="#1E293B" stroke="#334155" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="139" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" text-anchor="middle">读取 IAP/EEPROM 传感器对码表</text> <!-- Step 3: Idle state --> <rect x="20" y="185" width="200" height="40" rx="4" fill="#1E293B" stroke="#334155" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="209" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" text-anchor="middle">进入 STATE_NORMAL 并开启接收管</text> <!-- Loop Start Junction --> <circle cx="120" cy="260" r="8" fill="#FFB74D"/> <text x="120" y="280" fill="#FFB74D" font-family="system-ui, sans-serif" font-size="9" text-anchor="middle">while(1) 轮询</text> <!-- Check 1: Button --> <polygon points="120,300 220,325 120,350 20,325" fill="#1E293B" stroke="#334155" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="329" fill="#E2E8F0" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle">有按键事件触发?</text> <!-- Handle Button --> <rect x="20" y="380" width="200" height="40" rx="4" fill="#0F172A" stroke="#00E5FF" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="404" fill="#E2E8F0" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle">处理按键 (状态切换/对码/SOS)</text> <!-- Check 2: RF Data --> <polygon points="120,450 220,475 120,500 20,475" fill="#1E293B" stroke="#334155" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="479" fill="#E2E8F0" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle">有RF信号输入?</text> <!-- Handle RF --> <rect x="20" y="530" width="200" height="40" rx="4" fill="#0F172A" stroke="#FF9800" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="554" fill="#E2E8F0" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle">解析协议 (报警触发 / 主机广播)</text> <!-- Update UI --> <rect x="20" y="600" width="200" height="40" rx="4" fill="#1E293B" stroke="#00E5FF" stroke-width="1" filter="url(#shadow)"/> <text x="120" y="624" fill="#FFFFFF" font-family="system-ui, sans-serif" font-size="11" text-anchor="middle">执行 OLED 局部增量刷新渲染</text> <!-- Connections Left Column --> <path d="M 120 85 L 120 115" stroke="#64748B" stroke-width="1.5" fill="none" marker-end="url(#arrow)"/> <path d="M 120 155 L 120 185" stroke="#64748B" stroke-width="1.5" fill="none" marker-end="url(#arrow)"/> <path d="M 120 225 L 120 252" stroke="#64748B" stroke-width="1.5" fill="none" marker-end="url(#arrow)"/> <path d="M 120 268 L 120 300" stroke="#64748B" stroke-width="1.5" fill="none" marker-end="url(#arrow)"/> <path d="M 120 350 L 120 380" stroke="#64748B" stroke-width="1.5" fill="none" marker-end="url(#arro
</div>
<!-- Section 1 -->
<div class="section-title">一、 硬件引脚映射与电气特性</div>
<div class="card">
<table>
<thead>
<tr>
<th>硬件功能分类</th>
<th>端口别名</th>
<th>STC32G 引脚</th>
<th>驱动电气逻辑说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>🌈 单线制幻彩 RGB LED</b></td>
<td><code>WS2812_DI</code></td>
<td>P0.0</td>
<td>单线级联数据输入800Kbps 归零码协议,推挽输出,上电初始化输出 <b>0</b></td>
</tr>
<tr>
<td><b>📳 振动驱动马达</b></td>
<td><code>MOTOR</code></td>
<td>P2.5</td>
<td>直流控制,输出 <b>1</b> 开启马达,输出 0 停止。</td>
</tr>
<tr>
<td><b>▲ 方向按键 (上)</b></td>
<td><code>KEY_UP</code></td>
<td>P0.1</td>
<td>按下为 <b>0</b>,带内部上拉输入。</td>
</tr>
<tr>
<td><b>▼ 方向按键 (下)</b></td>
<td><code>KEY_DOWN</code></td>
<td>P0.3</td>
<td>按下为 <b>0</b>,带内部上拉输入。</td>
</tr>
<tr>
<td><b>🆘 紧急/对码按键</b></td>
<td><code>KEY_SOS</code></td>
<td>P0.2</td>
<td>按下为 <b>0</b>,带内部上拉输入。</td>
</tr>
</tbody>
</table>
</div>
<!-- Section 2 -->
<div class="section-title">二、 核心设计决策 (Design Decisions)</div>
<div class="alert" style="border-left-color: #00E5FF;">
<div class="alert-title"><span>💡</span> 决策 1纯法语语言包French-Only UI</div>
<div class="alert-body">
由于系统调整为仅需要法语界面,因此移除了原本复杂的中文字库寻址及字库空间分配方案。全界面文案已替换为符合法语习惯的词汇。为了适应 120 像素宽的 OLED 屏幕边界,各短语的长度被严格控制在 15 个字符以内以防止屏幕溢出,并微调了各个关键界面的显示坐标(如 "DESARME" 页面图标与文字)实现完美居中。
</div>
</div>
<div class="alert" style="border-left-color: #FF9800;">
<div class="alert-title"><span>📡</span> 决策 2单线制幻彩 RGB LED 驱动集成 (XL-2020RGBC-2812B)</div>
<div class="alert-body">
原三路 GPIO 独立驱动的共阳极三色 LED 更换为内置 IC 的单线级联式幻彩 LED 珠。由于 STC32G 工作在 24MHz 1T 模式下(每周期 41.67ns),通过在软件上实现精准 NOP 指令延时的 bit-bang 驱动,通过 <code>P0.0</code> 引脚向 LED 发送符合 800Kbps 时序T0H/T0L/T1H/T1L 归零码)的 24 位 GRB 数据流。为了不影响原有各状态下复杂的灯效和马达波形逻辑,我们仅将 <code>LED_R/G/B</code> 重新定义为内存中的虚拟 bit 变量。在 1ms 中断服务程序末尾,当检测到这些虚拟变量的数值发生改变时,自动触发一次单线数据发送,从而实现了上层逻辑的 100% 兼容。
</div>
</div>
<!-- Section 3 -->
<div class="section-title">三、 UI 渲染引擎细节与坐标规划</div>
<div class="card">
<h3 style="color: #FFFFFF; margin-top: 0;">1. 直流流式送数驱动 (`LCD_DrawMonoBitmap`)</h3>
<p>基于硬件 SPI 接口,在写图前设置矩形窗口 <code>(x, y) -> (x+w-1, y+h-1)</code>,然后从 Flash 字模中逐 Bit 扫描:如果是 1 则流式送入前景色0 则送入背景色。此方案**零显存开销**,完全避开了单片机 RAM 资源瓶颈,且写屏速度极快。</p>
<h3 style="color: #FFFFFF;">2. 圆形视口安全区域划分</h3>
<p>由于屏幕物理切边,有效显示区收拢在 <b>X 坐标 [10, 110]Y 坐标 [30, 210]</b> 的安全圆形范围内:</p>
<ul>
<li><b>时钟待机页</b>:右上角电池图标设在 $X=92, Y=27$,电量百分比文字 "85%" 设在 $X=62, Y=24$,留出 6 像素的安全间距。日期及星期 "JEU 07-02" 居中设在 $Y=155$。下方布防 "ARME" 位于 $X=52, Y=202$;撤防 "DESARME" 位于 $X=42, Y=202$。</li>
<li><b>配对菜单页</b>:标题为 "MENU APPAI." 位于 $Y=30$。菜单项(如 "DETEC. PORTE")采用 3 行滚动布局,选中行($Y=110$)画出 $100 \times 28$ 边框,高亮显示。</li>
<li><b>告警与呼救页</b>:本机 SOS 发射界面显示 "SOS EMIS" $Y=125$)以及 "BRACELET ACTIF"$Y=155$)。接收普通传感器报警时,名称(如 "PORTE ENTREE")显示于 $Y=120$,下行显示 "ZONE X | ALARME" 位于 $Y=155$。</li>
</ul>
</div>
<!-- Section 4 -->
<div class="section-title">四、 验证任务清单 (Task Checklist)</div>
<div class="card" style="background-color: #0F172A;">
<ul class="task-list">
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="task1" checked disabled>
<label for="task1" class="task-text"><b>1. 自动编译测试</b>:使用 Keil C251 重新编译,确保生成 <code>wristband.hex</code> 成功且 0 错误2 Warnings 可忽略。</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="task2" checked disabled>
<label for="task2" class="task-text"><b>2. 待机时钟与菜单测试</b>:确认待机时间显示正确,▲+▼ 同时按 3 秒进入配对列表,▲/▼ 能在 5 个法语传感器条目间顺滑切换。</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="task3" checked disabled>
<label for="task3" class="task-text"><b>3. LED与马达报警测试</b>:验证配对成功、失败时绿灯常亮 2 秒与红灯闪烁等物理动作;验证各防区报警时虚拟 LED 转换出的 RGB 驱动电平正确输出。</label>
</li>
<li class="task-item">
<input type="checkbox" class="task-checkbox" id="task4" checked disabled>
<label for="task4" class="task-text"><b>4. Git 远程提交同步</b>:将所有修改和新增的 .gitignore 提交到本地 Git并成功 Push 到服务器的 `zouhaitao/stc32g128k.git` 仓库中。</label>
</li>
</ul>
</div>
</div>
</body>
</html>