first commit

This commit is contained in:
zhaohengze
2026-05-14 17:53:52 +08:00
commit e1ffcf2e7d
156 changed files with 109026 additions and 0 deletions

216
README.md Normal file
View File

@ -0,0 +1,216 @@
# 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`