目录

1. 引言

2. 霍尔信号特性与测速原理

2.1 霍尔传感器输出特性

2.2 转速测量基本方程

2.3 固定时间窗口测速公式

3. 硬件接口设计

3.1 引脚分配与定时器选型

3.2 抗干扰设计要点

4. 定时器配置策略

4.1 时基参数计算

4.2 输入捕获通道参数

4.3 中断使能与溢出处理

5. 软件实现

5.1 数据结构与全局变量

5.2 初始化函数

5.3 中断服务与回调实现

5.4 主循环中转速计算

6. 实验结果与讨论

6.1 测试条件

6.2 测速精度

6.3 实时性分析

6.4 瞬时法与固定窗口法对比

7. 工程注意事项


针对直流无刷电机(BLDC)在工业控制中对转速测量的实时性与精度要求,提出一种基于STM32G4系列微控制器高级定时器输入捕获功能的霍尔传感器测速方案。本文首先分析霍尔传感器输出信号特性与电机转子机械角度的关系,推导基于电周期的转速计算公式;其次,详细阐述定时器时基参数、双边沿捕获、数字滤波及溢出补偿的配置方法;然后,给出基于HAL库的完整驱动代码,包括初始化、中断服务与溢出处理机制;最后,通过实验验证测速误差在±0.3%以内,并对比瞬时法与固定窗口法的适用场景。本文方法具有硬件资源占用少、实时性强、抗干扰能力好的特点,适用于BLDC电机驱动中的闭环速度控制。

关键词:STM32G4;输入捕获;霍尔传感器;BLDC;测速;定时器中断


1. 引言

直流无刷电机(BLDC)凭借其高效率、低维护成本和良好的调速性能,在电动工具、机器人、无人机及电动汽车等领域得到广泛应用。转速的精确获取是实现闭环速度控制的关键前提。常见的测速方案包括光电编码器、磁编码器及霍尔传感器。其中,霍尔传感器因成本低、结构简单、对恶劣环境适应性强,成为中低端BLDC驱动的首选位置/速度反馈元件。

STM32G4系列MCU基于Arm Cortex-M4内核,集成了多个高级控制定时器,其输入捕获功能可精确记录外部事件的时间戳,为霍尔信号测速提供了高效的硬件支持。然而,实际工程应用中常面临以下挑战:

  1. 霍尔信号易受功率级开关噪声干扰,导致边沿误触发;

  2. 低速时相邻霍尔跳变间隔长,16位定时器易溢出;

  3. 中断优先级配置不当会引发系统死锁;

  4. 不同测速策略(瞬时法/窗口法)对动态响应与稳态精度影响不同。

本文针对上述问题,提出一套完整的解决方案,包含硬件接口设计、定时器参数优化、溢出补偿算法、中断优先级管理及软件滤波机制,旨在实现宽速域(100~3000 RPM)内的高精度、高鲁棒性转速测量。


2. 霍尔信号特性与测速原理

2.1 霍尔传感器输出特性

BLDC电机内部通常安装三个开关型霍尔传感器(H_U、H_V、H_W),空间互差120°电角度。当转子永磁磁场穿过霍尔元件时,传感器输出低电平(导通);反之输出高电平(截止)。由于采用开漏输出,外部必须配置上拉电阻(典型值4.7kΩ~10kΩ)以产生有效逻辑电平。

三个霍尔信号的组合状态构成3位二进制编码,共6种有效状态,对应一个电周期内的6个换相区间。转子每转过一对磁极(即一个电周期),霍尔状态序列完整循环一次。设电机极对数为 p,则转子机械旋转一周时,霍尔状态变化次数为 6p,每个霍尔通道输出 p 个完整的脉冲周期。

2.2 转速测量基本方程

此即基于瞬时电周期测量的转速计算公式。实际操作中可取任意霍尔通道的同极性边沿(如两次上升沿)获得 C,然后代入式(1)即可得到瞬时转速。

2.3 固定时间窗口测速公式

对于低速工况,相邻霍尔边沿间隔大,采用瞬时法时转速更新慢且易受单次测量噪声影响。此时可改用固定时间窗口计数法:在预设时间 Tw​(如10 ms)内,统计所有霍尔通道发生的总跳变次数 N。由于机械旋转一周总跳变次数为 6p,故转速为:

3. 硬件接口设计

3.1 引脚分配与定时器选型

本方案选用TIM1的三个通道(CH1、CH2、CH3)分别连接霍尔信号H_U、H_V、H_W。TIM1为高级控制定时器,支持16位计数、双边沿捕获及硬件数字滤波,且其更新中断可用于溢出补偿。具体引脚复用配置见表1。

霍尔信号 TIM1 通道 引脚 复用功能
HALL_U CH1 PA8 AF6
HALL_V CH2 PA9 AF6
HALL_W CH3 PA10 AF6

3.2 抗干扰设计要点

霍尔信号线应远离三相动力线,避免平行长距离走线。建议在MCU引脚附近对地并联100 nF电容,并在PCB上采用信号线两侧包地处理。此外,定时器内置的数字滤波器可有效抑制窄脉冲毛刺,滤波参数选择4~6个采样时钟周期。


4. 定时器配置策略

4.1 时基参数计算

系统时钟配置为170 MHz,TIM1挂载于APB2总线(时钟频率170 MHz)。为获得足够的时间分辨率并覆盖低速测量范围,设定:

4.2 输入捕获通道参数

每个霍尔通道需配置为双边沿捕获,以捕捉任何极性变化。使用STM32CubeMX进行配置时,参数如下:

参数项 设置值 说明
Polarity Selection TIM_ICPOLARITY_BOTHEDGE 上升沿和下降沿均触发捕获
IC Selection TIM_ICSELECTION_DIRECTTI 直接连接至TIx引脚
IC Prescaler TIM_ICPSC_DIV1 不分频
IC Filter 6 数字滤波,采样频率 fDTSfDTS​,连续6次有效才确认边沿

数字滤波的具体值应根据实际噪声频率调整,一般取4~6可有效滤除200 ns以内的毛刺。

4.3 中断使能与溢出处理

  • 使能TIM1的捕获中断(TIM1_CC_IRQn)和更新中断(TIM1_UP_IRQn,与Break/Trigger/COM共用向量)。

  • 设置中断优先级:捕获中断优先级为5,更新中断优先级也为5(或略高,如4),但必须确保两者均低于SysTick(默认15),防止HAL_Delay死锁。

  • 启动定时器前,务必清除所有挂起的标志位:

__HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_UPDATE);
NVIC_ClearPendingIRQ(TIM1_CC_IRQn);
NVIC_ClearPendingIRQ(TIM1_UP_IRQn);

5. 软件实现

5.1 数据结构与全局变量

typedef struct {
    uint32_t last_cnt;          // 上次捕获的计数值
    uint32_t curr_cnt;          // 本次捕获的计数值
    uint32_t overflow_cnt;      // 两次捕获间发生的更新溢出次数
    uint32_t delta_t;           // 时间间隔(单位:μs)
    float speed_rpm;            // 计算得到的转速(RPM)
    uint8_t new_data;           // 新数据标志
} HallSpeed_HandleTypeDef;

HallSpeed_HandleTypeDef hhall[3];   // 索引0:U相, 1:V相, 2:W相
volatile uint16_t tim1_overflow = 0; // 更新中断累计溢出次数

5.2 初始化函数

void MX_TIM1_Hall_Init(void)
{
    // 1. 时钟使能
    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // 2. GPIO配置 (PA8, PA9, PA10 → AF6)
    GPIO_InitTypeDef gpio = {0};
    gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
    gpio.Mode = GPIO_MODE_AF_PP;
    gpio.Pull = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_LOW;
    gpio.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(GPIOA, &gpio);

    // 3. TIM1时基配置
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_IC_InitTypeDef sConfigIC = {0};

    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 169;         // 1 MHz计数频率
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = 65535;           // 满量程
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_IC_Init(&htim1);

    // 4. 时钟源选择
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);

    // 5. 捕获通道配置(以CH1为例)
    sConfigIC.ICPolarity = TIM_ICPOLARITY_BOTHEDGE;
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
    sConfigIC.ICFilter = 6;
    HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);
    HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2);
    HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_3);

    // 6. 主从模式(可选,本例不使用复位模式)
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

    // 7. 中断优先级与清除标志
    HAL_NVIC_SetPriority(TIM1_CC_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
    HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_UPDATE);
    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);
    NVIC_ClearPendingIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
}

5.3 中断服务与回调实现

更新中断回调(溢出计数):

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM1) {
        tim1_overflow++;
    }
}

捕获中断回调(以U相为例):

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance != TIM1) return;

    uint32_t cnt = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
    HallSpeed_HandleTypeDef *pHall = &hhall[0];  // U相

    if (pHall->last_cnt == 0) {
        pHall->last_cnt = cnt;
        return;
    }

    pHall->curr_cnt = cnt;
    // 计算时间间隔,考虑溢出
    if (pHall->curr_cnt >= pHall->last_cnt) {
        pHall->delta_t = (pHall->curr_cnt - pHall->last_cnt) + (tim1_overflow * 65536);
    } else {
        pHall->delta_t = (pHall->curr_cnt + 65536 - pHall->last_cnt) + (tim1_overflow * 65536);
    }
    pHall->last_cnt = pHall->curr_cnt;
    pHall->overflow_cnt = tim1_overflow;
    tim1_overflow = 0;          // 重置溢出计数器
    pHall->new_data = 1;        // 通知主循环计算转速
}

V相和W相的处理逻辑相同,只需修改通道号和结构体索引即可。

5.4 主循环中转速计算

void CalculateSpeedFromHall(void)
{
    const uint32_t timer_freq = 1000000;   // 1 MHz -> 1 μs per count
    const uint8_t pole_pairs = 4;           // 8极电机

    for (int i = 0; i < 3; i++) {
        if (hhall[i].new_data) {
            hhall[i].new_data = 0;
            if (hhall[i].delta_t > 0) {
                // 公式 (1): RPM = 60e6 / (p * delta_t)
                hhall[i].speed_rpm = 60000000.0f / (pole_pairs * hhall[i].delta_t);
            } else {
                hhall[i].speed_rpm = 0.0f;
            }
        }
    }
}

为提高低速稳定性,可对三个通道的转速值进行滑动平均或中值滤波。


6. 实验结果与讨论

6.1 测试条件

  • MCU:STM32G431RBT6,主频170 MHz

  • 电机:8极BLDC(极对数p=4),额定转速3000 RPM

  • 霍尔传感器:US5881,上拉电阻10kΩ

  • 定时器计数频率:1 MHz

  • 测速方法:瞬时法(相邻同相上升沿间隔)

6.2 测速精度

使用高精度激光转速表(精度±1 RPM)作为参考,对比结果如表2所示。

设定转速 (RPM) 实测转速 (RPM) 绝对误差 (RPM) 相对误差 (%)
100 100.2 +0.2 0.20
500 499.4 -0.6 0.12
1000 999.1 -0.9 0.09
2000 2003.5 +3.5 0.18
3000 2996.2 -3.8 0.13

误差主要来源于霍尔元件安装位置偏差及电机转速波动,硬件捕获本身的量化误差为±1 μs(对应转速误差<0.05%)。

6.3 实时性分析

捕获中断服务程序执行时间约为1.2 μs(包括读取CCR、计算delta_t及标志操作),远小于最坏情况下的霍尔间隔(3000 RPM时约为300 μs)。因此不会对主循环造成明显阻塞。

6.4 瞬时法与固定窗口法对比

测速方法 响应时间 低速噪声 适用场景
瞬时法 一个电周期(≤10 ms@1000 RPM) 较大 中高速闭环控制
窗口法 (10 ms) 10 ms 固定延时 平滑 低速显示、速度环前馈

建议采用混合策略:当瞬时转速低于阈值(如300 RPM)时自动切换至窗口法,并启用一阶低通滤波器。


7. 工程注意事项

  1. 霍尔上拉电阻:必须确认硬件上是否存在上拉电阻,否则信号浮空导致误触发。

  2. 中断优先级:捕获与更新中断优先级不得高于SysTick(数值≥5),避免HAL_Delay死锁。

  3. 溢出补偿:若最大电周期超过65535 μs(对应转速低于229 RPM@p=4),必须启用更新中断并累加溢出次数。

  4. 滤波与去抖:数字滤波器可滤除大部分噪声;若仍有异常跳变,可在软件中增加边沿有效性判断(如最小间隔检查)。

  5. 极对数的准确获取:错误设置极对数将导致转速成比例偏差。可通过手动旋转电机一圈并记录霍尔状态变化次数来测定。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐