【STM32G4-FOC】(1)STM32G431 之创建项目
【STM32G4-FOC】(2)STM32G431 之 TIM+ADC
【STM32G4-FOC】(3)STM32G431之三相互补 PWM
【STM32G4-FOC】(4)PWM 硬件触发 ADC 同步采样
【STM32G4-FOC】(5)DAC 受控输出闭环链路
【STM32G4-FOC】(6)三相电流采样与标定
【STM32G4-FOC】(6)三相电流采样与标定 ------ 实验设计与验证
-
- [1. 项目介绍](#1. 项目介绍)
-
- [1.1 目的与意义](#1.1 目的与意义)
- [1.2 实验设计](#1.2 实验设计)
- [1.3 硬件需求与连接](#1.3 硬件需求与连接)
- [2 技术原理](#2 技术原理)
- [3. CubeMX 配置](#3. CubeMX 配置)
-
- [3.1 MCU 外设及其分工](#3.1 MCU 外设及其分工)
- [3.2 新建工程与系统配置](#3.2 新建工程与系统配置)
- [3.3 TIM 与 ADC 的配置](#3.3 TIM 与 ADC 的配置)
- [3.4 工程配置](#3.4 工程配置)
- [4. 三相电流数据结构与变量命名规范](#4. 三相电流数据结构与变量命名规范)
- [5. 实验 6-1:三相电流零点标定](#5. 实验 6-1:三相电流零点标定)
- [6. 小结:](#6. 小结:)
1. 项目介绍
1.1 目的与意义
在【STM32G4-FOC】(5)DAC 受控输出闭环链路 中,通过"采样---计算---输出"的实时闭环控制链路,验证了 STM32G431 在实时控制场景下构建闭环系统的可行性。
在此基础上,本章引入 FOC 控制中最关键的物理反馈量------三相定子电流,围绕电流采样链路的建立与标定展开实验。通过三相电流零点标定、静态通流一致性验证以及低速运行条件下的电流波形观测,系统性地验证电流采样数据的准确性与一致性,为后续坐标变换和电流闭环控制做好准备。
本章围绕三相电流采样与标定,将完成以下几个目标:
-
建立完整的三相电流采样链路
在真实功率驱动与电机负载条件下,打通电流信号从功率级到 ADC 的采样路径,确保采样流程可控、稳定。
-
完成电流采样的基础标定与一致性验证
通过零点偏置校正和静态通流实验,确保三相电流采样结果准确且相互一致。
-
为后续 FOC 控制提供可信的电流数据基础
验证电流采样在静态与低速动态条件下的可靠性,为坐标变换和电流闭环控制做好准备。
1.2 实验设计
本章围绕三相电流采样与标定展开,实验设计遵循由静态到动态、由验证到应用的工程思路,整体划分为以下三个层次:
-
零点标定实验(不依赖电机旋转)
在关闭或固定 PWM 输出的条件下,对三相电流采样通道进行连续采样,测量并补偿采样链路中的零点偏置,用于验证采样通道的稳定性与一致性。
-
静态通流一致性验证(不引入动态控制)
在完成零点标定的基础上,通过控制不同相位通流并对比三相电流采样结果,评估各相采样通道在幅值和趋势上的一致性,为后续坐标变换提供可信输入。
-
低速运行电流波形观测(接近实际工况)
在保证前两步结果可靠的前提下,引入低速开环运行条件,对三相电流波形的连续性和相位关系进行观测,用于验证采样链路在动态情况下的稳定性。
本章重点在于采样链路与数据可信度验证,而非完整 FOC 控制。通过上述分层实验设计,逐步验证三相电流采样数据的准确性与可靠性,为后续控制算法的实现做好准备。
1.3 硬件需求与连接
为完成本章"三相电流采样与标定"相关实验,需要构建包含控制、功率与负载的基本硬件系统。
本文使用 ST 官方提供的 P-NUCLEO-IHM03:基于 STM32 的电机控制套件 作为实验的硬件平台。P-NUCLEO-IHM03 STM32 电机控制套件包括:X-NUCLEO-IHM16M1 电机驱动板、NUCLEO-G431RB 主控板、GBM2804H-100T 云台直流无刷电机和 12V 直流电源。
-
控制模块:NUCLEO-G431RB 控制板
NUCLEO-G431RB 控制板,它连接用户命令和配置参数以驱动电机,以执行电机驱动控制算法(如FOC)。
基于高性能Arm® Cortex®-M4 32位 RISC内核,最高频率可达170 MHz且带有浮点单元(FPU),内嵌高级模拟外设集。
-
驱动模块:X-NUCLEO-IHM16M1 电机驱动板
NUCLEO-IHM16M1 电机驱动板,基于STSPIN830面向BLDC/PMSM电机的三相驱动板。
内嵌PWM电流控制器,支持单电阻或三电阻电流采样架构,支持并配置不同的闭环控制、FOC或6步有感或无感方案。
-
电机负载:GBM2804H-100T 直流无刷电机(PMSM)
以低压三相直流无刷电机作为实际负载,用于形成真实的三相电流通路。

P-NUCLEO-IHM03 电机控制套件的硬件连接如下:
-
堆叠连接电机驱动板与控制板。将 IHM16M1电机驱动板通过两侧的 CN7 和 CN10 连接器插接到 G431RB 控制板上,NUCLEO-G431RB 板上的两个按钮(用户按钮 B1和重置按钮 B2)应保持未覆盖状态。
-
将三相电机连接线 U、V、W 连接到 IHM16M1 电机驱动板上 CN1 连接器的 3/4/5 输出端。
-
配置 NUCLEO-G431RB 控制板上的跳线:
- 从 USB 为 NUCLEO-G431RB 供电时,将 JP5 的 5V-STLK 源设为 [1-2] 位置(跳线安装在 pin1、pin2 针脚);
- JP6(IDD)设为 ON 状态(安装 2针跳线);
- JP7(BOOT0)设为 OFF 状态(不安装跳线);
- JP8 的 VREF 设为 [1-2] 位置(跳线装在 pin1、pin2 针脚)。
-
配置 IHM16M1 电机驱动板的跳线,以选择所需的控制算法。注意:更改控制模式之前,必须关闭电源电压。
以FOC 控制为例:
- 三电阻采样配置:默认模式,背面的 JP4、JP7 处于开路状态(Open)。
- 电流采样模式:J5、J6 安装跳线,使电流采样信号连接到 ADC输入端。
- 过流保护:J2 设为 [2-3] 位置(跳线装在 pin2、pin3),使用软件过流保护。
- 限流阈值:J3 设为 [1-2] 位置(跳线装在 pin1、pin2),使用固定参考电压作为电流限制阈值。
-
将 12V/2A 直流电源连接到 NUCLEO-G431RB 控制板上的 CN1 连接端口(mini-USB),或连接到 X-NUCLEO-IHM16M1 电机驱动板上的 J4 连接器(电源插座),并通电(IHM03 套件中标配的云台电机的最大电压为12 VDC-youcans)。
通过上述硬件配置与连接方式,本章实验能够在保证安全和可控的前提下,获取具有工程意义的三相电流采样数据,为后续 FOC 控制实验提供可靠硬件基础。
2 技术原理
在 FOC 控制系统中,三相电流是坐标变换和电流闭环控制的直接输入,其采样结果由功率回路、电流采样电路以及 ADC 等多个硬件环节共同决定。
由于采样电路通常引入固定偏置和放大误差,即使在电流为零或条件相同的情况下,不同相位的采样结果也可能存在偏差。如果不对这些误差进行处理,误差将被进一步传递并放大,直接影响 FOC 控制的稳定性与性能。
本章通过分层实验的方式完成电流标定:
- 首先在不依赖电机旋转的条件下,对三相电流采样通道进行零点偏置测量并在软件中加以补偿;
- 随后在静态通流条件下对比三相电流采样结果,验证各相采样的一致性;
- 最后在低速运行条件下观测三相电流波形,确认标定结果在接近实际工况下依然有效。
通过上述过程,可在不引入完整 FOC 控制复杂度的前提下,确保三相电流采样数据具有足够的准确性与可靠性,为后续控制算法的实现提供可信输入。
说明:为与三相数学建模与坐标变换理论统一,本文使用 Ia / Ib / Ic 表示三相电流,与前文中的 Iu / Iv / Iw 在物理意义上是等价的。
3. CubeMX 配置
3.1 MCU 外设及其分工
"三相电流采样与标定"实验主要围绕电流的同步采样与数据获取展开,涉及的 STM32G431 片上外设及其分工如下:
-
高级定时器(TIM1)
用于生成三相互补 PWM 信号,驱动功率级形成三相电流;同时提供精确的硬件触发事件,用于触发 ADC 在指定时刻进行电流采样,保证采样时序与 PWM 周期严格同步。
-
模数转换器(ADC)
负责对三相电流采样电路输出的模拟电压进行转换,获取对应的数字量。本章通过配置 ADC 多通道采样,实现对 Ia、Ib、Ic 的连续采集,为电流标定与一致性验证提供数据基础。
-
DMA(可选)
用于在 ADC 转换完成后自动搬运采样数据,减少 CPU 干预,提高采样过程的实时性与稳定性。
-
GPIO(辅助)
用于实验过程中的调试与状态指示,例如使能控制、测试点输出或波形观测。
3.2 新建工程与系统配置
-
新建工程。
启动 STM32CubeMX,点击 "Start New Project"(或使用快捷键 Ctrl+N)新建工程,进入 New Project 界面。
选择 MCU 型号 STM32G431RBT6(与所使用开发板一致),或直接选择 NUCLEO-G431RB 开发板。
完成器件选择后,点击右上角 "Start Project" 创建工程,并将工程文件另存为:FOC_calib01.ioc。该工程将作为三相电流采样与标定实验的基础工程。 -
系统时钟配置。
点击顶部 "Clock Configuration" 选项卡,进入时钟树配置界面。本实验采用外部高速晶振(HSE)作为系统时钟源,并通过 PLL 将系统主频配置为 160 MHz。
主要时钟参数配置如下:
bash
Input frequency: 24 MHz (HSE)
SysCLK frequency: 160 MHz (HSE)
System Clock Mux: PLLCLK(youcans@qq.com)
AHB Prescaler: 1 (不分频)
APB1 Prescaler: 1
APB2 Prescaler: 1
配置完成后,System Clock、HCLK、PCLK1 与 PCLK2 均应显示为 160 MHz。
该配置为后续 PWM 生成与 ADC 高速采样提供充足的时钟裕量。
- 系统功能配置。
在 Pinout & Configuration 页面中,完成以下系统相关配置,确保系统以外部晶振为基准稳定运行。
-
(1)SYS 配置
- 调试器类型:Debug 模式设置为 Serial Wire,以支持 SWD 调试
- 基础时钟源:保持默认的 SysTick
-
(2)RCC 配置
- High Speed Clock (HSE) 设置为 Crystal/Ceramic Resonator
- Low Speed Clock (LSE) 设置为 Disable(本章实验不使用低速时钟)
- GPIO 基础配置
为便于实验调试与状态指示,配置以下基础 GPIO 资源:-
LD2(PA5)
配置为 GPIO_Output,用于程序运行状态指示或简单调试输出。
-
用户按键(PC13)
配置为 GPIO_EXTI13,作为外部中断输入,后续可用于实验控制或状态切换。
-
3.3 TIM 与 ADC 的配置
3.3.1 配置思路
在之前的实验中,已完成基于 TIM1 硬件触发的 ADC 注入组三相电流同步采样配置,并对其时序与稳定性进行了验证。为保持采样机制的一致性,本章实验中继续采用 ADC 注入组进行采样。
- 由高级定时器 TIM1 负责 PWM 生成与采样时序控制;
- 通过 TIM1 的比较事件或更新事件 作为 ADC 的硬件触发源;
- 使用 ADC 注入组 依次采样三相电流;
- 通过 硬件触发(而非软件触发),保证每次采样都发生在 PWM 周期中的固定位置。
这种配置方式可以避免采样时刻在 PWM 周期内随机漂移,从而确保在静态与动态条件下获得具有可比性的电流数据,为电流标定和后续 FOC 控制提供可靠基础。
3.3.2 定时器(TIM1)配置方案
在本章实验中,使用 STM32G431 的TIM1 高级定时器,实现 三相 PWM 生成 与 ADC 采样触发控制 这两项关键任务。通过将 TIM1 的 CH1/CH2/CH3 用于三相 PWM 输出、CH4 专用于 ADC 采样触发,构建了一种清晰、稳定且可扩展的定时器配置方案。
- PWM 输出通道配置(CH1、CH2、CH3)
TIM1 的 Channel 1、Channel 2 和 Channel 3 用于生成三相互补 PWM 信号,直接驱动功率级,形成三相电流通路。在 CubeMX 中,对 TIM1 的配置要点如下:
- 计数模式:设置为中心对齐模式(Center-aligned Mode),用于在 PWM 周期中部获得稳定的电流采样窗口。
- TRGO 模式:Update Event
- PWM 输出:
- 启用 CH1 / CH2 / CH3 及其互补通道 CH1N / CH2N / CH3N;
- 死区时间(Dead Time):根据功率器件特性配置合适的死区时间,防止功率器件直通;
- PWM 模式:PWM Mode 1
- 输出极性:保持默认或根据硬件需求配置
TIM1_CH4 的配置: - CH4 模式:PWM Generation No Output
- Pulse(CCR4):设置为 PWM 周期中部(例如 ARR/2),对应电流相对稳定的时刻
- Preload:Enable(推荐)
- ADC 采样触发通道配置(CH4)
为实现电流采样与 PWM 周期的严格同步,使用 TIM1_CH4 硬件触发 ADC 注入组采样,而不参与 PWM 输出。
当定时器计数器运行到 CCR4 所设定的位置时,将产生一次 Capture Compare 4(CC4)事件,该事件作为 ADC 注入组的外部触发源,用于启动一次三相电流采样序列。通过这种方式,可以在不改变三相 PWM 输出波形的前提下,灵活、精确地控制电流采样时刻。- 触发源:Timer 1 Catture Compare 4 event
TIM1 的详细配置参数,请参见《(4)PWM 硬件触发 ADC 同步采样》内容。
3.3.3 ADC 配置方案
在本章实验中,ADC1 用于完成三相电流的同步采样,并采用 注入组(Injected Group) 的方式进行转换,外部触发源配置为 Timer 1 Capture Compare 4 event(TIM1_CC4)。该配置方式已在前序实验中完成验证,能够在 PWM 驱动条件下实现采样时刻固定、时序可控的同步采样。
-
ADC 工作模式配置
在 CubeMX 中,对 ADC1 的基本工作模式配置如下:
- ADCs_Commeon_Settings:Independent mode
- Resolution:12-bit
- Data Alignment:Right
- Scan Conversion Mode:Enable(用于多通道注入采样)
- Continuous Conversion Mode:Disable
- Overrun:Preserve Data
-
注入组触发源配置
为保证电流采样与 PWM 周期严格同步,ADC 注入组采用 TIM1 的硬件事件作为外部触发源。
在 CubeMX 中,ADC 注入组触发方式配置为:
- Injected Conversion Mode:Enable
- Injected Trigger Source:Timer 1 Capture Compare 4 event (TIM1_CC4)
- Injected Trigger Edge:Trigger detection on the rising edge
- ADC Injected End of Conversion Interrupt:Enable
通过该配置,ADC 注入组将在 TIM1 产生指定触发事件时启动一次注入序列转换,确保每次采样都发生在 PWM 周期中的固定位置,从而避免采样相位在 PWM 周期内漂移。
-
注入组通道顺序配置
ADC 注入组用于采样三相电流信号 Ia、Ib、Ic。
为保证数据组织清晰、处理逻辑简单,注入组通道顺序在 CubeMX 中固定配置为:
- Number of Conversions: 3
- Injected Rank 1:Channel 2 (PA1, Ia)
- Injected Rank 2:Channel 12 (PB1, Ib)
- Injected Rank 3:Channel 15 (PB0, Ic)
所有通道采用相同的采样时间设置,以避免通道间由于采样时间不同而引入额外误差。
在每次注入触发到来时,ADC 将按照上述顺序依次完成三相电流的采样。
- 注入组中断与数据读取方式
ADC1 注入组转换完成后,通过 ADC 全局中断进入中断服务函数。
在 CubeMX 中需启用 ADC1 的 NVIC 全局中断:在 NVIC Settings 页面中,勾选 ✅ ADC1 and ADC2 global interrupt。HAL 库将在注入组转换完成时调用 HAL_ADCEx_InjectedConvCpltCallback() 回调函数,用于读取注入组采样结果。
ADC 的详细配置参数,请参见《(4)PWM 硬件触发 ADC 同步采样》内容。
3.4 工程配置
- 工程管理配置。
(1)点击 "Project Manager"→ "Project",输入项目名称 "FOC_calib01.ioc"。
(2)点击 "Project Manager"→ "Code Generator",设置如下。
bash
Project:
- Project Name: FOC_calib01.ioc
- Toolchain/IDE: STM32CubeIDE
Code Generator:
√ Generate peripheral initialization as a pair of '.c/.h'
√ Keep User Code when re-generating
√ Backup previously generated files
youcans@qq.com
4. 三相电流数据结构与变量命名规范
本文采用"原始采样值 raw → 偏置补偿 off → 物理量 i"的三级变量体系,并保持 a/b/c 相与注入组 Rank 顺序一致。
-
通道与相位的对应关系
Injected Rank 1 → Ia
Injected Rank 2 → Ib
Injected Rank 3 → Ic
-
变量命名约定
(1)原始 ADC 采样值(未处理):ia_raw, ib_raw, ic_raw:三相原始采样值(ADC 码值,uint16_t)
(2)零点偏置(Offset)的码值:ia_off, ib_off, ic_off:三相零点偏置(建议用 int32_t 保存均值结果)
(3)补偿后的码值:ia_adc, ib_adc, ic_adc:扣除偏置后的采样码值(建议 int32_t,允许出现正负)
(4)物理电流值(可选,单位 A):ia, ib, ic:三相电流(float,单位 A)
-
数据结构(结构体 + 数组并存)
为了兼顾可读性与可扩展性,建议字段划分如下(概念层面,后续代码中实现即可):
- raw[3]:ADC 原始值
- off[3]:偏置(标定值)
- adc[3]:补偿后码值
- i[3]:电流物理量(可选)
- tick/sample_id:采样序号(用于日志与波形对齐)
- flag_new:新数据标志(主循环/日志读取用)
5. 实验 6-1:三相电流零点标定
实验目的:测量并补偿三相电流采样的零点偏置
三相电流采样链路通常包含采样电阻、运放(或电流传感器)与 ADC 等环节,即使实际电流为 0,ADC 也可能读到非零值(零点偏置/Offset)。本实验的目的就是在"理论电流为零"的条件下测得三相采样通道的偏置,并在软件中进行补偿,为后续一致性验证与电流环控制提供可靠基础。
实验条件:
- 硬件连接:控制板 + 功率级 + 电机负载均已连接(形成真实采样通路)。
- 电机状态:本实验不要求电机旋转。
- PWM 状态:关闭 PWM 输出,或将占空比设为 0,确保功率级不向电机施加有效电压。
- 采样触发:ADC1 注入组由 TIM1_CC4 硬件触发。
- 安全建议:首次上电建议限流/低母线电压,并确认功率级使能逻辑正确。
实验内容:
- 连续采样 Ia / Ib / Ic:在"电流为零"的状态下,连续采集一段时间的三相电流 ADC 原始值 ia_raw/ib_raw/ic_raw;
- 计算三相电流的偏置量:对每一相分别求平均值(或中位数/均值滤波)得到偏置 ia_off/ib_off/ic_off;
- 在软件中进行偏置补偿:后续每次采样都执行 i a d c = i r a w − i o f f i_{adc}=i_{raw} − i_{off} iadc=iraw−ioff,得到扣除偏置后的电流码值 ia_adc/ib_adc/ic_adc(允许正负)。
参考代码:
- 参数和变量定义
c
// 固定索引:0->A, 1->B, 2->C
#define PH_A 0
#define PH_B 1
#define PH_C 2
#define N_PHASE 3
volatile uint16_t iabc_raw[N_PHASE]; // ADC原始采样
volatile int32_t iabc_off[N_PHASE]; // 偏置(标定结果)
volatile int32_t iabc_adc[N_PHASE]; // 扣偏置后的码值
static volatile int64_t sum_off[N_PHASE];
static volatile uint32_t cnt_off;
static volatile uint8_t calib_done;
- 回调函数
c
/**
* @brief ADC1 注入组转换完成回调(JEOC)
* @note 触发源:TIM1_CC4;注入Rank顺序:Rank1->Ia, Rank2->Ib, Rank3->Ic
*/
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
/* 只处理 ADC1 */
if (hadc->Instance != ADC1) return;
/* 1) 读取注入组 3 个 Rank 的值(顺序必须与 CubeMX 配置一致) */
iabc_raw[PH_A] = (uint16_t)HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);
iabc_raw[PH_B] = (uint16_t)HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);
iabc_raw[PH_C] = (uint16_t)HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);
/* 2) 若标定未完成:累加求均值 */
if (!calib_done)
{
sum_off[PH_A] += (int64_t)iabc_raw[PH_A];
sum_off[PH_B] += (int64_t)iabc_raw[PH_B];
sum_off[PH_C] += (int64_t)iabc_raw[PH_C];
cnt_off++;
if (cnt_off >= OFFSET_CALIB_SAMPLES)
{
/* 用整除求均值即可(如需更稳健可用中位数/去极值平均) */
iabc_off[PH_A] = (int32_t)(sum_off[PH_A] / (int64_t)cnt_off);
iabc_off[PH_B] = (int32_t)(sum_off[PH_B] / (int64_t)cnt_off);
iabc_off[PH_C] = (int32_t)(sum_off[PH_C] / (int64_t)cnt_off);
calib_done = 1;
}
}
/* 3) 正常运行:扣偏置(标定完成后才有严格意义,但提前做也无妨) */
iabc_adc[PH_A] = (int32_t)iabc_raw[PH_A] - iabc_off[PH_A];
iabc_adc[PH_B] = (int32_t)iabc_raw[PH_B] - iabc_off[PH_B];
iabc_adc[PH_C] = (int32_t)iabc_raw[PH_C] - iabc_off[PH_C];
/* 4) 新数据标志:通知主循环/日志模块读取 */
flag_new = 1;
}
- 主程序 main.c 关于标定的关键代码:
c
/* USER CODE BEGIN 2 */
printf("\r\n=== Exp6-1 Current Offset Calibration (ADC Injected, TIM1_CC4) ===\r\n");
// 1) 启动 TIM1_CH4 用于产生ADC触发事件,暂不启动CH1~CH3
HAL_TIM_Base_Start( &htim1); // 启动定时器计数
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
// 2) 启动 ADC1 注入组(外部触发 + 中断方式)
if (HAL_ADCEx_InjectedStart_IT(&hadc1) != HAL_OK) {
printf("ERROR: ADC Injected Start IT failed!\r\n");
Error_Handler();
}
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_JEOC);
// __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,4000); // TIM1_CH4 三角波触发 ADC1 采样
HAL_Delay(100);
// 3) 开始标定(清零累加器)
for (int k = 0; k < N_PHASE; k++) sum_off[k] = 0;
cnt_off = 0;
calib_done = 0;
printf("Calibrating... please keep current = 0\r\n");
// 等待标定完成(calib_done 在 JEOC 回调里置1)
while (!calib_done)
{
// 闪灯提示正在标定
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_Delay(50);
}
printf("Calib done.\r\n");
printf("Offset: ia_off=%ld, ib_off=%ld, ic_off=%ld\r\n",
(long)iabc_off[PH_A], (long)iabc_off[PH_B], (long)iabc_off[PH_C]);
/* USER CODE END 2 */
// 4) 补偿效果观测:统计补偿后均值和峰值
/* Infinite loop */
while (1)
{
int32_t mean[3] = {0};
int32_t vmin[3] = { 2147483647, 2147483647, 2147483647};
int32_t vmax[3] = { -2147483647, -2147483647, -2147483647};
const uint32_t M = 1000; // 统计1000组(取决于触发频率)
for (uint32_t n = 0; n < M; n++)
{
// 等待新数据(flag_new在回调中置1)
while (!flag_new) {}
flag_new = 0;
for (int k = 0; k < 3; k++)
{
int32_t x = iabc_adc[k];
mean[k] += x;
if (x < vmin[k]) vmin[k] = x;
if (x > vmax[k]) vmax[k] = x;
}
}
for (int k = 0; k < 3; k++) mean[k] /= (int32_t)M;
printf("Compensated ADC: mean=[%ld,%ld,%ld], p2p=[%ld,%ld,%ld]\r\n",
(long)mean[0], (long)mean[1], (long)mean[2],
(long)(vmax[0]-vmin[0]), (long)(vmax[1]-vmin[1]), (long)(vmax[2]-vmin[2]));
HAL_Delay(500);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
实验结果
运行程序,通过串口调试助手接收输出数据如下。
bash
=== Exp6-1 Current Offset Calibration (ADC Injected, TIM1_CC4) ===
Calibrating... please keep current = 0
Calib done.
Offset: ia_off=1893, ib_off=1896, ic_off=1904
Compensated ADC: mean=[0,0,0], p2p=[10,5,6]
Compensated ADC: mean=[0,0,0], p2p=[10,5,6]
Compensated ADC: mean=[0,0,0], p2p=[10,5,6]
Compensated ADC: mean=[0,0,0], p2p=[10,5,5]
Compensated ADC: mean=[0,0,0], p2p=[9,4,5]
...

实验结果表明:
- 得到三相偏置参数:ia_off=1893, ib_off=1896, ic_off=1904。三相偏置接近、差异很小,符合真实电流为零时"通道偏置略有不同"的典型情况。Offset 在 1900 左右,说明电流采样电路带了中点偏置。
- 补偿后零点的稳定性:补偿后均值为 0(mean=[0,0,0])。说明在后续每次采样都进行了偏置补偿,并且统计窗口足够大,使得均值收敛到 0。
- 补偿后只有小幅噪声(p2p 很小),说明残余波动主要是 ADC + 模拟前端噪声,而不是残余直流偏置或错误触发。
结果分析:
- 本实验得到的 iabc_off 是后续所有电流相关计算的"基础校正参数"。在后续实验以及电流环控制中,必须在每次采样后执行偏置补偿(推荐直接在 JEOC 回调中处理):
c
ia_adc = ia_raw - ia_off
ib_adc = ib_raw - ib_off
ic_adc = ic_raw - ic_off
-
偏置参数的保存
(1)在教学/实验中,可以每次上电都做一次零点标定。简单可靠,可以自动适应温漂。
(2)在产品化中,推荐上电标定一次后保存(Flash/EEPROM),运行中只做小幅更新,启动速度更快。
-
单位换算。
电流环最终需要电流单位一致(通常用 A)。可以增加如下代码实现:
c
i[A] = i_adc * adc_to_amp
其中 adc_to_amp 由采样电阻、运放增益、ADC 参考电压共同决定。
6. 小结:
本实验在零电流条件下测得三相采样通道的零点偏置分别为 1893、1896、1904(LSB),三相偏置差异很小,表明采样链路一致性良好。扣除偏置后,三相电流码值均值收敛至 0,峰峰值波动在 4~10 LSB 范围内,主要反映 ADC 与模拟前端噪声水平。后续所有电流相关计算(通流一致性验证、波形观测、坐标变换与电流环控制)均应基于补偿后的电流数据进行。
后记:
- 本打算在这篇把 3个实验都写完,看来有些长了,另外两个实验后文再补充吧。
- 本项目开源,需要项目资源的读者请留言。
版权声明:
【动手学电机驱动】是 youcans@qq 原创作品,转载必须标注原文链接: 【STM32G4-FOC】(6)三相电流采样与标定(https://blog.csdn.net/youcans/article/details/157504296)
Copyright@youcans 2026
Crated:2026-1