0. 先整体架构STM32 通过 RS485 Modbus RTU 控制 4 台汇川SV660C伺服电机- 使能伺服- 写目标位置- 写运行速度- 启动/停止- 读编码器位置1. CRC16校验最核心的底层函数cstatic uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len){uint16_t crc 0xFFFF; // 初始值固定 0xFFFFuint16_t i, j;for(i0; ilen; i) // 逐字节算CRC{crc ^ buf[i]; // 和当前字节异或for(j0; j8; j) // 逐bit移位{if(crc 0x0001) // 最低位为1{crc 1;crc ^ 0xA001; // 多项式 0xA001Modbus标准}else{crc 1; // 最低位为0直接右移}}}return crc;}作用Modbus 必须要 CRC16 校验否则伺服不认你的指令。关键点- 输出是 uint16_t- 发送时低字节在前高字节在后2. 写多个寄存器0x10功能码cstatic void SV660C_Write_Reg(uint8_t slave_addr, // 从站地址1~4uint16_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. 计算CRCcrc 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功能码cstatic 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. 构建读指令 0x03buf[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. CRCcrc 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. 伺服使能最关键cstatic 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轴初始化cvoid SV660C_FourAxis_Init(void){// 初始化RS485串口 19200 8N1USART2_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轴同时正转cvoid 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);// 启动运行控制字 0x001FSV660C_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轴同时反转cvoid 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. 读编码器位置cint32_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 0x606410. 超简总结10秒记住整个逻辑1. CRC16 保证指令有效2. 0x10 写32位数据位置/速度/使能3. 0x03 读32位位置4. 0x0006 → 0x000F 伺服使能5. 0x001F 启动运行6. 正转给位置反转给-位置如果你愿意我可以下一步帮你
如何通过485通信控制汇川电机
0. 先整体架构STM32 通过 RS485 Modbus RTU 控制 4 台汇川SV660C伺服电机- 使能伺服- 写目标位置- 写运行速度- 启动/停止- 读编码器位置1. CRC16校验最核心的底层函数cstatic uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len){uint16_t crc 0xFFFF; // 初始值固定 0xFFFFuint16_t i, j;for(i0; ilen; i) // 逐字节算CRC{crc ^ buf[i]; // 和当前字节异或for(j0; j8; j) // 逐bit移位{if(crc 0x0001) // 最低位为1{crc 1;crc ^ 0xA001; // 多项式 0xA001Modbus标准}else{crc 1; // 最低位为0直接右移}}}return crc;}作用Modbus 必须要 CRC16 校验否则伺服不认你的指令。关键点- 输出是 uint16_t- 发送时低字节在前高字节在后2. 写多个寄存器0x10功能码cstatic void SV660C_Write_Reg(uint8_t slave_addr, // 从站地址1~4uint16_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. 计算CRCcrc 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功能码cstatic 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. 构建读指令 0x03buf[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. CRCcrc 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. 伺服使能最关键cstatic 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轴初始化cvoid SV660C_FourAxis_Init(void){// 初始化RS485串口 19200 8N1USART2_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轴同时正转cvoid 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);// 启动运行控制字 0x001FSV660C_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轴同时反转cvoid 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. 读编码器位置cint32_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 0x606410. 超简总结10秒记住整个逻辑1. CRC16 保证指令有效2. 0x10 写32位数据位置/速度/使能3. 0x03 读32位位置4. 0x0006 → 0x000F 伺服使能5. 0x001F 启动运行6. 正转给位置反转给-位置如果你愿意我可以下一步帮你