STM32 + VESC6 + N5065电机CAN通信控制教程
硬件平台 :STM32G474VET6 + VESC6电调 + N5065无刷电机
开发环境 :CubeMX + CLion + OpenOCD(DAPLink调试器)
上位机:VOFA+ 和 VESC Tool 6.02
后续会将项目代码上传至github
效果展示
vofa+视角
电机视角
上位机教程
哔哩哔哩
VESC6.4电机驱动器固件更新和简单测试 VESC6.4使用教程(一)_哔哩哔哩_bilibili
csdn
N5065有感(带霍尔传感器))
永刚VESC6


一、VESC电调预配置(必须先完成)
1.1 使用VESC Tool连接电调
- 将VESC6电调通过USB连接到电脑
- 打开
VESC_Tool_6.02.exe
- 点击右上角"连接"按钮,选择对应COM口

后续步骤参考
1.2 电机检测与配置
-
进入左侧菜单:Motor Settings → FOC → General
-
点击 Run Detection 按钮
-
按照提示完成:
- 电机参数检测
- 霍尔传感器检测(如果有)
- 确认检测结果
-
点击 Apply 保存配置
1.3 设置CAN总线ID(关键步骤)
- 进入左侧菜单:App Settings → General
- 找到 CAN Status Message Mode ,设置为
CAN_STATUS_1_2_3_4_5
- 找到 Controller ID,设置ID号(默认为0,可设置0-254)
- 记住这个ID号,后续代码中需要使用
- 点击 Write Configuration 保存
1.4 CAN通信参数设置
- 进入左侧菜单:App Settings → CAN
- 设置 CAN Baud Rate 为
500000
(500kbps) - 确认 Send CAN Status 已勾选
- 点击 Write Configuration 保存
注意:配置完成后断开USB,使用CAN总线通信时不要同时连接USB
二、CubeMX硬件配置
2.1 创建新工程
- 打开STM32CubeMX
- 选择芯片:
STM32G474VETx
- 设置工程名:
VESC6_N5065_Motor_Control
2.2 时钟配置(RCC)
路径 :Pinout & Configuration → System Core → RCC
- HSE (High Speed External) :Crystal/Ceramic Resonator
- LSE (Low Speed External) :Disable
Clock Configuration标签页:
- Input frequency: 48 MHz(外部晶振频率)
- PLL Source Mux: HSE
- PLLM: /12
- PLLN: ×85
- System Clock Mux: PLLCLK
- HCLK: 170 MHz
- APB1: /2 → 85 MHz
- APB2: 170 MHz
2.3 FDCAN1配置(CAN总线)
路径 :Connectivity → FDCAN1
Mode标签页:
- Mode:
Activated
(勾选)
Parameter Settings:
- Nominal Prescaler:
10
- Nominal Time Seg1:
13
- Nominal Time Seg2:
3
- Nominal Sync Jump Width:
1
- Data Prescaler:
1
计算得到波特率:
ini
CAN_Clock = 85MHz / 10 = 8.5MHz
Bit_Time = 1 + 13 + 3 = 17
Baud_Rate = 8.5MHz / 17 = 500kbps
GPIO配置(自动设置):
- PA11: FDCAN1_RX
- PA12: FDCAN1_TX
NVIC Settings(中断配置):
- ✅ FDCAN1_IT0_IRQn(勾选使能)
2.4 USART1配置(VOFA通信)
路径 :Connectivity → USART1
Mode标签页:
- Mode:
Asynchronous
Parameter Settings:
- Baud Rate:
115200
Bits/s - Word Length:
8 Bits
- Parity:
None
- Stop Bits:
1
GPIO配置(自动设置):
- PC4: USART1_TX
- PC5: USART1_RX
NVIC Settings:
- ✅ USART1 global interrupt(勾选使能)
2.5 TIM2定时器配置(10ms任务循环)
路径 :Timers → TIM2
Clock Source:
- Internal Clock(内部时钟源)
Parameter Settings:
- Prescaler:
16999
- Counter Period:
99
- Auto-reload preload:
Enable
计算公式:
ini
Timer_Clock = 170MHz
Prescaler = 16999 → 实际分频系数 = 17000
Counter_Clock = 170MHz / 17000 = 10kHz
Period = 99 → 实际周期 = 100
Interrupt_Freq = 10kHz / 100 = 100Hz → 10ms中断一次
NVIC Settings:
- ✅ TIM2 global interrupt(勾选使能)
2.6 GPIO配置(LED指示灯)
路径 :System Core → GPIO
手动配置两个LED引脚:
- PE12: GPIO_Output(LED1)
- PE13: GPIO_Output(LED2)
配置参数:
- Output Level: Low
- Mode: Output Push Pull
- Pull-up/Pull-down: No pull-up and no pull-down
- Max output speed: Low
2.7 调试接口配置
路径 :System Core → SYS
Debug:
- Serial Wire(保留SWD调试接口)
Timebase Source:
- TIM1(避免与HAL_Delay冲突)
2.8 中断优先级配置
路径 :System Core → NVIC
NVIC标签页配置优先级:
- TIM1 UP TIM16: Priority
15
(最低,用于系统滴答) - FDCAN1_IT0: Priority
0
(最高,CAN接收) - USART1: Priority
0
(高优先级,串口接收) - TIM2: Priority
0
(高优先级,控制任务)
2.9 生成代码
-
Project Manager → Project:
- Project Name:
VESC6_N5065_Motor_Control
- Toolchain/IDE:
STM32CubeIDE
- Project Name:
-
Code Generator:
- ✅ Generate peripheral initialization as a pair of '.c/.h' files per peripheral
-
点击右上角 GENERATE CODE 生成工程
三、CLion工程配置
3.1 导入CubeMX生成的工程
- 将生成的工程复制到工作目录
- 在CLion中打开工程的
CMakeLists.txt
文件
3.2 添加自定义源文件
在Core
目录下直接添加用户文件:
bash
Core/
├── Inc/ # 头文件目录
│ ├── main.h # CubeMX生成
│ ├── stm32g4xx_it.h # CubeMX生成
│ ├── stm32g4xx_hal_conf.h # CubeMX生成
│ ├── motor_control.h # 手动添加
│ ├── vesc_communication.h # 手动添加
│ ├── vesc_motor.h # 手动添加
│ └── vofa_protocol.h # 手动添加
└── Src/ # 源文件目录
├── main.c # CubeMX生成(需修改)
├── stm32g4xx_it.c # CubeMX生成
├── stm32g4xx_hal_msp.c # CubeMX生成
├── system_stm32g4xx.c # CubeMX生成
├── motor_control.c # 手动添加
├── vesc_communication.c # 手动添加
├── vesc_motor.c # 手动添加
└── vofa_protocol.c # 手动添加
3.3 CMakeLists.txt说明
CubeMX生成的CMakeLists.txt已经包含了Core/Inc
和Core/Src
,无需额外修改。 用户自定义文件直接放在这两个目录下即可自动编译。
3.4 配置OpenOCD调试(DAPLink)
创建文件 :项目根目录创建daplink.cfg
粘贴配置内容 :(见项目文件daplink.cfg
)
CLion Run Configuration:
- Edit Configurations → + → OpenOCD Download & Run
- Board config file: 选择
daplink.cfg
- Executable: 选择生成的
.elf
文件
四、硬件连接
4.1 STM32与VESC6连接
STM32引脚 | VESC6引脚 | 说明 |
---|---|---|
PA11 (FDCAN1_RX) | CAN_H | CAN总线H |
PA12 (FDCAN1_TX) | CAN_L | CAN总线L |
GND | GND | 共地 |
注意:
- 需要在CAN_H和CAN_L之间接120Ω终端电阻
- STM32和VESC必须共地
- CAN总线不需要供电引脚
4.2 STM32与VOFA连接(USB转TTL)
STM32引脚 | USB转TTL | 说明 |
---|---|---|
PC4 (USART1_TX) | RX | 串口接收 |
PC5 (USART1_RX) | TX | 串口发送 |
GND | GND | 共地 |
4.3 DAPLink调试器连接
STM32引脚 | DAPLink | 说明 |
---|---|---|
PA13 (SWDIO) | SWDIO | 调试数据 |
PA14 (SWCLK) | SWCLK | 调试时钟 |
GND | GND | 共地 |
3V3 | 3V3 | 供电(可选) |
4.4 电源连接
- STM32:5V或3.3V供电(视开发板而定)
- VESC6:电池供电(根据电机电压选择,N5065建议12-48V)
- 电机:连接到VESC的三相输出端子
五、VOFA+上位机调试
5.1 VOFA配置
- 打开VOFA+软件
- 选择对应的串口(USB转TTL的COM口)
- 波特率设置为:
115200
- 协议选择:
FireWater
(CSV模式)
5.2 数据通道配置
在VOFA中配置8个通道(按CSV顺序):
target_duty
- 目标占空比current_duty
- 当前占空比current_rpm
- 当前转速target_current
- 目标电流current_current
- 当前电流temp_fet
- MOSFET温度temp_motor
- 电机温度control_type
- 控制模式
5.3 控制指令格式
在VOFA的"发送区"输入以下指令(输入后按回车发送):
切换控制模式:
bash
mode:0 # 占空比模式
mode:1 # 电流模式
mode:2 # 转速模式
mode:3 # 刹车模式
占空比控制(-1.0 ~ 1.0):
bash
duty:0.05 # 正转5%占空比
duty:-0.05 # 反转5%占空比
duty:0 # 停止
电流控制(单位:A):
bash
current:1.5 # 正转1.5A电流
current:-2.0 # 反转2A电流(刹车)
转速控制(单位:RPM):
bash
rpm:1000 # 正转1000RPM
rpm:-500 # 反转500RPM
刹车控制(单位:A):
bash
brake:3.0 # 3A刹车电流
通用目标值设置:
bash
target:0.1 # 根据当前模式设置目标值
使能控制:
bash
enable:1 # 使能电机控制
enable:0 # 禁用电机控制
紧急停止:
arduino
stop # 立即停止电机
六、测试与调试流程
6.1 第一次上电测试(安全检查)
-
断开电机,仅连接STM32和VESC6的CAN线
-
给STM32和VESC分别上电
-
观察LED指示:
- LED1应该每500ms闪烁一次(心跳)
- LED2应该每2秒闪烁一次(系统运行)
-
打开VOFA,观察是否收到数据(此时RPM和电流应为0)
6.2 电机低速测试
- 连接电机到VESC
- 在VOFA中发送:
duty:0.05
- 观察电机是否缓慢转动
- 在VOFA中发送:
stop
- 观察电机是否停止


6.3 反向测试
- 在VOFA中发送:
duty:-0.05
- 观察电机是否反向转动
- 发送:
stop
6.4 逐步提升测试
- 逐步增加占空比:
duty:0.1
→duty:0.2
→duty:0.3
- 观察转速变化和系统稳定性
- 监控温度数据(不应超过80°C)

6.5 其他模式测试
电流模式测试:
makefile
mode:1
current:2.0
转速模式测试:
makefile
mode:2
rpm:1500
七、can通信波特率计算
根据你的时钟配置图,让我详细分析CAN波特率的计算过程:
第一步:确定FDCAN时钟源
从你的时钟树图可以看到:
PLL配置路径:
- HSE输入:48 MHz(外部晶振)
- PLLM分频 :÷12 → 48MHz ÷ 12 = 4 MHz(PLL输入)
- PLLN倍频 :×85 → 4MHz × 85 = 340 MHz(VCO频率)
- PLLQ分频 :÷4 → 340MHz ÷ 4 = 85 MHz(FDCAN时钟源)
关键 :FDCAN使用的是PLLQ输出 ,频率为 85 MHz
第二步:CAN波特率计算公式
CAN波特率由以下参数决定:
scss
波特率 = FDCAN_Clock / (Prescaler × Bit_Time)
其中:
- FDCAN_Clock = 85 MHz(PLLQ输出)
- Prescaler(预分频器) = 10
- Bit_Time(位时间) = Sync_Seg + Time_Seg1 + Time_Seg2
第三步:位时间构成
你的配置参数:
- Sync_Seg(同步段) = 1 TQ(固定值,总是1)
- Time_Seg1 = 13 TQ
- Time_Seg2 = 3 TQ
ini
Bit_Time = 1 + 13 + 3 = 17 TQ(时间量子)
第四步:最终计算
方法1:直接计算
ini
波特率 = 85,000,000 Hz / (10 × 17)
= 85,000,000 / 170
= 500,000 bps
= 500 kbps
方法2:分步计算(更直观)
ini
步骤1:计算CAN模块时钟
CAN_Module_Clock = FDCAN_Clock / Prescaler
= 85 MHz / 10
= 8.5 MHz
步骤2:计算波特率
波特率 = CAN_Module_Clock / Bit_Time
= 8.5 MHz / 17
= 500 kbps
关键参数对照表
参数 | 配置值 | 说明 |
---|---|---|
FDCAN时钟源 | PLLQ = 85 MHz | 来自PLL的Q输出 |
Prescaler | 10 | CAN模块分频 |
Sync_Seg | 1 TQ | 固定值 |
Time_Seg1 | 13 TQ | 传播段+相位段1 |
Time_Seg2 | 3 TQ | 相位段2 |
总位时间 | 17 TQ | 1个CAN位的时间量子数 |
最终波特率 | 500 kbps | 与VESC默认匹配 |
采样点位置
采样点 = (Sync_Seg + Time_Seg1) / Bit_Time = (1 + 13) / 17 = 82.35%
这是一个标准的CAN采样点位置(推荐75%-90%)。
为什么选择这些参数?
- 500 kbps:VESC默认CAN波特率,工业标准
- Prescaler=10:在85MHz下得到合适的TQ时钟
- 17 TQ:足够的位时间用于同步和采样
- 采样点82% :确保良好的抗干扰能力
这个配置与VESC Tool中设置的500kbps完全匹配!
八、常见问题排查
8.1 电机不转
可能原因:
- CAN总线连接错误 → 检查CAN_H和CAN_L是否正确
- VESC ID不匹配 → 检查代码中
VESC_CONTROLLER_ID
是否与VESC Tool设置一致 - 占空比指令错误 → 旧版代码字节序错误,确保使用修正后的代码
- 电机未检测 → 重新用VESC Tool进行电机检测
- 安全限制 → 检查
MAX_SAFE_DUTY
是否设置过小 - can通信波特率不匹配
8.2 电机全速运转(无法控制)
原因 :字节序错误(小端序 vs 大端序) 解决 :使用修正后的vesc_communication.c
代码(大端序发送)
8.3 VOFA收不到数据
可能原因:
- 串口选择错误 → 检查COM口
- 波特率错误 → 确认为115200
- UART未初始化 → 检查
VOFA_Init()
是否调用
8.4 CAN通信无响应
排查步骤:
- 使用逻辑分析仪或示波器检查CAN信号
- 确认终端电阻(120Ω)已接入
- 检查VESC Tool中的CAN设置
- 确认CAN中断是否使能
8.5 温度过高
处理措施:
- 降低电流/占空比
- 检查散热器安装
- 检查电机负载是否过大
- 添加温度保护逻辑
九、代码安全保护机制
9.1 占空比限幅
在vesc_motor.c
的VESC_Motor_SetTarget()
中:
arduino
#define MAX_SAFE_DUTY 0.05f // 调试期间最大5%
调试完成后可修改为更大的值(最大1.0)
9.2 温度监控
建议添加温度保护逻辑:
ini
if (motor.current_temp_fet > 80.0f || motor.current_temp_motor > 80.0f) {
motor.enabled = 0;
VESC_SetDuty(0);
// 触发报警
}
9.3 启动延时
代码中已包含2秒启动延时和3次闪烁指示,避免上电瞬间误动作
十、扩展功能建议
10.1 PID闭环控制
可在vesc_motor.c
中添加位置/速度PID控制器,实现精确控制
10.2 多电机控制
修改不同的VESC_CONTROLLER_ID
,可同时控制多个电机
10.3 轨迹规划
结合TIM定时器,实现梯形/S型速度曲线
10.4 故障诊断
解析VESC的故障代码,实现故障自动检测和保护
十一、参考资料
- VESC官方文档 :vesc-project.com/
- VESC CAN协议 :项目中的
VESC6_CAN_CommandsTelemetry.pdf
- STM32G4参考手册:RM0440
- FDCAN外设应用笔记:AN5348
教程完成! 按照以上步骤操作,即可实现STM32通过CAN总线控制VESC电调和无刷电机。