Files
poweroff-protection/README.md
2026-05-14 17:53:52 +08:00

217 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Poweroff Protection
基于 STM32 + Linux 的安全断电保护系统。当主电源断开时STM32 通知 Linux 主机执行关机,等待关机完成后再切断继电器电源,避免数据损坏。
## 系统架构
```
主 12V 电源 ──┬──> [Main12V_In] STM32F103C8 [Relay_out] ──> 继电器 ──> Linux 主机电源
│ │
│ UART / USB CDC
│ │
└──────────────── Linux 主机 (poweroff_linux)
```
## 通信协议
| 方向 | 指令 | 说明 |
|------|------|------|
| Linux → STM32 | `start` | 启动监控循环 |
| STM32 → Linux | `Alive` | 心跳请求 |
| Linux → STM32 | `blive` | 心跳应答 |
| STM32 → Linux | `SHUTDOWN` | 通知主机立即关机 |
| Linux → STM32 | `ok` | 关机完成确认 |
## 工作流程
1. Linux 端连接串口,发送 `start`
2. STM32 进入监控循环,持续发送 `Alive` 并等待 `blive` 应答5 秒超时)
3. 当检测到主 12V 电源断开(连续 10 次读取为高或心跳超时STM32 发送 `SHUTDOWN`
4. 等待 Linux 回复 `ok`(最长 60 秒)
5. 收到 `ok` 后延迟 10 秒,拉高继电器引脚切断主机电源
## 目录结构
```
poweroff/
├── poweroff_stm32/ # STM32 固件 (Keil MDK 工程)
│ ├── Core/ # 用户代码 (main.c, gpio.c, usart.c)
│ ├── Drivers/ # HAL 驱动 + CMSIS
│ ├── Middlewares/ # USB CDC 中间件
│ ├── USB_DEVICE/ # USB 设备配置
│ └── MDK-ARM/ # Keil 工程文件
└── poweroff_linux/ # Linux 端 Go 程序
├── shutdown.go # 主程序
├── shutdown # 预编译二进制
├── config.json # 配置文件
├── install.sh # 安装脚本
├── uninstall.sh # 卸载脚本
├── change_port.sh # 更换串口脚本
├── send_signal.sh # 关机信号钩子
├── ttyshutdown.service
├── go.mod
└── go.sum
```
## 硬件引脚 (STM32F103C8)
| 引脚 | 端口 | 功能 |
|------|------|------|
| SHUT | PB4 | 关机指示(低电平有效) |
| RUN | PB5 | 运行指示灯 |
| Relay_out | PB6 | 继电器控制(高电平切断电源) |
| Main12V_In | PB7 | 主 12V 电源检测 |
| USART1_TX | PA9 | 串口发送 |
| USART1_RX | PA10 | 串口接收 |
| USB | PA11/PA12 | USB CDC 通信 |
## 安装
### 硬件准备
- STM32F103C8 最小系统板Blue Pill
- 继电器模块(低电平触发),用于控制 Linux 主机电源
- USB 转 TTL 串口模块(如 CH340/CP2102或 USB 数据线
- J-Link / ST-Link 下载器
- 12V 主电源
### 接线
```
STM32 外设
───── ────
PB6 (Relay_out) ──> 继电器信号端
PB7 (Main12V_In)──> 主 12V 电源检测(需分压至 3.3V
PB5 (RUN) ──> LED 指示灯
PB4 (SHUT) ──> 关机状态指示灯
PA9 (USART1_TX) ──> 串口模块 RX
PA10 (USART1_RX) ──> 串口模块 TX
USB (PA11/PA12) ──> Linux 主机 USB 口(使用 USB CDC 时)
```
> **注意**12V 电源检测引脚需通过电阻分压将电压降至 3.3V 以下,避免损坏 STM32。推荐使用 10k + 3.3k 电阻分压。
### STM32 固件编译与烧录
#### 前置要求
- [Keil MDK-ARM](https://www.keil.com/download/product/) v5.38+
- STM32F1xx DFP (Device Family Pack),通过 Pack Installer 安装
- J-Link 驱动或 ST-Link 驱动
#### 编译
1. 打开 Keil选择 `Project → Open Project`
2. 加载 `poweroff_stm32/MDK-ARM/poweroff_protection.uvprojx`
3. 点击 `Build (F7)` 编译
#### 烧录
1. 连接 J-Link / ST-Link 到 STM32 的 SWDIO、SWCLK、GND
2. 在 Keil 中选择 `Flash → Download (F8)` 烧录
3. 也可以使用 `poweroff_stm32/MDK-ARM/poweroff_protection/poweroff_protection.hex` 配合 ST-Link Utility 独立烧录
### Linux 端安装
#### 前置要求
- Linux 主机(需要 `shutdown` 命令权限)
- 串口设备已接入USB 转串口模块或 USB CDC
- `shutdown` 预编译二进制文件已放在 `poweroff_linux/` 目录下
#### 编译(可选)
如需从源码编译:
```bash
cd poweroff_linux
go build -o shutdown .
```
#### install.sh — 一键安装
安装脚本会交互式引导你完成配置,自动部署为 systemd 服务。
```bash
cd poweroff_linux
sudo bash install.sh
```
运行后脚本会:
1. **扫描串口** — 自动检测已接入的串口设备ttyUSB / ttyACM / ttyS以列表形式供你选择也可手动输入路径
2. **配置参数** — 按提示设置波特率(默认 115200和关机指令默认 `SHUTDOWN`),回车保持默认
3. **确认安装** — 显示完整配置,确认后执行安装
4. **自动部署** — 将二进制和配置文件安装到 `/opt/ttyshutdown/`,生成 systemd 服务,安装关机钩子,启用并启动服务
安装完成后:
```bash
# 查看服务状态
systemctl status ttyshutdown
# 查看实时日志
journalctl -u ttyshutdown -f
```
#### uninstall.sh — 卸载
```bash
cd poweroff_linux
sudo bash uninstall.sh
```
卸载脚本会依次执行:
1. 停止并禁用 `ttyshutdown` 服务
2. 删除 systemd 服务文件 `/etc/systemd/system/ttyshutdown.service`
3. 删除关机钩子 `/usr/lib/systemd/system-shutdown/send_signal.sh`
4. 删除安装目录 `/opt/ttyshutdown/`
执行前会要求确认(输入 `y`)。
#### change_port.sh — 更换串口
当串口设备变化(如更换 USB 口、换用不同串口模块)时使用:
```bash
cd poweroff_linux
sudo bash change_port.sh
```
运行后脚本会:
1. **显示当前配置** — 读取 `/opt/ttyshutdown/config.json`,展示当前串口、波特率、关机指令
2. **扫描新串口** — 列出可用设备,当前使用的串口会标记 `<-- 当前`
3. **修改参数** — 选择新串口后,可一并修改波特率和关机指令(回车保持原值)
4. **确认更改** — 显示变更对比(如 `串口设备: /dev/ttyUSB0 -> /dev/ttyACM0`
5. **生效** — 自动更新 `config.json` 和关机钩子 `send_signal.sh`,并重启服务
#### 常用命令
```bash
# 查看服务状态
systemctl status ttyshutdown
# 查看实时日志
journalctl -u ttyshutdown -f
# 手动重启服务
sudo systemctl restart ttyshutdown
# 手动停止服务
sudo systemctl stop ttyshutdown
```
## 通信说明
STM32 支持 UART 和 USB CDC 双通道,收到 `start` 指令时自动切换到对应通道:
- 通过串口模块发送 `start` → 使用 UART 通道
- 通过 USB CDC 发送 `start` → 使用 USB CDC 通道
程序会自动重连串口,每秒发送 `blive` 心跳,收到 `SHUTDOWN` 指令后执行 `shutdown -h now`