newPtz/drivers/readme.md

538 lines
29 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.

## ADC原理说明
GD32F4系列搭载了高性能的12位逐次逼近型SARADC提供了非常灵活和强大的数据采集功能。其采集方式可以从**操作模式**和**数据转移方式**两个维度来理解。
### 一、按操作模式划分
操作模式决定了ADC如何执行转换序列主要配置在 `ADC_RSQ0`、`ADC_RSQ1`、`ADC_RSQ2`寄存器(规则序列寄存器)和 `ADC_OSQ`寄存器(注入序列寄存器)。
#### 1. 单次转换模式 (Single Conversion Mode)
* **工作原理**ADC只执行一次转换可以是一个通道也可以是多个通道组成的序列转换完成后自动停止并置位转换结束标志位EOC
* **触发方式**
* **软件触发**:通过设置 `ADC_CTL1``SWRCST`位启动。
* **硬件触发**通过外部信号如定时器TRGO、EXTI线启动。
* **特点**最简单功耗最低转换间隙ADC可自动进入低功耗模式但需要不断重新触发才能进行下一次转换。适用于对采样率要求不高的场合。
* **代码逻辑**`启动 -> 等待EOC -> 读取数据 -> (下次需要时再次启动)`
#### 2. 连续转换模式 (Continuous Conversion Mode)
* **工作原理**ADC完成一次转换序列后**立即自动重新启动**下一次转换,永不停止,连续不断地进行转换。
* **触发方式**:通常由**一次软件或硬件触发**来启动这个连续的进程。
* **特点**:一旦启动,无需干预即可获得连续的数据流,实时性高。但**功耗相对较高**因为ADC一直处于工作状态。通常需要与DMA配合使用。
* **代码逻辑**`启动 -> (自动循环转换) -> 不断读取数据`
#### 3. 扫描模式 (Scan Mode)
* **工作原理**:此模式**不是独立的**它需要与单次或连续模式结合使用。当使能扫描模式后ADC会按照预先在规则序列寄存器 `ADC_RSQi`或注入序列寄存器 `ADC_OSQ`中设置好的**通道顺序**,依次对多个通道进行转换。
* **特点**:实现了多通道自动轮流采样。**特别注意**
* 在扫描模式下,每次完成**整个序列**的转换后,才会产生一个**EOC**(转换结束)中断标志。
* 如果需要每个通道转换完都产生中断,需要使能 `EOCIE`并配合DMA使用。
* **常见组合**
* **单次扫描模式**:触发一次,按顺序转换所有通道一次,然后停止。
* **连续扫描模式**:触发一次,按顺序循环不停地转换所有通道。
#### 4. 间断模式 (Discontinuous Mode)
* **工作原理**:此模式用于将一个长的转换序列**分批次(短序列)** 完成。您需要设置短序列的长度 `DISNUM`例如n=3。每次由一个硬件触发信号触发时ADC不会转换整个序列而是只转换序列中的**接下来的n个通道**。再次触发再转换接下来的n个通道直到整个序列完成然后循环。
* **特点**:提供了更精细的触发控制,允许用多个触发信号来控制一个长序列的转换。应用相对小众,常用于由定时器精确控制采样点的复杂场景。
---
### 二、按数据转移方式划分
转换完成后的数据需要被CPU读取根据读取方式的不同也决定了系统的效率。
#### 1. 中断方式 (Interrupt)
* **工作原理**使能ADC中断如EOC中断在转换完成后进入中断服务函数ISR在ISR中读取 `ADC_RDATA`寄存器。
* **适用场景**
* **单通道单次转换**:最简单。
* **扫描模式**如果只关心整个序列转换完成可以在EOC中断中读取所有数据但需要自己记录顺序
* **缺点**频繁中断会消耗大量CPU资源尤其在高速、多通道采样时效率低下。
#### 2. DMA方式 (Direct Memory Access)
* **工作原理**:这是**多通道扫描+连续转换模式的标准且高效的解决方案**。使能ADC的DMA请求并配置好DMA控制器。每次ADC转换完成一个通道的数据后会自动触发DMA由DMA控制器**在不占用CPU的情况下**,将 `ADC_RDATA`寄存器的数据直接搬运到指定的内存数组Buffer中。
* **特点**
* **极高效率**CPU只需在数据数组满或半满时进行处理大大解放了CPU。
* **数据对齐**ADC数据寄存器是32位的但数据只有12位。DMA可以轻松处理数据对齐问题左对齐或右对齐
* **适用场景**:几乎所有需要高速、实时、多通道采样的应用,如音频处理、电机控制、数字电源、多路数据采集卡等。
#### 3. 查询方式 (Polling)
* **工作原理**:在主循环或函数中,不断**查询**ADC状态寄存器中的标志位如EOC一旦发现标志位置位就去读取数据。
* **特点**编程简单但CPU利用率最低因为在等待转换完成时CPU什么也做不了一直在空循环。**不推荐在实际项目中使用**,仅用于简单测试。
---
### 三、特殊模式双ADC模式 (Dual ADC Mode)
GD32F4系列通常有多个ADC单元如ADC0, ADC1, ADC2。它们可以协同工作组成更高级的采样模式用于需要精确同步采样的场景。
* **同步注入模式**一个主ADC被触发后从ADC同时被触发进行注入组转换。
* **同步规则模式**主从ADC同步进行规则组转换。
* **交替触发模式**定时器触发后主从ADC交替采样**同一个通道**,可以实现**2倍于单个ADC**的采样率。
* **交替模式**主从ADC交替采样每次触发交替转换。
* **混合模式**:规则组和注入组可以分别配置为不同的同步模式。
### 总结与对比
| 模式分类 | 模式名称 | 特点 | 适用场景 |
| :----------------- | :------------------ | :-------------------------------------------------- | :--------------------------------------------------- |
| **操作模式** | **单次转换** | 转换一次即停止,低功耗,需反复触发 | 低速、单点采样,电池供电设备 |
| | **连续转换** | 转换一次后自动开始下一次,连续不断 | 高速、实时数据流采集 |
| | **扫描模式** | 按预设顺序自动转换多个通道 | **多通道**数据采集(必须配合单次/连续模式) |
| | **间断模式** | 分多次触发完成一个长序列 | 由外部信号精细控制采样节奏的复杂应用 |
| **数据转移** | **查询方式** | CPU不断查询状态标志效率最低 | 简单测试,不推荐用于实际项目 |
| | **中断方式** | 转换完成产生中断CPU在ISR中读取数据 | 中低速、通道数较少的应用 |
| | **DMA方式** | **自动**将数据搬运到内存,**不占用CPU** | **高速、多通道、实时**采集的**首选方案** |
| **ADC组合** | **双ADC模式** | 多个ADC单元协同工作同步或交替采样 | 需要高采样率或通道间严格同步的高精度应用 |
### 如何选择?
1. **单通道、低速采样**:单次转换 + 中断。
2. **多通道、低速采样**:单次扫描 + DMA或中断但DMA更优
3. **多通道、高速采样****连续扫描 + DMA** (这是最常用、最经典的配置)。
4. **极限采样率(单通道)**使用双ADC的交替模式配合DMA。
5. **需要同步采样两个相关信号**使用双ADC的同步模式。
这是一个非常核心且优秀的问题它触及了ADC模块设计思想的本质。
**规则组和注入组****操作模式****数据转移方式** 是不同维度的概念,但它们之间**存在着紧密的协作和配合关系**。您可以这样理解:
* **规则组 vs 注入组**:定义的是 **“要转换什么”**What即ADC转换任务的**内容**和**队列**。它们就像是两个不同的**任务列表**。
* **操作模式**:定义的是 **“如何执行转换”**How即如何对待上述任务列表是执行一次还是循环执行是软件启动还是硬件启动。它定义了任务的**执行策略**。
* **数据转移方式**:定义的是 **“转换完成后如何处理数据”**What to do with the result即如何获取转换结果。它定义了任务结果的**收集方式**。
它们之间的关系可以用下面的图表来清晰地展示:
```mermaid
flowchart TD
subgraph A[任务内容What]
direction LR
A1[规则组<br>常规任务队列]
A2[注入组<br>高优先级任务队列]
end
subgraph B[执行策略How]
B1[操作模式<br>单次/连续/扫描/间断]
end
subgraph C[结果收集What to do]
direction LR
C1[数据转移方式<br>查询/中断/DMA]
end
D[原始模拟信号] --> A
A -- 任务列表 --> B
B -- 执行转换 --> C
C -- 获取结果 --> E[数字转换结果]
B -.->|执行策略同时<br>应用于两个组| A1
B -.->|执行策略同时<br>应用于两个组| A2
C1 -->|读取规则组<br>需及时处理| A1
C1 -->|读取注入组<br>有专用寄存器| A2
```
下面我们进行详细的解读。
---
### 1. 规则组/注入组 与 操作模式 的关系
操作模式(单次、连续、扫描)**同时适用于规则组和注入组**,但两者的行为有一些关键区别。
| 特性 | 规则组 (Routine Group) | 注入组 (Injected Group) |
| :--------------------- | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **扫描模式** | **必须启用**才能转换多通道序列。 | 注入组**本身就是一个短序列**,其通道数由 `IL`(Injected Length) 决定,**无需**单独的“扫描模式”使能。 |
| **单次 vs 连续** | 决定了规则序列是执行一次还是循环执行。 | 决定了注入序列是执行一次还是循环执行。**注意**:一个注入触发信号通常只执行一次注入序列,除非配置为连续模式。 |
| **触发源** | 可以使用软件触发或硬件触发(如定时器)。 | 同样可以使用软件触发或**独立的**硬件触发源。**关键**:注入组的硬件触发可以**中断**当前正在进行的规则组转换立即执行注入序列完成后自动恢复规则组转换。这就是“注入”Injected的含义——高优先级任务插入。 |
**关系小结**:操作模式定义了各组转换的**执行流程**。规则组是“常规任务流程”,而注入组是可打断常规流程的“高优先级中断任务流程”。
---
### 2. 规则组/注入组 与 数据转移方式 的关系
这是关系最紧密的部分,**数据转移方式的选择直接受到所用组别的严重影响**。
| 特性 | 规则组 (Routine Group) | 注入组 (Injected Group) |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **数据寄存器** | 只有**一个**数据寄存器 `ADC_RDATA`。所有规则通道的转换结果都放在这里。**如果不及时读取,就会被下一个通道的结果覆盖**。 | 有**多个**独立的数据寄存器(如 `ADC_IDATA0`, `ADC_IDATA1`, `ADC_IDATA2`, `ADC_IDATA3`)。每个注入通道都有自己专用的寄存器,结果不会被覆盖。 |
| **数据转移方式** | **强烈依赖DMA**。因为在扫描模式下多个通道快速连续转换CPU很难及时读取单个寄存器而不丢失数据。DMA可以自动将每个通道的结果搬运到指定数组。 | **非常适合使用中断**。因为注入组通道数少且每个结果都有独立的寄存器不会丢失。可以在注入转换完成中断JEOC中安全地读取所有 `ADC_IDATAx` 寄存器。 |
| **标志位** | 转换结束标志 `EOC` 在**每个通道**转换完成后都置位。序列结束标志 `EOS` 在**整个规则序列**转换完成后置位。 | 注入组转换结束标志 `JEOC` 在**整个注入序列**转换完成后置位。 |
**关系小结**
* **规则组 + 多通道 + 扫描模式 => 几乎必须使用DMA**来高效可靠地搬运数据。
* **注入组 + 少数通道 => 使用查询或中断**即可安全地读取数据,因为结果有专属“座位”(寄存器),不会丢。
---
### 实际应用场景举例(结合三者)
**场景:云台系统监控**
* **规则组**(常规任务):用于**周期性采集**电机编码器位置、系统电压、系统电流。配置为**连续扫描模式 + DMA**。ADC在后台持续采样DMA自动将三个通道的数据循环写入内存数组主循环只需读取数组即可极其高效。
* **注入组**(紧急任务):用于**过流保护**。配置一个电流通道,设置为**单次转换模式 + 中断**并由一个比较器的硬件输出信号作为触发源。当电流突然超过阈值比较器触发信号立即产生ADC**中断**正在进行的规则组转换,**立即**执行注入转换采集电流,并在转换完成后进入中断服务程序。在中断中,程序可以立即读取 `ADC_IDATA0` 得到电流值,并紧急停止电机。
在这个例子中,您可以看到:
* **What** (规则组/注入组):定义了监控和保护两个任务。
* **How** (连续扫描/单次):定义了任务的执行节奏。
* **What to do** (DMA/中断):定义了结果数据的处理方式。
三者协同工作,共同构成了一个高效、可靠且响应及时的数据采集系统。
## `adc_routine_channel_config`函数说明
在GD32微控制器的ADC驱动库中`adc_routine_channel_config`函数用于配置规则组(常规序列)的通道序列。
### 🧾 函数原型
在GD32的库函数中该函数的原型通常类似于
```c
void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t channel, uint32_t sample_time);
```
### 📊 参数详解
为了更直观地理解第二和第三个参数的区别与联系,请看下表:
| 特性 | 第二个参数 (`rank`) | 第三个参数 (`channel`) |
| :------------------- | :------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- |
| **参数含义** | 指定**转换顺序中的序号**(即该通道在规则组序列中的**位置** | 指定**具体的ADC物理通道**(即连接模拟信号的**输入源** |
| **参数目的** | 决定**多个通道的转换先后顺序** | 决定**转换哪个引脚或内部信号源** |
| **取值范围** | 通常从 `0`开始最大取决于规则组通道总数例如16个通道则是 `0``15` | 取决于MCU型号例如 `ADC_CHANNEL_0`, `ADC_CHANNEL_1`, ..., `ADC_CHANNEL_17`(内部通道) |
| **配置寄存器** | `ADC_RSQ2`, `ADC_RSQ1`, `ADC_RSQ0` (规则序列寄存器) | 与 `rank`共同配置规则序列寄存器 |
| **示例说明** | `rank = 0`表示该通道是序列中**第一个**被转换的 | `channel = ADC_CHANNEL_5`表示选择MCU的**特定ADC引脚**如PA5 |
### ⚠️ 注意事项
1. **`rank`值与实际转换顺序**`rank`参数通常从 `0`开始递增,表示转换的先后顺序。**`rank`值越小,转换顺序越靠前**。例如,`rank = 0`的通道最先转换,`rank = 1`的通道其次,以此类推。
2. **通道总数设置**:在配置所有通道的 `rank`之前,务必先通过 `adc_channel_length_config(adc_periph, ADC_ROUTINE_CHANNEL, n)`函数正确设置规则组的总通道数 `n`
3. **避免重复或越界**:确保不同的 `rank`值指向不同的序列位置,并且所有 `rank`值都小于总通道数 `n`。同时,确保选择的物理 `channel`在MCU实际存在的范围内。
4. **采样时间**:此函数的第四个参数 `sample_time`采样时间同样重要它决定了ADC对输入信号采样的持续时间需根据信号源阻抗进行调整。
### 💡 总结
可以这样理解:
* **`rank`(第二个参数)是“排队号”**:决定通道转换的**顺序**。
* **`channel`(第三个参数)是“身份证”**:确定转换的**具体是哪个物理通道**。
函数的作用就是将特定的物理通道(`channel`)安排到规则组转换序列中的指定位置(`rank`)上。
---
## ADC程序模式说明
这几种ADC模式是STM32中常见的配置组合主要区别在于**转换组别、转换方式、数据采集方式**等方面。让我详细解释每种模式:
### ADC_MODE_0 - 基础单次转换模式
```c
// 规则组、单次转换、非扫描
#define CONTINUOUS_STATUS DISABLE // 单次转换
#define SEQUENCE_CHANNEL ADC_ROUTINE_CHANNEL // 规则组
#define SCAN_STATUS DISABLE // 非扫描
#define CHANNEL_LENGTH 1 // 单通道
```
**特点:**
- **单次转换**:每次触发只转换一次
- **规则组**:常规转换通道组
- **非扫描**:只转换一个通道
- **应用场景**简单的单通道ADC读取如电位器、温度传感器
**工作流程:**
```
触发 → 转换通道1 → 停止 → 等待下次触发
```
### ADC_MODE_1 - 注入组扫描模式
```c
// 注入组、单次转换、扫描、转换结束标志位采集
#define CONTINUOUS_STATUS DISABLE // 单次转换
#define SEQUENCE_CHANNEL ADC_INSERTED_CHANNEL // 注入组
#define SCAN_STATUS ENABLE // 扫描模式
#define CHANNEL_LENGTH 2 // 多通道
```
**特点:**
- **注入组**:高优先级,可打断规则组转换
- **扫描模式**:自动按顺序转换多个通道
- **查询方式**:通过轮询标志位获取数据
- **应用场景**:需要打断常规转换的紧急测量
**工作流程:**
```
触发 → 转换通道1 → 转换通道2 → 设置EOC标志 → 读取数据
```
### ADC_MODE 2 - 中断方式注入组扫描
```c
// 注入组、单次转换、扫描、中断转换结束标志位采集
#define CONTINUOUS_STATUS DISABLE
#define SEQUENCE_CHANNEL ADC_INSERTED_CHANNEL // 注入组
#define SCAN_STATUS ENABLE // 扫描模式
#define CHANNEL_LENGTH 2 // 多通道
#define ADCX_IRQn ADC_IRQn // 启用中断
```
**特点:**
- **中断方式**:转换完成后产生中断
- **实时性更好**:不需要轮询等待
- **应用场景**:对实时性要求高的多通道测量
**工作流程:**
```
触发 → 转换通道1 → 转换通道2 → 产生中断 → 在ISR中读取数据
```
### ADC_MODE 3 - DMA连续采集模式
```c
// 规则组、连续转换、扫描、DMA采集
#define CONTINUOUS_STATUS ENABLE // 连续转换
#define SEQUENCE_CHANNEL ADC_ROUTINE_CHANNEL // 规则组
#define SCAN_STATUS ENABLE // 扫描模式
#define CHANNEL_LENGTH 2 // 多通道
#define DMAX DMA1 // 使用DMA
```
**特点:**
- **连续转换**:自动重复转换序列
- **DMA传输**:自动将数据搬运到内存
- **高效率**不占用CPU资源
- **应用场景**:高速数据采集、波形采样、实时监控
**工作流程:**
```
启动 → [转换通道1 → 转换通道2] → DMA传输 → [转换通道1 → 转换通道2] → ...
↑_____________________________循环___________________________↑
```
### 关键概念对比
#### 1. 规则组 vs 注入组
| 特性 | 规则组 | 注入组 |
| ------ | -------- | ------------------ |
| 优先级 | 正常 | 高(可打断规则组) |
| 通道数 | 最多16个 | 最多4个 |
| 应用 | 常规测量 | 紧急或同步测量 |
#### 2. 单次 vs 连续转换
| 特性 | 单次转换 | 连续转换 |
| -------- | ---------------- | ------------ |
| 工作方式 | 触发一次转换一次 | 自动重复转换 |
| CPU占用 | 低 | 需要管理数据 |
| 适用场景 | 低速采样 | 高速连续采样 |
#### 3. 数据获取方式对比
| 方式 | 查询标志位 | 中断方式 | DMA方式 |
| ------- | ---------------- | ------------------- | -------- |
| CPU占用 | 中等(需要轮询) | 低仅在ISR中处理 | 几乎为零 |
| 实时性 | 一般 | 好 | 最好 |
| 复杂度 | 简单 | 中等 | 复杂 |
### 实际应用建议
#### 选择指南:
- **简单单通道读取** → MODE_0
- **紧急多通道测量** → MODE_1或MODE_2
- **高速连续采集** → MODE_3
- **需要实时响应** → MODE_2中断
- **需要低CPU占用** → MODE_3DMA
#### 性能考虑:
- DMA模式适合采样率>10Ksps的场景
- 中断模式适合1-10Ksps的中等速率
- 查询模式适合<1Ksps的低速应用
这些模式覆盖了从简单到复杂的各种ADC应用场景可以根据具体需求灵活选择
---
| 事件 | 断电保护 | 电压过高保护 | 过流保护 | 一般温度10以下故障 | 极限温度10以上故障 | 光电开关遮挡 |
| :--: | :----------: | :----------: | :------: | :----------------------: | :----------------------: | -------------------- |
| 响应 | 检测掉电存储 | 断电 | 电机停转 | -仅故障回传 | 电机停转 | 同时累计遮挡电机停转 |
| | | | | | | |
| | | | | | | |
# 高精度转台/云台嵌入式软件故障上报与响应规范
## 概述
此文档定义了高精度转台云台嵌入式软件中的故障上报与响应机制涵盖的主要故障类型包括电源异常过电压过流)、温度异常光电挡板限位传感器异常掉电保护等
### 大概故障分类
按紧急程度分为P0致命)、P1)、P2)、P3四类故障
| 故障类型 | 定义 | 响应 |
| ------------- | ------------------------------------ | -------------------------------------- |
| P0 致命 | 严重电流过载电压过高温度过高 | 立即停机断电报警并持久化故障状态 |
| P1 | 光电挡板遮挡电流持续过流电压过低 | 停机限流恢复模式报警上报 |
| P2 | 温度接近限制传感器异常 | 限速报警上报 |
| P3 (可不用) | 通信错误较小的传感器波动 | 记录日志便于后续诊断 |
## 关键设计原则
- **快速检测安全响应**利用硬件中断和软件冗余检测保障故障发生时的最短响应时间
- **可恢复优先不能恢复则安全停机**在无法恢复的情况下紧急停机并持久化关键故障信息
- **掉电保护**确保在掉电时能够正确保存系统状态以便恢复
## 主要模块
### 电压监测
- **硬件设计**利用ADC模块或者电压比较器监测主电源电压
- **故障响应**过电压和欠电压将触发报警并在满足条件时进行电机断电停机
### 电流监测
- **硬件设计**使用霍尔传感器或分流电阻监测电机电流
- **故障响应**持续过流时电机停止工作并切断PWM驱动或者发送停转电机指令
### 温度监测
- **硬件设计**通过温度传感器如NTC热敏电阻或者TMP75进行监测
- **故障响应**超过设定温度阈值时限制负载和转速或停机保护
### 光电挡板(限位)监测
- **硬件设计**使用光电传感器或光耦监测挡板状态
- **故障响应**检测到遮挡时立即停机避免碰撞
### 掉电保护
- **硬件设计**通过监测电源电压下降并使用电容保证在掉电瞬间写入系统状态
- **故障响应**在掉电事件前保存关键状态数据
## 故障上报
错误代码使用统一格式进行上报确保与上位机的兼容性
| 错误码 | 错误描述 | 优先级 | 模块 |
| ---------- | -------------------- | ------ | ---------- |
| 0x01010001 | 主电源过压 | P1 | 电源 |
| 0x01010002 | 主电源欠压 | P1 | 电源 |
| 0x02020001 | 电机A持续过流 | P0 | 电流 |
| 0x02020002 | 电机B短路 | P0 | 电流 |
| 0x03030001 | 驱动模块过温 | P1 | 温度 |
| 0x04040001 | 光电挡板左侧遮挡异常 | P1 | 限位传感器 |
| 0x04040002 | 光电挡板右侧开路 | P2 | 限位传感器 |
| 0x05050001 | 编码器错位 | P2 | 传感器 |
## 测试与验收
### 单元测试
* 电压检测模拟电压过高/过低验证响应动作
* 电流检测模拟过流验证驱动停止和故障上报
* 温度检测模拟温度过高验证系统限速和停机保护
### 集成测试
* 多故障并发模拟电流过载和电压不稳检查故障优先级和响应动作
* 长时间压力测试测试系统长时间稳定运行模拟逐渐升温
### 验收标准
* 掉电保护成功率99.9%断电前成功写入状态
* 电流/电压/温度监测反应时间:≤5ms
* 故障上报与记录符合协议信息完整且准确
**示例上报报文格式**
```json
{
"error_code": "0x01020005",
"severity": "P1",
"timestamp": "2025-09-30T11:32:14Z",
"voltage_v": 28.3,
"current_a": 1.3,
"temp_c": 52.4,
"encoder_deg": 12.345,
"message": "motor B continuous overcurrent",
//"firmware": "v1.2.3",
"cmd_id": "PT-001"
"mac": "PT-001"
}
```
## C示例代码
```c
// 电流监测中断处理示例
void OVERCURRENT_IRQHandler(void) {
// 立即切断驱动使能
Motor_DisableDriver(MOTOR_B);
// 读取电流并记录
float current = adc_read(CURRENT_B);
log_error(ERROR_CODE_OVERCURRENT(MOTOR_B), "Overcurrent detected", current);
// 上报错误至上位机
ReportErrorToHost(ERROR_CODE_OVERCURRENT(MOTOR_B));
// 进入等待人工复位模式
EnterSafeLoop();
}
// 掉电ISR 保存最小状态
volatile bool power_failing = false;
void POWER_FALL_IRQHandler(void) {
if (power_failing) return;
power_failing = true;
// 禁止新动作立即切断PWM
Motor_StopAllPWMImmediate();
// 采集快照
Snapshot_t snap;
snap.magic = SNAP_MAGIC;
snap.timestamp = rtc_get_time();
snap.voltage = adc_read(VOLTAGE_CHANNEL);
snap.current = adc_read(CURRENT_CHANNEL);
snap.temp = adc_read(TEMP_CHANNEL);
snap.encoder_pos = encoder_get_position();
snap.error_flags = global_error_flags;
// 计算CRC并保存
snap.crc = crc32((uint8_t*)&snap, sizeof(snap) - sizeof(snap.crc));
FRAM_Write(SNAPSHOT_ADDR, (uint8_t*)&snap, sizeof(snap));
// 启动刹车机制
Hardware_EnableBrake();
// 进入安全循环
EnterSafeLoop();
}
```