STM32F405 ADC规则组+注入组混合采集
STM32F405ADC规则组+注入组混合采集
·
STM32F405 ADC规则组+注入组混合采集
- 📍相关篇《STM32F405 ADC+DMA双缓冲规则组采集》:
https://blog.csdn.net/weixin_42880082/article/details/160885937?spm=1011.2415.3001.5331
🔰两种模式对比
在同时使能规则组和注入组,并开启自动转换(JAUTO=1)的模式下,规则组优先被转换。
具体流程是:ADC会先完整执行完规则组的所有通道转换,转换结束后自动立即启动注入组的转换,无需外部触发。
| 模式 | 转换顺序 | 适用场景 |
|---|---|---|
| 自动注入 (JAUTO=1) | 规则组 → 注入组(固定顺序) | 需要规则组和注入组“打包”完成,对时序要求严格的场合 |
| 触发注入 (JAUTO=0) | 注入组可随时打断规则组(高优先级) | 注入组需要在特定时刻(如PWM中点)紧急插入 |
📘注入组模式下,触发方式
- 在触发注入模式下(
JAUTO = 0),STM32的注入组支持两类外部触发源:定时器事件和外部中断线。具体的可用触发源如下:
⏱️ 定时器触发源(最常用)
注入组转换可通过多个定时器的输出事件来启动,支持选择的事件类型包括:
- 比较/捕获事件:如
TIMx_CCy,在定时器计数值与通道比较值匹配时触发,非常适合在特定PWM位置进行采样(如电机控制)。 - 触发输出事件:如
TIMx_TRGO或TIMx_TRGO2,利用定时器自己的主模式输出,可用来同步触发ADC等多个外设。
🔌 外部中断线触发源
除了定时器,还可以通过 EXTI(外部中断/事件控制器)线 来触发。例如 EXTI Line 15,它能将任意GPIO的边沿信号直接作为ADC的触发源。这种方式逻辑简单,无需配置定时器,但需要注意可能比定时器触发的噪声更大一些。
🎯 触发极性与使能
除了选择触发源,你还可以配置触发极性:
- 上升沿触发
- 下降沿触发
- 双边沿触发(上升沿或下降沿都触发)
⚠️ 重要注意事项
- 配置时机:外部触发源的选择(
JEXTSEL)和极性(JEXTEN)必须在停止注入组转换(JADSTART = 0)时进行配置,否则可能无效。 - 系列差异:不同STM32系列支持的具体定时器编号和EXTI线不同。例如某些型号支持TIM15触发,而有些则不支持。具体支持哪些,请务必查阅对应型号的参考手册(Reference Manual)。
- 优先级:一旦启用了外部触发(
JEXTEN不为0),硬件触发将生效,此时软件触发通常会被忽略。
💡 典型应用场景
- 电机控制/FOC:使用PWM定时器的比较事件(如TIM1_CC4)触发注入组,在PWM周期的特定时刻(如下桥臂导通中点)进行电流采样,以避开开关噪声。
- 变频器/电源:利用定时器的更新事件(TRGO)同步多个ADC同时采样电压和电流。
📒例程配置
- ADC规则组通道:2个(CH0, CH1) | 注入组通道:4个(CH2, CH3, CH4, CH5)
- 本项目实现基于STM32F405的6通道ADC数据采集系统,采用规则组DMA传输+注入组中断读取的混合架构,实现高效、稳定的数据采集和串口输出。
主要特性:
- 规则组(Regular Group):2通道(PA0, PA1),DMA双缓冲传输
- 注入组(Injected Group):4通道(PA2, PA3, PA4, PA5),中断读取
- 注入组在规则组转换完成后自动触发
- 串口实时输出采集结果(含电压转换)
⚙️ 硬件配置
🖥️ MCU
| 参数 | 规格 |
|---|---|
| 型号 | STM32F405RGT6 |
| 内核 | ARM Cortex-M4 |
| 主频 | 168MHz |
⏱️ 时钟配置
| 参数 | 设置 |
|---|---|
| 时钟源 | HSE (8MHz 外部晶振) |
| PLL_M | 4 |
| PLL_N | 168 |
| PLL_P | 2 |
| PLL_Q | 4 |
| SYSCLK | 168MHz |
| HCLK (AHB) | 168MHz |
| PCLK1 (APB1) | 42MHz (最大42MHz) |
| PCLK2 (APB2) | 84MHz (最大84MHz) |
| ADC时钟 | 21MHz (PCLK2/4) |
📊 ADC配置
| 参数 | 设置 |
|---|---|
| 使用ADC | ADC2(独立模式) |
| 规则组通道 | CH0 (PA0), CH1 (PA1) |
| 注入组通道 | CH2 (PA2), CH3 (PA3), CH4 (PA4), CH5 (PA5) |
| 分辨率 | 12位(0~4095) |
| 采样时间 | 28个ADC时钟周期 |
| 转换模式 | 连续扫描模式 |
| 自动注入 | ENABLE(规则组完成后自动触发注入组) |
ADC初始化配置代码(adc.c):
hadc2.Instance = ADC2; // 使用ADC2
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 时钟分频:PCLK2/4 = 21MHz
hadc2.Init.Resolution = ADC_RESOLUTION_12B; // 分辨率:12位
hadc2.Init.ScanConvMode = ENABLE; // 扫描模式:使能(多通道)
hadc2.Init.ContinuousConvMode = ENABLE; // 连续转换模式:使能
hadc2.Init.DiscontinuousConvMode = DISABLE; // 间断转换模式:禁用
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; // 外部触发边沿:无
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 触发源:软件触发
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据对齐:右对齐
hadc2.Init.NbrOfConversion = 2; // 规则组通道数:2个
hadc2.Init.DMAContinuousRequests = ENABLE; // DMA连续请求:使能
hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV; // EOC选择:序列转换完成
注入组配置代码:
sConfigInjected.InjectedChannel = ADC_CHANNEL_2; // 注入通道2
sConfigInjected.InjectedRank = 1; // 注入序列位置1
sConfigInjected.InjectedNbrOfConversion = 4; // 注入组通道数:4个
sConfigInjected.AutoInjectedConv = ENABLE; // 自动注入:使能
sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START;
- 自动注入触发方式有关宏:
#define ADC_EXTERNALTRIGINJECCONV_T1_CC4 0x00000000U
#define ADC_EXTERNALTRIGINJECCONV_T1_TRGO ((uint32_t)ADC_CR2_JEXTSEL_0)
#define ADC_EXTERNALTRIGINJECCONV_T2_CC1 ((uint32_t)ADC_CR2_JEXTSEL_1)
#define ADC_EXTERNALTRIGINJECCONV_T2_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T3_CC2 ((uint32_t)ADC_CR2_JEXTSEL_2)
#define ADC_EXTERNALTRIGINJECCONV_T3_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T4_CC1 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1))
#define ADC_EXTERNALTRIGINJECCONV_T4_CC2 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T4_CC3 ((uint32_t)ADC_CR2_JEXTSEL_3)
#define ADC_EXTERNALTRIGINJECCONV_T4_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T5_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1))
#define ADC_EXTERNALTRIGINJECCONV_T5_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T8_CC2 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2))
#define ADC_EXTERNALTRIGINJECCONV_T8_CC3 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJECCONV_T8_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1))
#define ADC_EXTERNALTRIGINJECCONV_EXT_IT15 ((uint32_t)ADC_CR2_JEXTSEL)
#define ADC_INJECTED_SOFTWARE_START ((uint32_t)ADC_CR2_JEXTSEL + 1U)
🔄 ADC规则组 DMA配置
- ✨ ADC注入组不支持转换后DMA传输方式。ADC注入组有专门的中断回调函数。
| 参数 | 设置 |
|---|---|
| DMA通道 | DMA2_Stream2,通道1 |
| 数据宽度 | 半字(16位) |
| 传输模式 | 正常模式 |
| 传输方向 | 外设到内存 |
| 内存增量模式 | 使能 |
DMA初始化配置代码(dma.c):
hdma_adc2.Instance = DMA2_Stream2; // DMA流:DMA2_Stream2
hdma_adc2.Init.Channel = DMA_CHANNEL_1; // DMA通道:通道1
hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; // 传输方向:外设到内存
hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址增量:禁用
hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; // 内存地址增量:使能
hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 外设数据宽度:半字(16位)
hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; // 内存数据宽度:半字(16位)
hdma_adc2.Init.Mode = DMA_NORMAL; // 传输模式:正常模式
hdma_adc2.Init.Priority = DMA_PRIORITY_MEDIUM; // 优先级:中等
hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; // FIFO模式:禁用
📡 串口配置
| 参数 | 设置 |
|---|---|
| 串口 | USART1 |
| 波特率 | 115200 |
| 数据位 | 8位 |
| 停止位 | 1位 |
| 校验 | 无 |
🏗️ 软件架构
✨ 核心功能
- 规则组采集:2通道(CH0, CH1),DMA双缓冲传输
- 注入组采集:4通道(CH2, CH3, CH4, CH5),中断读取
- 自动触发:规则组完成后自动触发注入组转换
- 双缓冲机制:规则组使用双缓冲,实现零等待数据交换
- 串口输出:转换完成后通过串口打印各通道结果(含电压值)
🔀 工作原理
串行执行流程(推荐配置):
- 规则组转换完成 → 自动触发注入组(AutoInjectedConv = ENABLE)
- 注入组转换完成 → 在注入组回调中重启规则组DMA转换
完整的转换链:规则组 → 注入组 → 规则组 → 注入组…
┌──────────────────────────────────────────────────────────────────────────┐
│ 规则组+注入组串行采集流程 │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 启动规则组DMA转换 │
│ │ │
│ ↓ │
│ 2. 规则组转换 (CH0, CH1) + DMA传输 │
│ │ │
│ │ DMA完成中断 │
│ ↓ │
│ 3. HAL_ADC_ConvCpltCallback() │
│ │ - 设置new_regular_data_flag = 1 │
│ │ - 切换缓冲区 │
│ ↓ │
│ 4. [硬件自动触发] 注入组转换 (CH2, CH3, CH4, CH5) │
│ │ │
│ │ JEOC中断 │
│ ↓ │
│ 5. HAL_ADCEx_InjectedConvCpltCallback() │
│ │ - 读取注入组数据 │
│ │ - 设置new_injected_data_flag = 1 │
│ │ - 启动下一轮规则组DMA转换 │
│ ↓ │
│ 6. 主循环检测双标志 → 串口输出规则组+注入组数据 │
│ ↓ │
│ 循环回到步骤2... │
│ │
└──────────────────────────────────────────────────────────────────────────┘
工作时序:
- 启动规则组DMA转换(首次)
- 规则组完成 → DMA中断 → 设置规则组标志 + 切换缓冲区
- 硬件自动触发注入组转换
- 注入组完成 → JEOC中断 → 读取注入数据 + 设置注入组标志 + 重启规则组
- 主循环检测双标志 → 串口输出
- 循环往复
⚡ 中断触发流程
┌──────────────────────────────────────────────────────────────────────┐
│ 规则组+注入组中断触发流程 │
├──────────────────────────────────────────────────────────────────────┤
│ 1. HAL_ADC_Start_DMA() 启动规则组DMA转换 │
│ ↓ │
│ 2. ADC开始规则组转换 (CH0, CH1) │
│ ↓ │
│ 3. DMA将规则组数据传输到内存缓冲区 │
│ ↓ │
│ 4. 规则组完成 → DMA TC中断 │
│ ↓ │
│ 5. HAL_ADC_ConvCpltCallback() │
│ ↓ │
│ 6. 设置 new_regular_data_flag = 1 + 切换缓冲区 │
│ ↓ │
│ 7. [硬件自动触发] 注入组开始转换 (CH2, CH3, CH4, CH5) │
│ ↓ │
│ 8. 注入组完成 → JEOC中断 (注入组中断必须使能) │
│ ↓ │
│ 9. HAL_ADCEx_InjectedConvCpltCallback() │
│ ↓ │
│ 10. 读取注入组数据 + 设置 new_injected_data_flag = 1 │
│ ↓ │
│ 11. HAL_ADC_Start_DMA() 启动下一轮规则组转换 │
│ ↓ │
│ 12. 主循环检测双标志 → 读取数据 → 串口输出 │
└──────────────────────────────────────────────────────────────────────┘
关键配置要点:
| 配置项 | 设置 | 说明 |
|---|---|---|
AutoInjectedConv |
ENABLE | 规则组完成后自动触发注入组 |
ADC_IT_JEOC |
ENABLE | 使能注入组转换完成中断 |
| DMA模式 | NORMAL | 正常模式,每轮转换完成后需重新启动 |
🔑 关键变量
| 变量名 | 类型 | 说明 |
|---|---|---|
adc_regular_buf[2][2] |
uint16_t | 规则组双缓冲区(2个缓冲区,每区2个通道) |
adc_injected_buf[4] |
uint16_t | 注入组数据缓冲区(4个通道) |
current_buf |
uint8_t | 当前规则组DMA写入的缓冲区索引(0或1) |
new_regular_data_flag |
uint8_t | 规则组新数据标志 |
new_injected_data_flag |
uint8_t | 注入组新数据标志 |
📖 使用说明
🔌 硬件连接
| 信号 | MCU引脚 | 说明 |
|---|---|---|
| ADC_IN0 | PA0 | 模拟输入通道0 |
| ADC_IN1 | PA1 | 模拟输入通道1 |
| ADC_IN2 | PA2 | 模拟输入通道2 |
| ADC_IN3 | PA3 | 模拟输入通道3 |
| ADC_IN4 | PA4 | 模拟输入通道4 |
| ADC_IN5 | PA5 | 模拟输入通道5 |
| USART1_TX | PA9 | 串口发送(连接USB转TTL模块的RX) |
| USART1_RX | PA10 | 串口接收(可选,连接USB转TTL模块的TX) |
| VREF+ | VDDA | 参考电压输入(连接稳定3.3V) |
| GND | GND | 共地 |
📤 串口输出格式
=== ADC2 规则组数据 (Regular Group) ===
CH0 (PA0): 1270 (1.01V)
CH1 (PA1): 1287 (1.02V)
=== ADC2 注入组数据 (Injected Group) ===
CH2 (PA2): 1262 (1.00V)
CH3 (PA3): 1249 (0.99V)
CH4 (PA4): 1259 (1.00V)
CH5 (PA5): 1306 (1.03V)
------------------------
⚙️ 软件配置
编译环境:
- STM32CubeIDE / Keil MDK
- STM32Cube HAL库
烧录方式:
- 使用ST-Link连接开发板
- 编译工程生成.hex或.bin文件
- 通过烧录工具下载到STM32F405
⚠️ 注意事项
- 电压范围:模拟输入电压必须在0~3.3V范围内
- 参考电压:VDDA引脚必须连接稳定的3.3V电源,建议添加去耦电容
- ADC精度:12位分辨率,电压分辨率约为0.8mV(3.3V/4096)
- 串口设置:调试工具波特率需设置为115200
- 初始化:主函数中调用
HAL_ADC_Start_DMA()启动采集
💻 核心代码说明
📦 全局变量定义
#define ADC_REGULAR_CHANNEL_NUM 2 // 规则组通道数
#define ADC_INJECTED_CHANNEL_NUM 4 // 注入组通道数
uint16_t adc_regular_buf[2][ADC_REGULAR_CHANNEL_NUM]; // 规则组双缓冲
uint16_t adc_injected_buf[ADC_INJECTED_CHANNEL_NUM]; // 注入组缓冲区
uint8_t current_buf = 0; // 当前DMA写入缓冲区索引
uint8_t new_regular_data_flag = 0; // 规则组新数据标志
uint8_t new_injected_data_flag = 0; // 注入组新数据标志
▶️ 启动ADC转换
// 启动规则组DMA转换(注入组由硬件自动触发)
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_regular_buf[current_buf], ADC_REGULAR_CHANNEL_NUM);
//开启注入组中断
HAL_ADCEx_InjectedStart_IT(&hadc2);
🔔 规则组转换完成回调函数(main.c)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC2)
{
new_regular_data_flag = 1; // 标记规则组有新数据
current_buf = 1 - current_buf; // 切换缓冲区
// 由于AutoInjectedConv=ENABLE,硬件会自动触发注入组
}
}
🔔 注入组转换完成回调函数(main.c)
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC2)
{
// 读取注入组各通道数据
adc_injected_buf[0] = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);
adc_injected_buf[1] = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);
adc_injected_buf[2] = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);
adc_injected_buf[3] = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_4);
new_injected_data_flag = 1; // 标记注入组有新数据
// 启动下一轮规则组DMA转换(形成串行循环)
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_regular_buf[current_buf], ADC_REGULAR_CHANNEL_NUM);
}
}
🔄 主循环数据处理
while (1)
{
// 处理规则组和注入组数据
if(new_regular_data_flag )
{
uint8_t read_buf = 1 - current_buf;
printf("=== ADC2 规则组数据 (Regular Group) ===\r\n");
printf("CH0 (PA0): %d (%.2fV)\r\n", adc_regular_buf[read_buf][0], ADC_to_Voltage(adc_regular_buf[read_buf][0]));
printf("CH1 (PA1): %d (%.2fV)\r\n", adc_regular_buf[read_buf][1], ADC_to_Voltage(adc_regular_buf[read_buf][1]));
printf("\r\n");
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // LED闪烁指示
new_regular_data_flag = 0;
}
else if(new_injected_data_flag)
{
printf("=== ADC2 注入组数据 (Injected Group) ===\r\n");
printf("CH2 (PA2): %d (%.2fV)\r\n", adc_injected_buf[0], ADC_to_Voltage(adc_injected_buf[0]));
printf("CH3 (PA3): %d (%.2fV)\r\n", adc_injected_buf[1], ADC_to_Voltage(adc_injected_buf[1]));
printf("CH4 (PA4): %d (%.2fV)\r\n", adc_injected_buf[2], ADC_to_Voltage(adc_injected_buf[2]));
printf("CH5 (PA5): %d (%.2fV)\r\n", adc_injected_buf[3], ADC_to_Voltage(adc_injected_buf[3]));
printf("\r\n");
new_injected_data_flag = 0;
}
}
⚡ ADC值转电压函数
float ADC_to_Voltage(uint16_t adc_value)
{
return (adc_value * 3.3f) / 4095.0f;
}
- 🎉对于不支持硬件浮点运算内核的MCU(Cortex-M0/M3),可以采用毫伏表示:
uint32_t ADC_to_Voltage_mv(uint16_t adc_value)
{
//定点(保留 3 位小数)
return ((uint32_t)adc_value*3300)/4096;//单位:毫伏
}
如果需要伏显示输出,使用sprintf函数:
sprintf(buf, "%d.%03d\n", voltage_mv / 1000, voltage_mv % 1000);
📐ADC转换时间计算
STM32系列(Cortex-M3/M4)的ADC总转换时间计算公式(以12位分辨率为例)通常为:
TCONV=(采样时间+12.5)×TADC_CLKT_{CONV} = (采样时间 + 12.5) \times T_{ADC\_CLK}TCONV=(采样时间+12.5)×TADC_CLK
其中12.5是逐次逼近(SAR)ADC内部完成量化所需的内核时钟周期数,固定不变。
🔰不同系列的差异
| MCU系列 | 内核 | 12位模式转换周期 | 其他分辨率对应周期 |
|---|---|---|---|
| STM32F1 | Cortex-M3 | 12.5个周期 | - |
| STM32F4 | Cortex-M4 | 12.5个周期 | 10位: 10.5 / 8位: 8.5 / 6位: 6.5 |
| STM32L4 | Cortex-M4 | 12.5个周期 | 受电源电压影响 |
| STM32G4 | Cortex-M4 | 12.5个周期 | 支持硬件过采样,会额外增加时间 |
说明:即使在同一厂商、同一Cortex内核的不同型号中,公式中的常数也可能不同。本项目使用STM32F405,采用12位分辨率,因此转换周期为12.5个ADC时钟周期。
⚡ 性能参数
| 参数 | 数值 | 说明 |
|---|---|---|
| ADC时钟 | 21MHz | PCLK2=84MHz,分频4 |
| 单通道采样时间 | 28个ADC时钟周期 | 约1.33μs |
| 单通道总转换时间 | 40.5个ADC时钟周期 | 约1.93μs(Tconv = 28 + 12.5) |
| 规则组(2通道)转换时间 | ~81个ADC时钟周期 | ~3.86μs |
| 注入组(4通道)转换时间 | ~162个ADC时钟周期 | ~7.71μs |
| 单次完整转换(6通道) | ~243个ADC时钟周期 | ~11.57μs |
| 理论采样率 | ~86.4kSps | 6通道扫描模式 |
| 实际采样率 | ~70-80kSps | 受串口输出影响 |
🔧 故障排除
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 串口无输出 | 串口波特率不匹配 | 确认串口工具波特率为115200 |
| ADC值始终为0 | 模拟输入未连接或接地 | 检查模拟输入信号连接 |
| ADC值始终为4095 | 模拟输入超过3.3V或短路到VDD | 检查输入电压范围 |
| ADC值波动大 | 电源不稳定或未加滤波 | 增加电源去耦电容,使用RC滤波 |
| 数据不更新 | DMA配置错误 | 检查DMA通道、流配置和中断使能 |
| 中断不触发 | NVIC优先级配置错误 | 确认ADC和DMA中断已正确配置 |
| 缓冲区数据错误 | 缓冲区索引逻辑错误 | 检查 current_buf切换逻辑 |
📚测试源码
通过网盘分享的文件:STM32F405_ADC2_Injected_DMA.rar
链接: https://pan.baidu.com/s/1NDrXLmGOjORGSJtLUs2eFg 提取码: 5a4e
更多推荐



所有评论(0)