跳到主要内容

CiA 402 -- 伺服驱动器

CiA 402 (IEC 61800-7-204) 是基于 CoE 的伺服驱动器设备协议。

备注

CiA 402 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。

状态枚举​

typedef enum {
CIA402_NOT_READY = 0, /* 未就绪 */
CIA402_SWITCH_ON_DISABLED = 1, /* 开关禁用 */
CIA402_READY_TO_SWITCH_ON = 2, /* 准备开关 */
CIA402_SWITCHED_ON = 3, /* 已开关 */
CIA402_OPERATION_ENABLED = 4, /* 运行使能 */
CIA402_QUICK_STOP_ACTIVE = 5, /* 快速停止 */
CIA402_FAULT_REACTION = 6, /* 故障响应 */
CIA402_FAULT = 7, /* 故障 */
CIA402_UNKNOWN = 99 /* 未知 */
} cia402_state_t;

操作模式枚举​

typedef enum {
CIA402_PP = 1, /* 轮廓位置模式 */
CIA402_VL = 2, /* 速度模式 */
CIA402_PV = 3, /* 轮廓速度模式 */
CIA402_PT = 4, /* 轮廓转矩模式 */
CIA402_HM = 6, /* 回零模式 */
CIA402_IP = 7, /* 插补位置模式 */
CIA402_CSP = 8, /* 周期同步位置模式 */
CIA402_CSV = 9, /* 周期同步速度模式 */
CIA402_CST = 10 /* 周期同步转矩模式 */
} cia402_mode_t;

PDO 偏移扫描​

CiA 402 标准对象(ControlWord/StatusWord/PositionActual 等)在 IOmap 中的字节偏移由 advanced 层的 cia402_scan_pdo()(ethercat_advanced.h)扫描并填入 cia402_pdo_map_t。OP 状态后调用一次,后续所有 cia402_read_* / cia402_write_* 读写函数即按该偏移访问 PDO(读走输入帧快照,写走版本化整帧 Begin-patch-Commit;未映射时才退化为 SDO),0 拷贝金路径仍是进 OP 后 GetIO 一次钉页(见 PDO 输入输出)。详见下文 PDO 映射扫描。

状态控制​

CiA402_Enable()​

int CiA402_Enable(uint16_t master, uint16_t slave, int max_retries);

一步使能。DLL 内部自动执行完整的状态链转换(故障清除 -> Shutdown -> Switch On -> Enable Operation)。

参数:

  • master (uint16_t) — 主站索引
  • slave (uint16_t) — 从站索引
  • max_retries (int) — 最大重试次数

返回值:

  • int — 非 0 (TRUE) 成功,0 (FALSE) 失败(转发 BOOL 语义, 与 CiA402_FaultReset / CiA402_SetMode / CiA402_WriteControlWord 一致)

失能与停止​

C SDK 没有独立的 Disable / QuickStop 入口,失能与停止统一通过 CiA402_WriteControlWord() 写对应控制字值实现(见 控制字命令常量):

/* 完全失能: 写 ControlWord = 0x0000 (Disable Voltage) */
CiA402_WriteControlWord(master, slave, 0x0000);

/* 仅退出 Operation Enabled 回到 Switched On (保电不输出力矩): 写 0x0007 (Switch On) */
CiA402_WriteControlWord(master, slave, 0x0007);

/* 触发 Quick Stop (Controlword Bit2=0), 按 0x605A 选项码减速停止: 写 0x0002 */
CiA402_WriteControlWord(master, slave, 0x0002);

CiA402_FaultReset()​

int CiA402_FaultReset(uint16_t master, uint16_t slave);

故障复位。自动产生 ControlWord Bit 7 上升沿,确保故障清除可靠完成。

参数:

  • master (uint16_t) — 主站索引
  • slave (uint16_t) — 从站索引

返回值:

  • int — 非 0 (TRUE) 成功,0 (FALSE) 失败

CiA402_WriteControlWord()​

int CiA402_WriteControlWord(uint16_t master, uint16_t slave, uint16_t cw);

写入控制字 (0x6040)。

参数:

  • cw (uint16_t) — 控制字值

返回值:

  • int — 非 0 (TRUE) 成功,0 (FALSE) 失败

状态读取​

StateDrive​

由 CiA402_ParseState() 返回的当前驱动器状态枚举值(cia402_state_t)。典型流程: 读 StatusWord → ParseState → 判断当前是否处于 OPERATION_ENABLED / FAULT 等。

Statusword​

通过 CiA402_ReadStatusWord() 读 0x6041 实时状态字。位含义见 状态字位掩码常量。Bit10 (TargetReached)、Bit12 (Set-point Ack / HomingAttained)、Bit13 (Following Error / HomingError) 是 PP / HM 握手关键。

Controlword​

通过 CiA402_WriteControlWord() 写 0x6040 控制字。Bit4 (NewSetpoint / StartHoming)、Bit6 (PP 相对/绝对)、Bit8 (Halt) 是常用应用层位。

CiA402_ReadStatusWord()​

uint16_t CiA402_ReadStatusWord(uint16_t master, uint16_t slave);

读取状态字 (0x6041)。

返回值:

  • uint16_t — StatusWord 值

CiA402_ParseState()​

cia402_state_t CiA402_ParseState(uint16_t statusword);

从 StatusWord 解析当前驱动器状态。

参数:

  • statusword (uint16_t) — StatusWord 值

返回值:

  • cia402_state_t — 驱动器状态

CiA402_GetEnableCommand()​

uint16_t CiA402_GetEnableCommand(uint16_t statusword);

根据当前 StatusWord 计算下一步使能所需的 ControlWord。

参数:

  • statusword (uint16_t) — StatusWord 值

返回值:

  • uint16_t — 应写入的 ControlWord 值

操作模式​

CiA402_SetMode()​

int CiA402_SetMode(uint16_t master, uint16_t slave, int8_t mode);

设置操作模式 (0x6060)。写入目标模式后会读取模式显示对象 (0x6061) 确认设备已跟随,设备未跟随时返回失败。

参数:

  • mode (int8_t) — 操作模式 (cia402_mode_t)

返回值:

  • int — 非 0 (TRUE) 成功,0 (FALSE) 失败

CiA402_GetMode()​

int8_t CiA402_GetMode(uint16_t master, uint16_t slave);

读取当前操作模式 (0x6061)。

返回值:

  • int8_t — 操作模式 (cia402_mode_t)

PDO 映射扫描 (ethercat_advanced.h)​

cia402_pdo_map_t​

typedef struct {
int controlword; /* 0x6040 RxPDO 字节偏移 (-1=未映射) */
int target_position; /* 0x607A */
int target_velocity; /* 0x60FF */
int target_torque; /* 0x6071 */
int modes_of_operation; /* 0x6060 */
int statusword; /* 0x6041 TxPDO 字节偏移 (-1=未映射) */
int position_actual; /* 0x6064 */
int velocity_actual; /* 0x606C */
int torque_actual; /* 0x6077 */
int modes_display; /* 0x6061 */
} cia402_pdo_map_t;

cia402_scan_pdo()​

int cia402_scan_pdo(uint16_t master, uint16_t slave,
cia402_pdo_map_t* map);

扫描 CiA 402 PDO 映射,自动定位各对象在 IOmap 中的字节偏移。

参数:

  • master (uint16_t) — 主站索引
  • slave (uint16_t) — 从站索引
  • map (cia402_pdo_map_t*) — 输出映射信息

返回值:

  • int — 0 成功,非 0 失败

PDO 映射读写​

int cia402_read_statusword(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, uint16_t* out);
int cia402_write_controlword(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, uint16_t val);
int cia402_read_position(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t* out);
int cia402_write_target_position(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t val);
int cia402_read_velocity(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t* out);
int cia402_write_target_velocity(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t val);
int cia402_read_torque(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int16_t* out);
int cia402_write_target_torque(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int16_t val);

所有函数返回 0 成功,非 0 失败。

示例:

#include "ethercat_advanced.h"

/* 扫描 PDO 映射 */
cia402_pdo_map_t map;
if (cia402_scan_pdo(master, 1, &map) == 0) {
printf("StatusWord 偏移: %d\n", map.statusword);
printf("ControlWord 偏移: %d\n", map.controlword);
printf("实际位置偏移: %d\n", map.position_actual);
printf("目标位置偏移: %d\n", map.target_position);

/* 通过映射读取状态字 */
uint16_t sw;
cia402_read_statusword(master, 1, &map, &sw);
printf("StatusWord: 0x%04X\n", sw);

/* 写入目标位置 */
cia402_write_target_position(master, 1, &map, 100000);
}

运动参数 (SDO 访问)​

以下参数通过 SDO 读写,适合参数配置。高频控制请使用 PDO 映射。SDO 读写接口见 CoE — dx_sdo_read / dx_sdo_write。

对象访问类型说明
0x6064读 (dx_sdo_read)int32实际位置
0x606C读 (dx_sdo_read)int32实际速度
0x6077读 (dx_sdo_read)int16实际转矩(千分之额定)
0x607A写 (dx_sdo_write)int32目标位置
0x60FF写 (dx_sdo_write)int32目标速度
0x6071写 (dx_sdo_write)int16目标转矩
0x6081写 (dx_sdo_write)uint32轮廓速度
0x6083写 (dx_sdo_write)uint32轮廓加速度
0x6084写 (dx_sdo_write)uint32轮廓减速度
0x6085写 (dx_sdo_write)uint32快速停止减速度
0x607E写 (dx_sdo_write)uint8极性(Bit6=速度反转, Bit7=位置反转)
0x6086写 (dx_sdo_write)int16运动轮廓类型(0=梯形, 1=S形)
0x605A读写 (dx_sdo_read / dx_sdo_write)int16快速停止选项码(读失败哨兵见选项码与错误码)
0x6072写 (dx_sdo_write)uint16最大转矩(千分之额定)
0x6076写 (dx_sdo_write)uint32电机额定转矩(mNm)
0x60B0写 (dx_sdo_write)int32位置偏移(CSP 模式叠加)
0x60B1写 (dx_sdo_write)int32速度偏移(CSV 模式叠加)
0x60C2:01写 (dx_sdo_write)uint8插补时间周期值
0x60C2:02写 (dx_sdo_write)int8插补时间周期指数(周期 = 值 × 10^指数 秒)
0x60E0写 (dx_sdo_write)uint16正方向力矩限制(千分之额定)
0x60E1写 (dx_sdo_write)uint16负方向力矩限制(千分之额定)
SDO 读写函数签名

dx_sdo_write(mi, si, index, sub, BOOL CA, uint8_t* bytes, int length),dx_sdo_read(mi, si, index, sub, BOOL CA, int* out_byte_size) — 注意 C SDK 的 SDO 接口没有单独的超时参数(超时由 DLL 内部按 ETG 兜底)。完整说明见 CoE 页面。

选项码与错误码 (0x605A–0x605E / 0x603F)​

五类驱动器选项码决定各状态转换时的减速/停止行为;错误码反映驱动器当前故障。下列接口直读直写对象字典(薄壳直接导出, 无同名 inline 转发, 按 DarraEcat_ 名调用):

类别接口类型读写返回值
选项码DarraEcat_CiA402_GetQuickStopOption(master, slave)int16只读正常 = 真值;读失败 = -32768 (INT16_MIN)
选项码DarraEcat_CiA402_SetQuickStopOption(master, slave, value)BOOL只写成功 = TRUE
选项码DarraEcat_CiA402_GetShutdownOption(master, slave)int16只读正常 = 真值;读失败 = -32768 (INT16_MIN)
选项码DarraEcat_CiA402_SetShutdownOption(master, slave, value)BOOL只写成功 = TRUE
选项码DarraEcat_CiA402_GetDisableOperationOption(master, slave)int16只读正常 = 真值;读失败 = -32768 (INT16_MIN)
选项码DarraEcat_CiA402_SetDisableOperationOption(master, slave, value)BOOL只写成功 = TRUE
选项码DarraEcat_CiA402_GetHaltOption(master, slave)int16只读正常 = 真值;读失败 = -32768 (INT16_MIN)
选项码DarraEcat_CiA402_SetHaltOption(master, slave, value)BOOL只写成功 = TRUE
选项码DarraEcat_CiA402_GetFaultReactionOption(master, slave)int16只读正常 = 真值;读失败 = -32768 (INT16_MIN)
选项码DarraEcat_CiA402_SetFaultReactionOption(master, slave, value)BOOL只写成功 = TRUE
错误DarraEcat_CiA402_GetErrorCode(master, slave)uint16只读正常 = 真值;读失败 = 0xFFFF

读失败哨兵:三档返回类型各有一个专用哨兵常量,均非合法取值(合法选项码为小值含 0;错误码 0x0000 表无错误)。

  • DARRA_READ_FAIL_I16 = -32768 (INT16_MIN) — 有符号 16 位选项码 Get* (0x605A-0x605E) 读失败
  • DARRA_READ_FAIL_U16 = 0xFFFF — 无符号 16 位 DarraEcat_CiA402_GetErrorCode (0x603F) 读失败
  • DARRA_READ_FAIL_INT = -1 — 返回 int 的计数形读取接口(DarraEcat_CiA402_GetErrorHistory / DarraEcat_CiA402_GetSupportedHomingMethods 等)读失败整体返回 -1(fail-closed)

判别宏:DARRA_IS_READ_FAIL_I16(v) / DARRA_IS_READ_FAIL_U16(v) / DARRA_IS_READ_FAIL_INT(v)。

备注

哨兵值请勿当作真实数值使用,一律按读取失败处理。int8 方法编号(0x60E3 列表项,-128..-1 为厂商自定义方法)是真实取值,不属哨兵,请勿用判别宏判别。

哨兵成因三态:真值 / 读失败 / 入口缺失,三者互斥。本 SDK 的 C 封装层按序号绑定入口,入口未绑定时按返回类型给兜底值,其中 16 位无符号兜底是 0xFFFF,与 0x603F 的读失败哨兵逐字节相同——单看返回值分不出是「入口没绑到」还是「Core 读失败」。要判成因请先取绑定基线再调 raw 入口,用 CiA402_ReadErrorCode 拿到 darraecat_sentinel_cause_t(真值 / 读失败 / 入口缺失);判定顺序是先看绑定状态,再看值。DARRA_IS_READ_FAIL_* 只认「值等于哨兵」,两种成因会被并成一种,不要拿它单独下结论。

示例:

int16_t qs = DarraEcat_CiA402_GetQuickStopOption(m, 1);
if (DARRA_IS_READ_FAIL_I16(qs)) {
/* 读失败哨兵, 不是真实选项码 */
} else {
/* qs 为真实选项码 */
}

uint16_t ec = DarraEcat_CiA402_GetErrorCode(m, 1);
if (DARRA_IS_READ_FAIL_U16(ec)) {
/* 读失败哨兵, 不是真实错误码 */
}

回零参数​

对象类型说明
0x6098int8回零方法
0x607Cint32回零偏移
0x6099:01uint32回零搜索速度
0x6099:02uint32回零爬行速度
0x609Auint32回零加速度

触探功能 (Touch Probe)​

配置 Touch Probe​

/* 通过 SDO 写 0x60B8 配置 Touch Probe 功能字 */
uint16_t fn = 0x0001; /* Bit0=启用探针1, Bit1=边沿选择 */
dx_sdo_write(master, slave, 0x60B8, 0, FALSE, (uint8_t*)&fn, sizeof(fn));
  • 0x60B8 (uint16) — Touch Probe 功能控制(Bit0=启用, Bit1=边沿选择)
  • 0x60B9 (uint16) — Touch Probe 状态(只读)
  • 0x60BA (int32) — 正边沿捕获位置(只读)
  • 0x60BB (int32) — 负边沿捕获位置(只读)

数字 IO​

对象类型说明
0x60FDuint32数字输入(只读,32 位位图)
0x60FE:01uint32数字输出(读写,32 位位图)

软件位置限制​

对象类型说明
0x607D:01int32最小位置限制
0x607D:02int32最大位置限制

快速运动控制​

NewSetpoint(控制字位)​

PP 模式发送新定位命令: 写 0x607A 目标位置 + 触发 Controlword Bit4 (NewSetpoint)。relative=TRUE 时同时设置 Bit6 (Relative)。

ClearNewSetpoint(控制字位)​

PP 模式清除 NewSetpoint 标志(Controlword Bit4=0)。在 TargetReached (Statusword Bit10=1) 后调用,完成 Set-point Ack 握手。

StartHoming(控制字位)​

HM 模式启动回零: 通过 SDO 配置 0x6098 (HomingMethod) / 0x607C (HomeOffset) 后, Controlword Bit4=1 启动。HomingAttained (Statusword Bit12) 表示完成, HomingError (Bit13) 表示错误。

PP / HM 握手由应用通过 PDO/SDO 操作 Controlword 完成,典型流程:

/* PP 模式发送新设定点 */
uint16_t cw = 0x000F; /* Operation Enable */
cw |= 0x0010; /* Bit4: New Setpoint */
if (relative) cw |= 0x0040; /* Bit6: Relative */
CiA402_WriteControlWord(master, slave, cw);
/* TargetReached 后清 Bit4: */
CiA402_WriteControlWord(master, slave, cw & ~0x0010);

/* HM 启动: 通过 SDO 配置 0x6098/0x607C 后, Controlword Bit4=1 启动 */

回零相关参数:

  • 0x6098 (int8) — 回零方法 (HomingMethod)
  • 0x607C (int32) — 回零偏移 (HomeOffset)

回零状态位 (Statusword):

  • Bit 12 — HomingAttained
  • Bit 13 — HomingError

驱动器信息​

SupportedDriveModes​

通过 SDO 0x6502 (uint32) 读取支持的驱动模式位掩码: Bit 0=PP, Bit 1=VL, Bit 2=PV, Bit 3=PT, Bit 5=HM, Bit 6=IP, Bit 7=CSP, Bit 8=CSV, Bit 9=CST。也可直接调 DarraEcat_CiA402_GetSupportedDriveModes(master, slave)(返回 uint32 掩码)。

IsModeSupported​

(SupportedDriveModes >> bit) & 1 即可判断指定模式是否可用;也可直接调 DarraEcat_CiA402_IsModeSupported(master, slave, mode)(返回 BOOL)。

SupportedHomingMethods​

int DarraEcat_CiA402_GetSupportedHomingMethods(uint16_t master, uint16_t slave, int8_t* out_methods, int max_count);

通过 SDO 0x60E3 (int8 数组) 读取驱动器支持的回零方法编号列表。subindex 0 为列表长度, 1..N 为各方法编号。

参数:

  • master (uint16_t) — 主站索引
  • slave (uint16_t) — 从站索引
  • out_methods (int8_t*) — 输出缓冲区,写入方法编号
  • max_count (int) — 输出缓冲区容量,最大写入条目数

返回值:

  • int — 成功时为实际写入的条目数(0..max_count),失败返回 -1

条目为 int8:-128..-1 为厂商自定义方法,0 为未选,1..35 与 37 为 ETG.6010 标准方法。

三种情形各返什么:

  • 失败(SDO 超时 / 通讯异常 / 其它 abort)— 返 -1
  • 空集(SI0=0 且读成功,从站真返回 0 条)— 返 0
  • 不支持(从站无 0x60E3 或 0x60E3:00,SDO abort 0x06020000 对象不存在 / 0x06090011 子索引不存在)— 返 -1,与失败同档
备注

失败与不支持都按失败处理,禁止当成「支持 0 种回零方法」。本导出读失败整体返回 -1(fail-closed),空集返回 0,两者可分辨,请用 DARRA_IS_READ_FAIL_INT 判别。

示例:

int8_t methods[32];
int n = DarraEcat_CiA402_GetSupportedHomingMethods(master, slave, methods, 32);
if (DARRA_IS_READ_FAIL_INT(n)) {
/* 失败或不支持 0x60E3, 都按失败处理, 不是「支持 0 种」 */
} else if (n == 0) {
/* 空集: 读成功但从站真返回 0 条 */
} else {
printf("支持 %d 种回零方法\n", n);
for (int i = 0; i < n; i++) {
printf(" 方法编号: %d\n", methods[i]);
}
}

TxPDO 数据有效性​

通过 SDO 读取 0x603E 判断 TxPDO 数据是否有效。非零表示驱动器 TxPDO 数据不可信,例如编码器未就绪时位置值无意义。

int sz = 0;
char* p = dx_sdo_read(master, slave, 0x603E, 0, FALSE, &sz);
if (p && sz >= 1 && *(uint8_t*)p == 0) {
/* TxPDO 数据有效,可安全使用 */
int32_t pos;
cia402_read_position(master, slave, &map, &pos);
}
if (p) FreeMemory(p);

驱动器信息表​

  • 0x6502 (uint32) — 支持的驱动模式位掩码(Bit0=PP, Bit7=CSP, Bit8=CSV, Bit9=CST)
  • 0x60E3 (int8[]) — 支持的回零方法列表
  • 0x603E (uint8) — TxPDO 数据有效性(非零=数据无效)

同步功能​

对象类型访问说明
0x60D9:01uint16读写同步设置 (SynchronizationSettings),同步使能位掩码
0x60DAuint16只读驱动同步状态 (DriveSyncStatus),指示驱动器是否已同步到主站时钟
/* 读取驱动器同步状态 */
int sz = 0;
char* p = dx_sdo_read(master, slave, 0x60DA, 0, FALSE, &sz);
if (p && sz >= 2) {
uint16_t sync_status = *(uint16_t*)p;
printf("同步状态: 0x%04X\n", sync_status);
}
if (p) FreeMemory(p);

控制字命令常量​

常量值说明
0x0006Shutdown — 关机
0x0007Switch On — 开启
0x000FEnable Operation — 使能运行
0x0000Disable Voltage — 禁用电压
0x0002Quick Stop — 快速停止
0x0080Fault Reset — 故障复位

状态字位掩码常量​

Bit掩码说明
Bit 00x0001Ready to Switch On
Bit 10x0002Switched On
Bit 20x0004Operation Enabled
Bit 30x0008Fault
Bit 40x0010Voltage Enabled
Bit 50x0020Quick Stop
Bit 70x0080Warning
Bit 90x0200Remote
Bit 100x0400Target Reached
Bit 120x1000Homing Attained / Set-point Ack
Bit 130x2000Homing Error / Following Error

完整示例​

#include "ethercat.h"
#include "ethercat_advanced.h"
#include <stdio.h>

int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);

uint16_t slave = 1;

/* 检查初始状态 */
uint16_t sw = CiA402_ReadStatusWord(master, slave);
cia402_state_t state = CiA402_ParseState(sw);
printf("当前状态: %d (SW=0x%04X)\n", state, sw);

/* 故障复位 */
if (state == CIA402_FAULT) {
CiA402_FaultReset(master, slave);
}

/* 设置 CSP 模式 */
CiA402_SetMode(master, slave, CIA402_CSP);
printf("操作模式: %d\n", CiA402_GetMode(master, slave));

/* 一步使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功\n");

/* 扫描 PDO 映射 */
cia402_pdo_map_t map;
if (cia402_scan_pdo(master, slave, &map) == 0) {
/* 读取实际位置 */
int32_t actual;
cia402_read_position(master, slave, &map, &actual);
printf("实际位置: %d\n", actual);

/* 写入目标位置 */
cia402_write_target_position(master, slave, &map, actual + 1000);
}
}

getchar();
Stop(master);
Dispose(master);
return 0;
}

PP 模式 — 轮廓位置控制​

#include "ethercat.h"
#include "ethercat_advanced.h"

int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);

uint16_t slave = 1;

/* 设置 PP 模式 */
CiA402_SetMode(master, slave, CIA402_PP);

/* 配置轮廓参数 (SDO) */
uint32_t vel = 10000, acc = 50000, dec = 50000;
dx_sdo_write(master, slave, 0x6081, 0, FALSE, (uint8_t*)&vel, sizeof(vel));
dx_sdo_write(master, slave, 0x6083, 0, FALSE, (uint8_t*)&acc, sizeof(acc));
dx_sdo_write(master, slave, 0x6084, 0, FALSE, (uint8_t*)&dec, sizeof(dec));

/* 使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功\n");

/* 发送定位命令: 写目标位置 0x607A, 然后 Controlword Bit4=NewSetpoint */
int32_t target = 100000;
dx_sdo_write(master, slave, 0x607A, 0, FALSE, (uint8_t*)&target, sizeof(target));
uint16_t cw = 0x001F; /* Operation Enable + NewSetpoint */
CiA402_WriteControlWord(master, slave, cw);

/* 等待到达 */
uint16_t sw;
do {
sw = CiA402_ReadStatusWord(master, slave);
} while ((sw & 0x0400) == 0); /* 等待 TargetReached (Bit 10) */

printf("目标已到达\n");
CiA402_WriteControlWord(master, slave, cw & ~0x0010); /* 清 NewSetpoint */
}

getchar();
Stop(master);
Dispose(master);
return 0;
}

HM 模式 — 回零​

#include "ethercat.h"

int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);

uint16_t slave = 1;

/* 设置 HM 模式 */
CiA402_SetMode(master, slave, CIA402_HM);

/* 设置回零参数 */
int8_t method = 35; /* 当前位置回零 */
int32_t offset = 0;
uint32_t search_speed = 5000, zero_speed = 500, homing_acc = 10000;

dx_sdo_write(master, slave, 0x6098, 0, FALSE, (uint8_t*)&method, sizeof(method));
dx_sdo_write(master, slave, 0x607C, 0, FALSE, (uint8_t*)&offset, sizeof(offset));
dx_sdo_write(master, slave, 0x6099, 1, FALSE, (uint8_t*)&search_speed, sizeof(search_speed));
dx_sdo_write(master, slave, 0x6099, 2, FALSE, (uint8_t*)&zero_speed, sizeof(zero_speed));
dx_sdo_write(master, slave, 0x609A, 0, FALSE, (uint8_t*)&homing_acc, sizeof(homing_acc));

/* 使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功,开始回零...\n");

/* 启动回零: Controlword Bit4=Start Homing */
CiA402_WriteControlWord(master, slave, 0x001F);

/* 等待回零完成 */
uint16_t sw;
do {
sw = CiA402_ReadStatusWord(master, slave);
if (sw & 0x2000) { /* Bit 13: HomingError */
printf("回零错误!\n");
break;
}
} while ((sw & 0x1000) == 0); /* Bit 12: HomingAttained */

if (sw & 0x1000) {
printf("回零完成\n");
}
}

getchar();
Stop(master);
Dispose(master);
return 0;
}