电机驱动开发学习7. 编码器的使用
- 一、编码器介绍
-
- [1. 什么是编码器](#1. 什么是编码器)
-
- [1.1 工作原理](#1.1 工作原理)
- [1.2 在 BLDC 系统中的两类位置反馈](#1.2 在 BLDC 系统中的两类位置反馈)
- [1.3 野火驱动板「编码器接口」](#1.3 野火驱动板「编码器接口」)
- [2. 编码器的分类](#2. 编码器的分类)
-
- [2.1 按工作原理分类](#2.1 按工作原理分类)
- [2.2 霍尔传感器(换相用,本实验借其测速)](#2.2 霍尔传感器(换相用,本实验借其测速))
- [2.3 本实验配置(霍尔测速,非外接编码器)](#2.3 本实验配置(霍尔测速,非外接编码器))
- [2.4 测速的两种方式:M 法与 T 法](#2.4 测速的两种方式:M 法与 T 法)
-
- [(1)M 法(频率法 / 测频法)](#(1)M 法(频率法 / 测频法))
- [(2)T 法(周期法 / 测周法)](#(2)T 法(周期法 / 测周法))
- 二、霍尔传感器测速与位置反馈原理
-
- [1. 霍尔信号与换相状态](#1. 霍尔信号与换相状态)
- [2. 转速测量原理](#2. 转速测量原理)
-
- [2.1 从一次跳变到 RPM 的推导](#2.1 从一次跳变到 RPM 的推导)
- [2.2 代入本工程参数](#2.2 代入本工程参数)
- [2.3 公式中各因子的物理含义](#2.3 公式中各因子的物理含义)
- [3. 位置与方向](#3. 位置与方向)
- [三、TIM5 Hall 接口配置](#三、TIM5 Hall 接口配置)
-
- [1. 引脚与定时器](#1. 引脚与定时器)
- [2. Hall 模式工作机制](#2. Hall 模式工作机制)
- 四、软件实现
-
- [1. 关键宏定义(`bsp_motor_tim.h`)](#1. 关键宏定义(
bsp_motor_tim.h)) - [2. 霍尔反馈 API](#2. 霍尔反馈 API)
- [3. 触发回调核心逻辑](#3. 触发回调核心逻辑)
- [4. 波形帧扩展(`bsp_adc.c`)](#4. 波形帧扩展(
bsp_adc.c)) - [5. 主循环(`main.c`)](#5. 主循环(
main.c))
- [1. 关键宏定义(`bsp_motor_tim.h`)](#1. 关键宏定义(
- 五、实验操作与现象
-
- [1. 接线](#1. 接线)
- [2. 串口控制](#2. 串口控制)
- [3. 输出数据](#3. 输出数据)
- [4. 调试提示](#4. 调试提示)
- 六、小结
本系列教程学习资源来自野火官方电机教程,部分代码及博客内容摘自官方教程。本系列教程使用野火骄阳 F407 开发板及野火有刷/无刷驱动板。
在上一篇(lesson6)中,我们完成了三相电流采集、软件过流保护。本篇在 lesson6 基础上,利用 TIM5 霍尔接口 ,实现电机转速、位置、方向 的测量,并与温度、电压、电流合并为 22 字节同一帧输出。

概念说明
- 霍尔传感器 :电机内部 U/V/W(HU/HV/HW) ,仅 6 个离散状态,首要用途是六步换相 ,精度远低于编码器。
本实验配套电机只有霍尔、没有另装光电编码器 ;代码沿用野火官方例程,借霍尔跳变间隔估算转速,属于低成本速度反馈。下文先介绍真正的编码器,再说明本实验实际用的是霍尔。
一、编码器介绍
1. 什么是编码器
编码器(Encoder)是一种将机械位移(角位移或直线位移)转换为电信号的传感器,用于测量电机的转速、位置和方向。在伺服、FOC 等闭环控制中,专用编码器是核心反馈元件。
1.1 工作原理
编码器通过检测转轴旋转,输出脉冲或数字码。控制器可得到:
- 转速:单位时间内的脉冲数(或捕获周期)
- 位置:累计脉冲数(增量式)或绝对码(绝对式)
- 方向:A/B 正交相位,或绝对码变化趋势
1.2 在 BLDC 系统中的两类位置反馈
| 类型 | 典型信号 | 分辨率 | 主要用途 |
|---|---|---|---|
| 增量式/绝对式编码器 | A、B、Z(EA/EB/EZ) | 高(数百~数千线/转) | 速度环、位置环、FOC 电角度 |
| 霍尔传感器 | HU、HV、HW | 低(6 状态/电周期) | 六步换相、堵转检测、粗测速 |
二者不要混称。霍尔不是编码器 ;口语里的「霍尔编码器」容易误导,工程上应称 霍尔位置传感器 或 换相霍尔。
1.3 野火驱动板「编码器接口」
驱动板编码器接口(J4)经光耦隔离后接到 MCU,原理图信号双命名:
| 端子信号 | 接增量式编码器时 | 接本电机霍尔线时 |
|---|---|---|
| EA | A 相脉冲 | HU |
| EB | B 相脉冲 | HV |
| EZ | Z 相零位脉冲 | HW |
J3 跳线可选 5 V / 12 V 给外设供电。若外接 2500 线增量编码器 ,应使用 TIM 编码器模式 对 EA/EB 计数;本系列 lesson4~7 配套电机只接霍尔线,未使用外接编码器。
2. 编码器的分类
2.1 按工作原理分类
(1)光电增量式编码器(本接口可外接的类型)

- 原理:码盘透光/遮光,输出 A、B 正交方波 + Z 零位脉冲
- 特点:分辨率高、适合速度/位置闭环
- MCU 用法 :
HAL_TIM_Encoder_Init(),对 A/B 边沿计数 - 应用:野火 FOC 例程、伺服、CNC
(2)绝对式编码器
- 每个机械角对应唯一码值,断电保持
- 成本高,用于高精度定位
(3)磁编码器
- 磁阻/霍尔阵列,精度介于霍尔开关与光电编码器之间
- 与电机内 3 个换相霍尔不是同一类器件
2.2 霍尔传感器(换相用,本实验借其测速)

- 原理:3 个开关型霍尔检测转子磁场,组合为 6 个有效状态(每 60° 电角度)
- 首要作用:确定换相时刻(lesson4 已用)
- 本实验附加作用:用 TIM5 Hall 模式捕获跳变间隔 → 估算 RPM、累计扇区位置
- 局限 :机械一圈仅 12 次 跳变(2 对极 × 6 状态),不能做精确定位
- 引脚:PH10(HU)、PH11(HV)、PH12(HW)
2.3 本实验配置(霍尔测速,非外接编码器)
| 参数 | 配置值 |
|---|---|
| 传感器 | 电机内置霍尔 HU/HV/HW(非外接 EA/EB/EZ 编码器) |
| 主要功能 | 换相 + 借跳变测速/方向/粗位置 |
| 定时器 | TIM5(Hall Sensor 模式,非 Encoder 模式) |
| 预分频系数 | 128 |
| 计数周期 | 0xFFFF (65535) |
| 输入滤波 | IC1Filter = 10 |
| 中断优先级 | 0 (最高) |
| 换相状态数 | 6 个有效状态 |
霍尔 3 路组合成状态 1~6,既用于 bldcm_commutate() 换相,也在 HAL_TIM_TriggerCallback() 中更新 RPM/POS/DIR。
2.4 测速的两种方式:M 法与 T 法
无论信号来自光电编码器脉冲 还是霍尔跳变 ,测转速的常用思路都可以归纳为两类。野火《电机应用开发实战指南》编码器章节对二者有完整介绍;本实验的霍尔测速属于其中的 T 法。
(1)M 法(频率法 / 测频法)
思路 :在固定时间窗口 (T_0) 内,统计传感器输出的脉冲(或霍尔跳变)个数 (M_0),用「单位时间内的脉冲数」换算转速。
对增量式编码器,设单圈总脉冲数为 (C)(含倍频后的计数,如 600 线 4 倍频则 (C=2400)),则:
n = 60 ⋅ M 0 C ⋅ T 0 n = \frac{60 \cdot M_0}{C \cdot T_0} n=C⋅T060⋅M0
对本电机霍尔,机械转一圈共 12 次 跳变((C_{hall}=12)),若在 ( T 0 = 0.05 s ) (T_0=0.05\,\text{s}) (T0=0.05s) 内测得 (M_0=5) 次跳变,则:
R P M = 60 × 5 12 × 0.05 = 500 RPM = \frac{60 \times 5}{12 \times 0.05} = 500 RPM=12×0.0560×5=500
特点:
| 优点 | 缺点 |
|---|---|
| 实现简单,主循环里计数即可 | 低速时 (T_0) 内脉冲很少,误差大、波动大 |
| 高速时 (M_0) 大,相对平稳 | 结果有 (T_0) 量级的滞后(需等窗口结束才更新) |
伪代码示例(本工程未采用,仅供对比):
c
/* 每 50 ms 统计一次霍尔跳变次数 delta_pos */
rpm = (60UL * delta_pos) / (12UL * T0_SEC);
(2)T 法(周期法 / 测周法)
思路 :测量相邻两次传感器事件之间的时间间隔 (T_e)(或等价地,用定时器捕获计数值 (N)),由「转一圈需要多久」反推转速。
对编码器: ( n = 60 C ⋅ T e ) (n = \dfrac{60}{C \cdot T_e}) (n=C⋅Te60)。
对本实验霍尔:每次跳变对应 60° 电角度,相邻跳变间隔 (T_{step}) 与 CCR1 捕获值 (N) 的关系见 §2.1,最终:
R P M = 60 ⋅ f t i m 6 ⋅ P p ⋅ P S C ⋅ N RPM = \frac{60 \cdot f_{tim}}{6 \cdot P_p \cdot PSC \cdot N} RPM=6⋅Pp⋅PSC⋅N60⋅ftim
特点:
| 优点 | 缺点 |
|---|---|
| 低速时 (T_e) 长,单次测量相对更准 | 高速时 (T_e) 极短,捕获分辨率受限,误差变大 |
| 每来一次跳变即可更新,响应快 | 对噪声、抖动更敏感,需滤波(如 IC1Filter、最小捕获阈值) |
本工程在 HAL_TIM_TriggerCallback() 中读取 CCR1,即 T 法;TIM5 Hall 硬件在每次霍尔变化时自动锁存间隔,无需在主循环里开固定窗口。
二、霍尔传感器测速与位置反馈原理
1. 霍尔信号与换相状态
本电机内置 3 个霍尔传感器(HU、HV、HW),5V 供电,2 对极。三路信号按位组合成 6 个有效状态(排除 000 与 111):
| 状态值 | HU | HV | HW | 电角度区间 |
|---|---|---|---|---|
| 1 | 0 | 0 | 1 | 0° ~ 60° |
| 3 | 0 | 1 | 1 | 60° ~ 120° |
| 2 | 0 | 1 | 0 | 120° ~ 180° |
| 6 | 1 | 1 | 0 | 180° ~ 240° |
| 4 | 1 | 0 | 0 | 240° ~ 300° |
| 5 | 1 | 0 | 1 | 300° ~ 360° |
正转时状态按 1 → 3 → 2 → 6 → 4 → 5 → 1 循环;反转则相反。机械转一圈(360° 机械角)共产生 12 次霍尔跳变(6 状态 × 2 对极)。
2. 转速测量原理
STM32 的 Hall Sensor 模式 将 HU/HV/HW 异或后接入 TIM5 通道 1。每当霍尔组合变化,定时器将两次跳变之间的计数值 锁存到 CCR1 并清零计数器。该计数值对应 60° 电角度 的旋转时间。
2.1 从一次跳变到 RPM 的推导
第一步:确定单次跳变对应的时间
本工程 TIM5 配置为:
- 定时器计数时钟 (f_{tim} = 84,\text{MHz})(系统 168 MHz,APB1 四分频得 42 MHz,定时器倍频后为 84 MHz)
- 预分频寄存器写入
128 - 1,实际分频系数 (PSC = 128) - 每次霍尔跳变捕获到的计数值为 (N)(即 CCR1)
计数器每加 1 所需时间为:
T c n t = P S C f t i m T_{cnt} = \frac{PSC}{f_{tim}} Tcnt=ftimPSC
相邻两次霍尔跳变的时间间隔(即转子转过 60° 电角度所需时间)为:
T s t e p = N ⋅ T c n t = N ⋅ P S C f t i m T_{step} = N \cdot T_{cnt} = \frac{N \cdot PSC}{f_{tim}} Tstep=N⋅Tcnt=ftimN⋅PSC
第二步:电周期与电频率
BLDC 电机每 60° 电角度对应一次霍尔状态变化,一个完整电周期(360° 电角度)包含 6 次跳变:
T e = 6 ⋅ T s t e p = 6 ⋅ N ⋅ P S C f t i m T_e = 6 \cdot T_{step} = \frac{6 \cdot N \cdot PSC}{f_{tim}} Te=6⋅Tstep=ftim6⋅N⋅PSC
电频率(每秒转过的电周期数)为:
f e = 1 T e = f t i m 6 ⋅ N ⋅ P S C f_e = \frac{1}{T_e} = \frac{f_{tim}}{6 \cdot N \cdot PSC} fe=Te1=6⋅N⋅PSCftim
第三步:电频率换算为机械转速
本电机极对数 (P_p = 2),即转子机械转 1 圈,定子磁场完成 2 个电周期。因此:
f m = f e P p = f t i m 6 ⋅ P p ⋅ N ⋅ P S C f_m = \frac{f_e}{P_p} = \frac{f_{tim}}{6 \cdot P_p \cdot N \cdot PSC} fm=Ppfe=6⋅Pp⋅N⋅PSCftim
其中 (f_m) 为机械频率(单位:转/秒,rps)。
第四步:换算为 RPM
每分钟转数:
R P M = 60 ⋅ f m = 60 ⋅ f t i m 6 ⋅ P p ⋅ P S C ⋅ N RPM = 60 \cdot f_m = \frac{60 \cdot f_{tim}}{6 \cdot P_p \cdot PSC \cdot N} RPM=60⋅fm=6⋅Pp⋅PSC⋅N60⋅ftim
整理后可记为:
R P M = 10 ⋅ f t i m P p ⋅ P S C ⋅ N RPM = \frac{10 \cdot f_{tim}}{P_p \cdot PSC \cdot N} RPM=Pp⋅PSC⋅N10⋅ftim
对应代码中的实现(bsp_motor_tim.c):
c
rpm = (60UL * MOTOR_HALL_TIMER_CLK_HZ) /
(6UL * MOTOR_POLE_PAIRS * MOTOR_HALL_PRESCALER_COUNT * capture);
2.2 代入本工程参数
| 符号 | 本工程取值 | 含义 |
|---|---|---|
| (f_{tim}) | 84 000 000 Hz | TIM5 计数时钟 |
| (PSC) | 128 | 预分频系数 |
| (P_p) | 2 | 极对数 |
| (N) | CCR1 捕获值 | 相邻两次霍尔跳变的计数值 |
验算示例:若 (N = 1094),则
R P M = 60 × 84 × 10 6 6 × 2 × 128 × 1094 ≈ 3017 RPM = \frac{60 \times 84\times10^6}{6 \times 2 \times 128 \times 1094} \approx 3017 RPM=6×2×128×109460×84×106≈3017
即约 3000 RPM,与空载运行时的观测值一致。
2.3 公式中各因子的物理含义
| 因子 | 含义 |
|---|---|
| 60 | 秒 → 分钟的单位换算 |
| 6 | 一个电周期(360° 电角度)内的霍尔跳变次数 |
| (P_p) | 极对数,将电频率降为机械频率 |
| (PSC) | 定时器预分频,降低计数频率以扩大可测最慢转速范围 |
| (N) | 两次跳变间隔的计数值,越大表示转速越慢 |
当 (N) 过小(本工程 < MOTOR_HALL_CAPTURE_MIN,即 10)时视为噪声不予计算;超过 200 ms 无新跳变则 RPM 归零(motor_hall_speed_poll())。
3. 位置与方向
- 位置 :每次检测到合法的霍尔状态跳变,位置计数 ±1(正转 +1,反转 −1)。数值表示累计的霍尔扇区数,可换算为电角度:
电角度 ≈ 位置 × 60° (mod 360°)。 - 方向 :比较相邻两次状态是否符合正转序列
1→3→2→6→4→5;符合则为正转(DIR=1),反之为反转(DIR=2)。超过 200 ms 无跳变则 DIR=0(停止)。 - 当前霍尔状态:实时读取的 1~6 换相状态,便于调试换相是否正确。
三、TIM5 Hall 接口配置
1. 引脚与定时器
| 项目 | 配置 |
|---|---|
| 定时器 | TIM5 |
| 霍尔 U/V/W | PH10 / PH11 / PH12 |
| 复用功能 | AF2_TIM5 |
| 预分频 | 128 |
| 计数周期 | 0xFFFF |
| 输入滤波 | IC1Filter = 10 |
| 捕获边沿 | 双边沿 TIM_ICPOLARITY_BOTHEDGE |
| 中断优先级 | 0(换相最高优先级) |
2. Hall 模式工作机制
HAL_TIMEx_HallSensor_Init() 配置 TIM5 为霍尔接口模式:
- 三路霍尔异或后接 TI1,任一霍尔变化产生触发中断;
- 触发时将 CCR1 锁存为上次跳变至本次跳变的计数值;
- 在
HAL_TIM_TriggerCallback()中读取 CCR1 计算转速,并执行六步换相。
与 lesson4 相同,换相逻辑仍在 bldcm_commutate() 中根据当前霍尔状态切换 TIM8 PWM 与下桥臂 GPIO。
四、软件实现
1. 关键宏定义(bsp_motor_tim.h)
c
#define MOTOR_HALL_TIMER_CLK_HZ 84000000UL
#define MOTOR_POLE_PAIRS 2U
#define MOTOR_HALL_CAPTURE_MIN 10U
#define MOTOR_RPM_MAX 20000U
#define MOTOR_HALL_SPEED_TIMEOUT_MS 200U
#define MOTOR_HALL_DIR_STOP 0U
#define MOTOR_HALL_DIR_FWD 1U
#define MOTOR_HALL_DIR_REV 2U
2. 霍尔反馈 API
| 函数 | 说明 |
|---|---|
motor_hall_get_rpm() |
机械转速(RPM) |
motor_hall_get_position() |
累计霍尔扇区位置(有符号,正转增) |
motor_hall_get_direction() |
0=停,1=正转,2=反转 |
motor_hall_get_state() |
当前霍尔状态 1~6 |
motor_hall_speed_poll() |
主循环调用,超时将 RPM/DIR 归零 |
3. 触发回调核心逻辑
在 HAL_TIM_TriggerCallback() 中:
c
capture = __HAL_TIM_GET_COMPARE(&motor_htimx_hall, TIM_CHANNEL_1);
motor_hall_update_speed(capture); /* 由 CCR1 计算 RPM */
delta = hall_transition_dir(prev, step); /* 判断正/反转 */
if (delta > 0) { motor_position++; motor_actual_dir = MOTOR_HALL_DIR_FWD; }
if (delta < 0) { motor_position--; motor_actual_dir = MOTOR_HALL_DIR_REV; }
bldcm_commutate(step); /* 六步换相 */
正转序列表 fwd_next[] 按 1→3→2→6→4→5 建立,用于判断跳变方向。
4. 波形帧扩展(bsp_adc.c)
在 lesson6 的 12 字节帧基础上扩展为 22 字节,同一时刻输出全部观测量:
| 偏移 | 长度 | 字段 | 说明 |
|---|---|---|---|
| 0 | 2 | 帧头 | 0xAA 0x55 |
| 2 | 2 | VBUS | uint16,×100,单位 V |
| 4 | 2 | TEMP | uint16,×10,单位 ℃ |
| 6 | 2 | IU | uint16,mA |
| 8 | 2 | IV | uint16,mA |
| 10 | 2 | IW | uint16,mA |
| 12 | 2 | RPM | uint16,机械转速 |
| 14 | 4 | POS | int32 小端,霍尔累计位置 |
| 18 | 2 | DIR | uint16:0停 / 1正 / 2反 |
| 20 | 2 | HALL | uint16,当前状态 1~6 |
所有多字节字段均为小端序 。每 50 ms 调用 adc_send_waveform_frame() 发送一帧。
解析示例:24.5 V、25.3 ℃、U=120 mA、V=130 mA、W=110 mA、RPM=3000、POS=+42、DIR=1(正转)、HALL=3
AA 55 92 09 FD 00 78 00 82 00 6E 00 B8 0B 2A 00 00 00 01 00 03 00
可用下面Python代码段辅助解析数据:
python
import struct
data = bytes.fromhex("AA559209FD00780082006E00B80B2A00000001000300")
assert data[0:2] == b'\xAA\x55'
vbus, temp, iu, iv, iw, rpm, pos, dir_, hall = struct.unpack_from('<6H i 2H', data, 2)
print(vbus/100, temp/10, iu, iv, iw, rpm, pos, dir_, hall)
5. 主循环(main.c)
在 lesson6 基础上增加 motor_hall_speed_poll(),其余逻辑不变(按键/串口控制、堵转检测、过流保护、50 ms 发帧):
c
while (1)
{
deal_key_input();
deal_serial_data();
motor_stall_poll();
motor_hall_speed_poll();
motor_overcurrent_poll();
if (HAL_GetTick() % 50 == 0 && print_flag == 0) {
print_flag = 1;
adc_send_waveform_frame();
} else if (HAL_GetTick() % 50 != 0 && print_flag == 1) {
print_flag = 0;
}
}
五、实验操作与现象
1. 接线
与 lesson4~6 相同:三相线 U/V/W、霍尔 HU/HV/HW(PH10~12)、SD(PE6)、TEMP/VBUS/IU/IV/IW 接驱动板接口 2。NTC 贴于电机表面。
2. 串口控制
| 指令 | 作用 |
|---|---|
d 0 |
正转 |
d 1 |
反转 |
v 1000 |
设置占空比/速度 |
v 0 |
停转 |
K1/K2 加减速,K3/K4 正反转(按下为高)。
3. 输出数据
设置查看串口数据:

通过串口输出速度波形:

可以看到转速并不稳定 。
查看霍尔值,即看转子位置:

4. 调试提示
- 若 RPM 跳变过大:检查
MOTOR_POLE_PAIRS是否与电机一致(本电机为 2 对极)。 - 若 DIR 与指令相反:霍尔线序或
fwd_next[]需按实际接线调整。 - 若 HALL 只在 1~6 中某个值不变:检查 HU/HV/HW 接线或电机是否堵转。
- 转速在停转后约 200 ms 自动归零,避免残留值。
六、小结
本实验使用电机内置霍尔(HU/HV/HW),在 lesson4 换相基础上复用 TIM5 Hall 接口实现:
- 转速:由霍尔跳变间隔(CCR1)估算机械 RPM(精度有限);
- 位置:累计霍尔扇区次数(粗位置,非编码器脉冲计数);
- 方向:由 6 状态序列判断正/反转;
- 统一输出:22 字节 HEX 帧同时携带 VBUS、温度、三相电流与霍尔观测量。
若需高精度速度/位置环或 FOC,应外接增量式编码器并使用 TIM 编码器模式;霍尔测速仅适合本阶段开环 + 粗反馈。下一篇可在霍尔 RPM 反馈基础上加入速度 PI 环,或另行实验外接编码器。