CiA 401 — 通用 I/O 模块
CiA 401 (IEC 61131-9) 是基于 CoE 的通用数字/模拟 I/O 设备协议。
CiA 401 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。
通过 slave.CiA401() 直接访问。从站不支持 CiA 401 时为 null。
IO 属性
通过访问器直接读写 IO 通道,所有通道号从 0 开始。
| 属性 | 读写 | 类型 | 说明 |
|---|---|---|---|
| DI.Get(n) | 只读 | boolean | 数字输入通道 n |
| DO.Get(n) / DO.Set(n, val) | 读写 | boolean | 数字输出通道 n |
| AI.Get(n) | 只读 | int | 模拟输入通道 n |
| AO.Get(n) / AO.Set(n, val) | 读写 | short | 模拟输出通道 n |
示例:
CiA401 io = slave.CiA401();
if (io == null) return;
// 数字 IO
boolean sensor = io.DI.Get(0);
io.DO.Set(0, true);
io.DO.Set(1, sensor);
// 模拟 IO
int adc = io.AI.Get(0);
io.AO.Set(0, (short) 16384);
高频率 I/O 控制应使用 PDO 映射 而非 SDO。SDO 适合参数配置和诊断。
DI
public DIAccessor DI;
数字输入访问器。DI.Get(channel) 按通道号 (从 0 开始) 读取单通道高/低电平,内部按 8 通道一组转 SDO 0x6000。
相关结构:
public class DIAccessor {
public boolean Get(int channel); // 只读, true = 高电平
}
示例:
boolean ch0 = io.DI.Get(0);
boolean ch5 = io.DI.Get(5);
DO
public DOAccessor DO;
数字输出访问器。DO.Get(channel) 读回上次写入的状态,DO.Set(channel, state) 设置目标状态 (写 SDO 0x6200),不影响同组其他通道。
相关结构:
public class DOAccessor {
public boolean Get(int channel);
public void Set(int channel, boolean state);
}
示例:
io.DO.Set(0, true);
io.DO.Set(1, io.DI.Get(0));
boolean current = io.DO.Get(0);
AI
public AIAccessor AI;
模拟输入访问器。AI.Get(channel) 返回 16/32 位有符号原始值,对应 SDO 0x6401 / 0x6402。如需无符号或 32 位无符号,使用 ReadAIUnsigned / ReadAI32Unsigned。
相关结构:
public class AIAccessor {
public int Get(int channel); // 只读
}
示例:
int adc0 = io.AI.Get(0);
double voltage = adc0 * 10.0 / 32768;
AO
public AOAccessor AO;
模拟输出访问器。AO.Get(channel) / AO.Set(channel, value) 读写 16 位有符号值 (SDO 0x6411)。32 位高精度设备使用 WriteAO32 / ReadAO32。
相关结构:
public class AOAccessor {
public short Get(int channel);
public void Set(int channel, short value);
}
示例:
io.AO.Set(0, (short) 16384); // 写入 50% 量程
short echo = io.AO.Get(0); // 读回当前设定值
方法 API
访问器内部调用以下方法,也可直接使用。
ReadDI
public boolean ReadDI(int channel)
读取数字输入。内部按 8 通道一组自动计算组号和位偏移。
参数:
channel— 通道号(从 0 开始)
WriteDO
public void WriteDO(int channel, boolean state)
设置数字输出,不影响同组其他通道。
参数:
channel— 通道号(从 0 开始)state— 目标状态
ReadAI
public int ReadAI(int channel)
读取模拟输入值。自动适应 16 位和 32 位设备。
参数:
channel— 通道号(从 0 开始)
WriteAO
public void WriteAO(int channel, short value)
写入模拟输出值。
参数:
channel— 通道号(从 0 开始)value— 16 位输出值
ReadAIUnsigned
public int ReadAIUnsigned(int channel)
读取模拟输入值(无符号 16 位,以 int 返回避免符号位扩展)。适用于 AI 数据范围为 0~65535 的设备。
参数:
channel— 通道号(从 0 开始)
返回值:
int— 无符号 16 位模拟值(高位补零)
ReadAI32Unsigned
public long ReadAI32Unsigned(int channel)
读取模拟输入值(无符号 32 位,以 long 返回)。适用于高精度 AI 设备,数据范围 0~4294967295。
参数:
channel— 通道号(从 0 开始)
返回值:
long— 无符号 32 位模拟值
示例:
CiA401 io = slave.CiA401();
// 有符号读取 (默认, 可能高位值变负数)
int aiSigned = io.ReadAI(0);
// 无符号 16 位读取 (0~65535)
int aiU16 = io.ReadAIUnsigned(0);
// 无符号 32 位读取 (高精度设备)
long aiU32 = io.ReadAI32Unsigned(0);
模拟输入中断与限值
ReadGlobalInterruptEnable / WriteGlobalInterruptEnable
public int ReadGlobalInterruptEnable()
public boolean WriteGlobalInterruptEnable(int value)
读取或设置模拟输入全局中断使能 (0x6423)。
参数:
value— 使能值 (0=禁用, 非0=使能)
ReadAIUpperLimit / WriteAIUpperLimit
public int ReadAIUpperLimit(int channel)
public boolean WriteAIUpperLimit(int channel, int value)
读取或写入模拟输入中断上限值 (0x6424)。当 AI 值超过上限时触发中断。
参数:
channel— 通道号(从 0 开始)value— 上限值
ReadAILowerLimit / WriteAILowerLimit
public int ReadAILowerLimit(int channel)
public boolean WriteAILowerLimit(int channel, int value)
读取或写入模拟输入中断下限值 (0x6425)。当 AI 值低于下限时触发中断。
参数:
channel— 通道号(从 0 开始)value— 下限值
示例:
CiA401 io = slave.CiA401();
// 启用全局中断
io.WriteGlobalInterruptEnable(1);
// 设置通道 0 的上下限
io.WriteAIUpperLimit(0, 30000);
io.WriteAILowerLimit(0, 1000);
// 读取当前限值配置
int upper = io.ReadAIUpperLimit(0);
int lower = io.ReadAILowerLimit(0);
int enabled = io.ReadGlobalInterruptEnable();
批量 IO 方法
除逐通道操作外,还支持 16/32 位批量读写,一次操作多个通道。
ReadDI16(int group)
public short ReadDI16(int group)
读取 16 位数字输入(16 个通道)。
参数:
group— 组号(子索引,从 1 开始)
返回值:
short— 16 位输入值,每位对应一个通道
ReadDI32(int group)
public int ReadDI32(int group)
读取 32 位数字输入(32 个通道)。
参数:
group— 组号(子索引,从 1 开始)
返回值:
int— 32 位输入值,每位对应一个通道
示例:
CiA401 io = slave.CiA401();
short di16 = io.ReadDI16(1); // 读取通道 0-15
int di32 = io.ReadDI32(1); // 读取通道 0-31
boolean ch5 = (di16 & (1 << 5)) != 0; // 检查通道 5
ReadDO16 / WriteDO16
public short ReadDO16(int group)
public void WriteDO16(int group, short value)
读取或写入 16 位数字输出(16 个通道)。
参数:
group— 组号(子索引,从 1 开始)value— 16 位输出值
ReadDO32 / WriteDO32
public int ReadDO32(int group)
public void WriteDO32(int group, int value)
读取或写入 32 位数字输出(32 个通道)。
参数:
group— 组号(子索引,从 1 开始)value— 32 位输出值
示例:
CiA401 io = slave.CiA401();
// 16 位批量操作
io.WriteDO16(1, (short) 0x00FF); // 通道 0-7 输出高,8-15 输出低
short do16 = io.ReadDO16(1); // 读回当前值
// 32 位批量操作
io.WriteDO32(1, 0x0000FFFF); // 通道 0-15 输出高
int do32 = io.ReadDO32(1); // 读回当前值
ReadAO32 / WriteAO32
public int ReadAO32(int channel)
public void WriteAO32(int channel, int value)
读取或写入 32 位模拟输出值。适用于高精度模拟输出设备。
参数:
channel— 通道号(从 0 开始)value— 32 位输出值
示例:
CiA401 io = slave.CiA401();
io.WriteAO32(0, 65536); // 写入 32 位高精度值
int ao = io.ReadAO32(0); // 读回当前值
数字输入配置
SetDIPolarity / GetDIPolarity
public void SetDIPolarity(int group, byte polarity)
public byte GetDIPolarity(int group)
设置或读取数字输入极性 (0x6002)。可按位反转输入信号逻辑。
参数:
group— 组号(子索引,从 1 开始)polarity— 极性掩码,1 = 反转对应通道
示例:
CiA401 io = slave.CiA401();
io.SetDIPolarity(1, (byte) 0x0F); // 反转通道 0-3 的极性
byte pol = io.GetDIPolarity(1); // 读取当前极性配置
SetDIFilter / GetDIFilter
public void SetDIFilter(int group, byte filterEnable)
public byte GetDIFilter(int group)
设置或读取数字输入滤波使能 (0x6003)。用于消除输入信号抖动。
参数:
group— 组号(子索引,从 1 开始)filterEnable— 滤波使能掩码
示例:
CiA401 io = slave.CiA401();
io.SetDIFilter(1, (byte) 10); // 设置滤波使能
byte flt = io.GetDIFilter(1); // 读取当前滤波配置
错误状态读取
GetDOErrorMode / GetDOErrorValue
public ErrorMode GetDOErrorMode(int group)
public byte GetDOErrorValue(int group)
读取数字输出错误模式和错误安全值的当前配置。
参数:
group— 组号(从 0 开始)
示例:
CiA401 io = slave.CiA401();
CiA401.ErrorMode mode = io.GetDOErrorMode(0);
byte safeVal = io.GetDOErrorValue(0);
System.out.printf("错误模式: %s, 安全值: 0x%02X%n", mode, safeVal);
错误处理
DOErrorMode
public void DOErrorMode(int group, ErrorMode mode)
设置数字输出错误模式。当 EtherCAT 通信丢失时,决定输出如何响应。
参数:
group— 组号(从 0 开始,每 8 个通道为一组:组 0 = 通道 0-7,组 1 = 通道 8-15)mode— 错误模式
相关结构:
public enum ErrorMode {
HOLD((byte) 0), // 保持当前输出值
SAFE_VALUE((byte) 1); // 切换到预设的安全值
}
DOErrorValue
public void DOErrorValue(int group, byte value)
设置数字输出通信丢失时的安全值。仅在 SAFE_VALUE 模式下生效。
参数:
group— 组号(从 0 开始)value— 安全输出值(8 位,每位对应一个通道)
AOErrorMode
public void AOErrorMode(int channel, ErrorMode mode)
设置模拟输出错误模式。
参数:
channel— 通道号(从 0 开始)mode— 错误模式
AOErrorValue
public void AOErrorValue(int channel, short value)
设置模拟输出通信丢失时的安全值。仅在 SAFE_VALUE 模式下生效。
参数:
channel— 通道号(从 0 开始)value— 16 位安全输出值
示例:
io.DOErrorMode(0, CiA401.ErrorMode.SAFE_VALUE);
io.DOErrorValue(0, (byte) 0x00);
io.AOErrorMode(0, CiA401.ErrorMode.SAFE_VALUE);
io.AOErrorValue(0, (short) 0);
标准对象索引常量
可搭配 slave.CoE().SDORead / SDOWrite 直接访问:
| 常量 | 值 | 说明 |
|---|---|---|
| OD_DI | 0x6000 | 数字输入 |
| OD_DI_16BIT | 0x6001 | 16 位数字输入 |
| OD_DI_POLARITY | 0x6002 | 数字输入极性 |
| OD_DI_FILTER | 0x6003 | 数字输入滤波使能 |
| OD_DI_INTERRUPT | 0x6005 | 数字输入中断触发 |
| OD_DI_INTERRUPT_EDGE | 0x6006 | 数字输入中断边沿 |
| OD_DI_32BIT | 0x6020 | 32 位数字输入 |
| OD_DO | 0x6200 | 数字输出 |
| OD_DO_16BIT | 0x6201 | 16 位数字输出 |
| OD_DO_POLARITY | 0x6202 | 数字输出极性 |
| OD_DO_ERROR_MODE | 0x6206 | 数字输出错误模式 |
| OD_DO_ERROR_VALUE | 0x6207 | 数字输出错误值 |
| OD_DO_32BIT | 0x6220 | 32 位数字输出 |
| OD_AI | 0x6400 | 模拟输入 |
| OD_AI_SI_UNIT | 0x6420 | 模拟输入量程 |
| OD_AI_GLOBAL_INTERRUPT | 0x6423 | 模拟输入全局中断使能 |
| OD_AI_UPPER_LIMIT | 0x6424 | 模拟输入中断上限 |
| OD_AI_LOWER_LIMIT | 0x6425 | 模拟输入中断下限 |
| OD_AO | 0x6411 | 模拟输出 |
| OD_AO_32BIT | 0x6412 | 32 位模拟输出 |
| OD_AO_SI_UNIT | 0x6430 | 模拟输出量程 |
| OD_AO_ERROR_MODE | 0x6443 | 模拟输出错误模式 |
| OD_AO_ERROR_VALUE | 0x6444 | 模拟输出错误值 |
完整示例
CiA401 io = slave.CiA401();
if (io == null) return;
// 数字 IO
boolean sensor = io.DI.Get(0);
boolean limit = io.DI.Get(5);
io.DO.Set(0, true);
io.DO.Set(1, sensor);
// 模拟 IO
int adc = io.AI.Get(0);
double temp = adc * 0.1;
io.AO.Set(0, (short) (temp > 50 ? 0 : 16384));
// 安全配置
io.DOErrorMode(0, CiA401.ErrorMode.SAFE_VALUE);
io.DOErrorValue(0, (byte) 0x00);