Poweroff Protection
基于 STM32 + Linux 的安全断电保护系统。当主电源断开时,STM32 通知 Linux 主机执行关机,等待关机完成后再切断继电器电源,避免数据损坏。
目前5块板子,仅id:0的板子可以正常使用USB与RS232口进行通信,其余板子由于硬件问题目前仅支持USB进行通信。
系统架构
主 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 |
关机完成确认 |
工作流程
- Linux 端连接串口,发送
start - STM32 进入监控循环,持续发送
Alive并等待blive应答(5 秒超时) - 当检测到主 12V 电源断开(连续 10 次读取为高)或心跳超时,STM32 发送
SHUTDOWN - 等待 Linux 回复
ok(最长 60 秒) - 收到
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 v5.38+
- STM32F1xx DFP (Device Family Pack),通过 Pack Installer 安装
- J-Link 驱动或 ST-Link 驱动
编译
- 打开 Keil,选择
Project → Open Project - 加载
poweroff_stm32/MDK-ARM/poweroff_protection.uvprojx - 点击
Build (F7)编译
烧录
- 连接 J-Link / ST-Link 到 STM32 的 SWDIO、SWCLK、GND
- 在 Keil 中选择
Flash → Download (F8)烧录 - 也可以使用
poweroff_stm32/MDK-ARM/poweroff_protection/poweroff_protection.hex配合 ST-Link Utility 独立烧录
Linux 端安装
前置要求
- Linux 主机(需要
shutdown命令权限) - 串口设备已接入(USB 转串口模块或 USB CDC)
shutdown预编译二进制文件已放在poweroff_linux/目录下
编译(可选)
如需从源码编译:
cd poweroff_linux
go build -o shutdown .
install.sh — 一键安装
安装脚本会交互式引导你完成配置,自动部署为 systemd 服务。
cd poweroff_linux
sudo bash install.sh
运行后脚本会:
- 扫描串口 — 自动检测已接入的串口设备(ttyUSB / ttyACM / ttyS),以列表形式供你选择,也可手动输入路径
- 配置参数 — 按提示设置波特率(默认 115200)和关机指令(默认
SHUTDOWN),回车保持默认 - 确认安装 — 显示完整配置,确认后执行安装
- 自动部署 — 将二进制和配置文件安装到
/opt/ttyshutdown/,生成 systemd 服务,安装关机钩子,启用并启动服务
安装完成后:
# 查看服务状态
systemctl status ttyshutdown
# 查看实时日志
journalctl -u ttyshutdown -f
uninstall.sh — 卸载
cd poweroff_linux
sudo bash uninstall.sh
卸载脚本会依次执行:
- 停止并禁用
ttyshutdown服务 - 删除 systemd 服务文件
/etc/systemd/system/ttyshutdown.service - 删除关机钩子
/usr/lib/systemd/system-shutdown/send_signal.sh - 删除安装目录
/opt/ttyshutdown/
执行前会要求确认(输入 y)。
change_port.sh — 更换串口
当串口设备变化(如更换 USB 口、换用不同串口模块)时使用:
cd poweroff_linux
sudo bash change_port.sh
运行后脚本会:
- 显示当前配置 — 读取
/opt/ttyshutdown/config.json,展示当前串口、波特率、关机指令 - 扫描新串口 — 列出可用设备,当前使用的串口会标记
<-- 当前 - 修改参数 — 选择新串口后,可一并修改波特率和关机指令(回车保持原值)
- 确认更改 — 显示变更对比(如
串口设备: /dev/ttyUSB0 -> /dev/ttyACM0) - 生效 — 自动更新
config.json和关机钩子send_signal.sh,并重启服务
常用命令
# 查看服务状态
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。
Description
Languages
C
99.3%
Shell
0.3%
Assembly
0.3%