GD32F4系列搭载了高性能的12位逐次逼近型（SAR）ADC，提供了非常灵活和强大的数据采集功能。其采集方式可以从**操作模式**和**数据转移方式**两个维度来理解。

### 一、按操作模式划分

操作模式决定了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/中断)：定义了结果数据的处理方式。

三者协同工作，共同构成了一个高效、可靠且响应及时的数据采集系统。

在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`）上。
