当前位置: 首页 > news >正文

如何通过485通信控制汇川电机

0. 先整体架构

STM32 通过 RS485 + Modbus RTU 控制 4 台汇川SV660C伺服电机

- 使能伺服

- 写目标位置

- 写运行速度

- 启动/停止

- 读编码器位置

1. CRC16校验(最核心的底层函数)

c

static uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len)

{

uint16_t crc = 0xFFFF; // 初始值固定 0xFFFF

uint16_t i, j;

for(i=0; i<len; i++) // 逐字节算CRC

{

crc ^= buf[i]; // 和当前字节异或

for(j=0; j<8; j++) // 逐bit移位

{

if(crc & 0x0001) // 最低位为1

{

crc >>= 1;

crc ^= 0xA001; // 多项式 0xA001(Modbus标准)

}

else

{

crc >>= 1; // 最低位为0,直接右移

}

}

}

return crc;

}

作用

Modbus 必须要 CRC16 校验,否则伺服不认你的指令。

关键点

- 输出是 uint16_t

- 发送时:低字节在前,高字节在后

2. 写多个寄存器(0x10功能码)

c

static void SV660C_Write_Reg(

uint8_t slave_addr, // 从站地址(1~4)

uint16_t reg_addr, // 要写的寄存器地址

uint32_t data) // 要写入的32位数据(位置、速度等)

{

uint8_t buf[16] = {0};

uint16_t crc;

uint8_t len = 0;

// 1. 从站地址

buf[len++] = slave_addr;

// 2. 功能码:0x10 = 写多个寄存器

buf[len++] = 0x10;

// 3. 寄存器地址 高8位 + 低8位

buf[len++] = (reg_addr >> 8) & 0xFF;

buf[len++] = reg_addr & 0xFF;

// 4. 要写的寄存器个数

buf[len++] = 0x00; // 高8位

buf[len++] = 0x02; // 低8位 → 一共写2个16位寄存器 = 32位

// 5. 字节总数:4字节

buf[len++] = 0x04;

// 6. 填入32位数据(高字节先发)

buf[len++] = (data >> 24) & 0xFF;

buf[len++] = (data >> 16) & 0xFF;

buf[len++] = (data >> 8) & 0xFF;

buf[len++] = data & 0xFF;

// 7. 计算CRC

crc = Modbus_CRC16(buf, len);

// 8. CRC低字节、高字节放入报文

buf[len++] = crc & 0xFF;

buf[len++] = (crc >> 8) & 0xFF;

// 9. 通过串口2(RS485)发送

USART2_Send_Data(buf, len);

delay_ms(5);

}

作用

给伺服发 32 位数据(位置、速度、控制字)

为什么用 0x10?

因为汇川位置/速度是 32bit,必须一次写两个16位寄存器。

3. 读寄存器(0x03功能码)

c

static int32_t SV660C_Read_Reg(uint8_t slave_addr, uint16_t reg_addr)

{

uint8_t buf[8] = {0};

uint16_t crc;

uint8_t len = 0;

int32_t res = 0;

// 1. 构建读指令 0x03

buf[len++] = slave_addr;

buf[len++] = 0x03; // 读保持寄存器

buf[len++] = (reg_addr >> 8) & 0xFF;

buf[len++] = reg_addr & 0xFF;

buf[len++] = 0x00; // 读2个寄存器

buf[len++] = 0x02;

// 2. CRC

crc = Modbus_CRC16(buf, len);

buf[len++] = crc & 0xFF;

buf[len++] = (crc >> 8) & 0xFF;

// 3. 清空接收,发指令

USART2_ClearRxBuffer();

USART2_Send_Data(buf, len);

delay_ms(5);

// 4. 判断是否接收完成

if(USART2_RX_STA & 0x8000)

{

uint8_t *rxbuf = USART2_RX_BUF;

// 校验地址和功能码

if(rxbuf[0] == slave_addr && rxbuf[1] == 0x03)

{

// 拼接4字节 → 32位有符号位置

res = (rxbuf[3] << 24)

| (rxbuf[4] << 16)

| (rxbuf[5] << 8)

| rxbuf[6];

}

}

return res;

}

作用

读伺服的32位数据:实际位置、转速、状态等

4. 伺服使能(最关键!)

c

static void SV660C_Servo_Enable(uint8_t slave_addr)

{

// 1. 设置操作模式

SV660C_Write_Reg(slave_addr, SV660C_OP_MODE, 1);

// 2. 控制字:0x0006 → 准备

SV660C_Write_Reg(slave_addr, SV660C_CTRL_WORD, 0x0006);

// 3. 控制字:0x000F → 真正使能

SV660C_Write_Reg(slave_addr, SV660C_CTRL_WORD, 0x000F);

delay_ms(10);

}

对应汇川标准流程

- 0x0006 :伺服准备

- 0x000F :伺服上电使能

不执行这段 → 电机不动、不刹车、无响应。

5. 4轴初始化

c

void SV660C_FourAxis_Init(void)

{

// 初始化RS485串口 19200 8N1

USART2_Init(19200);

delay_ms(100);

// 4个轴都使能

SV660C_Servo_Enable(1);

SV660C_Servo_Enable(2);

SV660C_Servo_Enable(3);

SV660C_Servo_Enable(4);

// 4个轴都设置运行速度

SV660C_Write_Reg(1, SV660C_PROFILE_SPEED, MOTOR_SPEED);

SV660C_Write_Reg(2, SV660C_PROFILE_SPEED, MOTOR_SPEED);

SV660C_Write_Reg(3, SV660C_PROFILE_SPEED, MOTOR_SPEED);

SV660C_Write_Reg(4, SV660C_PROFILE_SPEED, MOTOR_SPEED);

}

作用

开机调用一次,4台伺服全部准备好。

6. 4轴同时正转

c

void FourMotor_Forward(void)

{

// 写目标位置

SV660C_Write_Reg(1, SV660C_TARGET_POS, MOVE_STEP);

SV660C_Write_Reg(2, SV660C_TARGET_POS, MOVE_STEP);

SV660C_Write_Reg(3, SV660C_TARGET_POS, MOVE_STEP);

SV660C_Write_Reg(4, SV660C_TARGET_POS, MOVE_STEP);

// 启动运行(控制字 0x001F)

SV660C_Write_Reg(1, SV660C_CTRL_WORD, 0x001F);

SV660C_Write_Reg(2, SV660C_CTRL_WORD, 0x001F);

SV660C_Write_Reg(3, SV660C_CTRL_WORD, 0x001F);

SV660C_Write_Reg(4, SV660C_CTRL_WORD, 0x001F);

}

- SV660C_TARGET_POS :目标位置寄存器

- 0x001F :启动位置模式运行

7. 4轴同时反转

c

void FourMotor_Backward(void)

{

// 目标位置 = 负数

SV660C_Write_Reg(1, SV660C_TARGET_POS, -MOVE_STEP);

SV660C_Write_Reg(2, SV660C_TARGET_POS, -MOVE_STEP);

SV660C_Write_Reg(3, SV660C_TARGET_POS, -MOVE_STEP);

SV660C_Write_Reg(4, SV660C_TARGET_POS, -MOVE_STEP);

// 启动

SV660C_Write_Reg(1, SV660C_CTRL_WORD, 0x001F);

...

}

反转原理

给负的位置指令即可。

8. 读编码器位置

c

int32_t SV660C_Read_Encoder(uint8_t slave_addr)

{

return SV660C_Read_Reg(slave_addr, SV660C_ACTUAL_POS);

}

void FourMotor_Read_Encoders(int32_t *enc_data)

{

enc_data[0] = SV660C_Read_Encoder(1);

enc_data[1] = SV660C_Read_Encoder(2);

enc_data[2] = SV660C_Read_Encoder(3);

enc_data[3] = SV660C_Read_Encoder(4);

}

作用

读4个电机实时位置,用于闭环、限位、回零。

9. 配套的 sv660c.h 宏定义

c

#define SV660C_OP_MODE 0x6060

#define SV660C_CTRL_WORD 0x6040

#define SV660C_TARGET_POS 0x607A

#define SV660C_PROFILE_SPEED 0x6081

#define SV660C_ACTUAL_POS 0x6064

10. 超简总结(10秒记住整个逻辑)

1. CRC16 保证指令有效

2. 0x10 写32位数据(位置/速度/使能)

3. 0x03 读32位位置

4. 0x0006 → 0x000F 伺服使能

5. 0x001F 启动运行

6. 正转给+位置,反转给-位置

如果你愿意,我可以下一步帮你:

http://www.jsqmd.com/news/487053/

相关文章:

  • 锂离子电池的充电状态和健康状态估计 石墨-磷酸铁锂电池的循环寿命模型 该项目的目标是设计一个强...
  • 光储直流微电网Simulink仿真模型——独立光伏系统能量管理及最大功率点跟踪
  • 2026最新!AI大模型系统学习路线图曝光,从入门到商业落地_AI大模型的详细完整学习路线,从入门到精通
  • 打开软件时弹出提示D3DCompiler_47.dll文件找不到无法启动应用解决方法
  • 文档检索软件self searcher绿色版下载
  • BEV 融合
  • JavaScript同时触发多个函数的5种高效方法
  • 都什么时候了, 你还在担心不会英语不能做外贸?
  • 成都GEO优化公司选择指南?本地标杆和全国企业的对比评测 - 速递信息
  • 解决openclaw下载OMM问题
  • 机房漏水监测系统白皮书:技术革新×应用实践·未来蓝图
  • MOVA“亮剑”AWE2026:让机器人长出“轮足”,用芯片重新定义智慧生活
  • vue+Python云听在线听读音乐小程序的设计与实现
  • 无锡π乐思镜片优质企业
  • 技能提升路线程序,输入目标岗位,倒推所需技能,规划学习顺,少走弯路,快速进阶。
  • 专业提供角膜塑形镜的企业
  • 1/2L7812CV稳压芯片解析
  • 2026年亲测!合肥系统门窗工厂实录
  • 温升测试基础
  • c语言指针解析
  • 【面试真题】能讲讲MySQL的锁机制吗
  • C++ 实战进阶:从编译避坑到打造“转码 - 合并 - 压缩 - 加密”全能视频工厂
  • 使用Maven创建一个web项目
  • 分享一个【连续下跌企稳反弹】指标——在暴跌后的混沌期,精准识别那些即将走牛的黄金坑
  • 基于扩展卡尔曼滤波的车辆质量与道路坡度估计模型(Matlab Simulink 2019+)
  • VMware Workstation 安装 CentOS 7 64位 完整教程
  • 8-Kotlin高阶语法-高阶函数与Lambda
  • Escrcpy - 免费开源!电脑控制安卓手机的投屏工具 (屏幕镜像 / 无线 / AI 自动化 / 录屏)
  • 搭建虚拟机环境Linux
  • OpenClaw这么火了,还需要学信奥赛吗?