CiA 401 — 通用 I/O 模块
CiA 401 (IEC 61131-9) 是基于 CoE 的通用数字/模拟 I/O 设备协议。
CiA 401 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。
通过 slave.CoE.CiA401 访问。从站不支持 CiA 401 时为 null。
IO 属性
通过索引器直接读写 IO 通道,所有通道号从 0 开始。
| 属性 | 读写 | 类型 | 说明 |
|---|---|---|---|
| DI[n] | 只读 | bool | 数字输入通道 n |
| DO[n] | 读写 | bool | 数字输出通道 n |
| AI[n] | 只读 | int | 模拟输入通道 n |
| AO[n] | 读写 | short | 模拟输出通道 n |
示例:
var io = slave.CoE.CiA401;
if (io == null) return;
// 数字 IO
bool sensor = io.DI[0];
io.DO[0] = true;
io.DO[1] = sensor;
// 模拟 IO
int adc = io.AI[0];
io.AO[0] = 16384;
高频率 I/O 控制应使用 PDO 映射 而非 SDO。SDO 适合参数配置和诊断。
DI
public DIAccessor DI { get; }
数字输入索引器。DI[channel] 按通道号 (从 0 开始) 读取单通道高/低电平,内部按 8 通道一组转 SDO 0x6000。
相关结构:
public class DIAccessor
{
public bool this[int channel] { get; } // 只读, true = 高电平
}
示例:
bool ch0 = io.DI[0];
bool ch5 = io.DI[5];
DO
public DOAccessor DO { get; }
数字输出索引器。DO[channel] 既可读回上次写入的状态,也可设置目标状态 (写 SDO 0x6200),不影响同组其他通道。
相关结构:
public class DOAccessor
{
public bool this[int channel] { get; set; }
}
示例:
io.DO[0] = true;
io.DO[1] = io.DI[0];
bool current = io.DO[0];
AI
public AIAccessor AI { get; }
模拟输入索引器。AI[channel] 返回 16/32 位有符号原始值,对应 SDO 0x6401 / 0x6402。如需无符号或 32 位无符号,使用 ReadAIUnsigned / ReadAI32Unsigned。
相关结构:
public class AIAccessor
{
public int this[int channel] { get; } // 只读
}
示例:
int adc0 = io.AI[0];
double voltage = adc0 * 10.0 / 32768;
AO
public AOAccessor AO { get; }
模拟输出索引器。AO[channel] 读写 16 位有符号值 (SDO 0x6411)。32 位高精度设备使用 WriteAO32 / ReadAO32。
相关结构:
public class AOAccessor
{
public short this[int channel] { get; set; }
}
示例:
io.AO[0] = 16384; // 写入 50% 量程
short echo = io.AO[0]; // 读回当前设定值
方法 API
索引器内部调用以下方法,也可直接使用。
ReadDI
public bool ReadDI(int channel)
读取数字输入。内部按 8 通道一组自动计算组号和位偏移。
参数:
channel— 通道号(从 0 开始)
WriteDO
public void WriteDO(int channel, bool 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 ushort ReadAIUnsigned(int channel)
读取模拟输入值(无符号 16 位)。适用于 AI 数据范围为 0~65535 的设备。
参数:
channel— 通道号(从 0 开始)
返回值:
ushort— 无符号 16 位模拟值
ReadAI32Unsigned
public uint ReadAI32Unsigned(int channel)
读取模拟输入值(无符号 32 位)。适用于高精度 AI 设备,数据范围 0~4294967295。
参数:
channel— 通道号(从 0 开始)
返回值:
uint— 无符号 32 位模拟值
示例:
var io = slave.CoE.CiA401;
// 有符号读取 (默认, 可能高位值变负数)
int aiSigned = io.ReadAI(0);
// 无符号 16 位读取 (0~65535)
ushort aiU16 = io.ReadAIUnsigned(0);
// 无符号 32 位读取 (高精度设备)
uint aiU32 = io.ReadAI32Unsigned(0);
模拟输入中断与限值
ReadGlobalInterruptEnable / WriteGlobalInterruptEnable
public bool ReadGlobalInterruptEnable()
public void WriteGlobalInterruptEnable(bool enable)
读取或设置模拟输入全局中断使能 (0x6423)。
参数:
enable—true= 使能,false= 禁用
ReadAIUpperLimit / WriteAIUpperLimit
public int ReadAIUpperLimit(int channel)
public void WriteAIUpperLimit(int channel, short value)
读取或写入模拟输入中断上限值 (0x6424)。当 AI 值超过上限时触发中断。
参数:
channel— 通道号(从 0 开始)value— 上限值
ReadAILowerLimit / WriteAILowerLimit
public int ReadAILowerLimit(int channel)
public void WriteAILowerLimit(int channel, short value)
读取或写入模拟输入中断下限值 (0x6425)。当 AI 值低于下限时触发中断。
参数:
channel— 通道号(从 0 开始)value— 下限值
示例:
var io = slave.CoE.CiA401;
// 启用全局中断
io.WriteGlobalInterruptEnable(true);
// 设置通道 0 的上下限
io.WriteAIUpperLimit(0, 30000);
io.WriteAILowerLimit(0, 1000);
// 读取当前限值配置
int upper = io.ReadAIUpperLimit(0);
int lower = io.ReadAILowerLimit(0);
bool enabled = io.ReadGlobalInterruptEnable();
批量 IO 方法
除逐通道操作外,还支持 16/32 位批量读写,一次操作多个通道。
ReadDI16(int group)
public ushort ReadDI16(int group)
读取 16 位数字输入(16 个通道)。
参数:
group— 组号(从 0 开始,每 16 个通道为一组)
返回值:
ushort— 16 位输入值,每位对应一个通道
ReadDI32(int group)
public uint ReadDI32(int group)
读取 32 位数字输入(32 个通道)。
参数:
group— 组号(从 0 开始,每 32 个通道为一组)
返回值:
uint— 32 位输入值,每位对应一个通道
示例:
var io = slave.CoE.CiA401;
ushort di16 = io.ReadDI16(0); // 读取通道 0-15
uint di32 = io.ReadDI32(0); // 读取通道 0-31
bool ch5 = (di16 & (1 << 5)) != 0; // 检查通道 5
ReadDO16 / WriteDO16
public ushort ReadDO16(int group)
public void WriteDO16(int group, ushort value)
读取或写入 16 位数字输出(16 个通道)。
参数:
group— 组号(从 0 开始,每 16 个通道为一组)value— 16 位输出值
ReadDO32 / WriteDO32
public uint ReadDO32(int group)
public void WriteDO32(int group, uint value)
读取或写入 32 位数字输出(32 个通道)。
参数:
group— 组号(从 0 开始,每 32 个通道为一组)value— 32 位输出值
示例:
var io = slave.CoE.CiA401;
// 16 位批量操作
io.WriteDO16(0, 0x00FF); // 通道 0-7 输出高,8-15 输出低
ushort do16 = io.ReadDO16(0); // 读回当前值
// 32 位批量操作
io.WriteDO32(0, 0x0000FFFF); // 通道 0-15 输出高
uint do32 = io.ReadDO32(0); // 读回当前值
ReadAO32 / WriteAO32
public int ReadAO32(int channel)
public void WriteAO32(int channel, int value)
读取或写入 32 位模拟输出值。适用于高精度模拟输出设备。
参数:
channel— 通道号(从 0 开始)value— 32 位输出值
示例:
var io = slave.CoE.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 = 反转对应通道
示例:
var io = slave.CoE.CiA401;
io.SetDIPolarity(1, 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— 滤波使能掩码
示例:
var io = slave.CoE.CiA401;
io.SetDIFilter(1, 10); // 设置滤波使能
byte flt = io.GetDIFilter(1); // 读取当前滤波配置
错误状态读取
GetDOErrorMode / GetDOErrorValue
public CiA401ErrorMode GetDOErrorMode(int group)
public byte GetDOErrorValue(int group)
读取数字输出错误模式和错误安全值的当前配置。
参数:
group— 组号(从 0 开始)
示例:
var io = slave.CoE.CiA401;
var mode = io.GetDOErrorMode(0);
byte safeVal = io.GetDOErrorValue(0);
Console.WriteLine($"错误模式: {mode}, 安全值: 0x{safeVal:X2}");
错误处理
DOErrorMode
public void DOErrorMode(int group, CiA401ErrorMode mode)
设置数字输出错误模式。当 EtherCAT 通信丢失时,决定输出如何响应。
参数:
group— 组号(从 0 开始,每 8 个通道为一组:组 0 = 通道 0-7,组 1 = 通道 8-15)mode— 错误模式
相关结构:
public enum CiA401ErrorMode : byte
{
Hold = 0, // 保持当前输出值
SafeValue = 1, // 切换到预设的安全值
}
DOErrorValue
public void DOErrorValue(int group, byte value)
设置数字输出通信丢失时的安全值。仅在 SafeValue 模式下生效。
参数:
group— 组号(从 0 开始)value— 安全输出值(8 位,每位对应一个通道)
AOErrorMode
public void AOErrorMode(int channel, CiA401ErrorMode mode)
设置模拟输出错误模式。
参数:
channel— 通道号(从 0 开始)mode— 错误模式
AOErrorValue
public void AOErrorValue(int channel, short value)
设置模拟输出通信丢失时的安全值。仅在 SafeValue 模式下生效。
参数:
channel— 通道号(从 0 开始)value— 16 位安全输出值
示例:
io.DOErrorMode(0, CiA401ErrorMode.SafeValue);
io.DOErrorValue(0, 0x00);
io.AOErrorMode(0, CiA401ErrorMode.SafeValue);
io.AOErrorValue(0, 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 | 模拟输出错误值 |
完整示例
var io = slave.CoE.CiA401;
if (io == null) return;
// 数字 IO
bool sensor = io.DI[0];
bool limit = io.DI[5];
io.DO[0] = true;
io.DO[1] = sensor;
// 模拟 IO
int adc = io.AI[0];
double temp = adc * 0.1;
io.AO[0] = (short)(temp > 50 ? 0 : 16384);
// 安全配置
io.DOErrorMode(0, CiA401ErrorMode.SafeValue);
io.DOErrorValue(0, 0x00);