跳到主要内容

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)。

参数:

  • enabletrue = 使能, 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_DI0x6000数字输入
OD_DI_16BIT0x600116 位数字输入
OD_DI_POLARITY0x6002数字输入极性
OD_DI_FILTER0x6003数字输入滤波使能
OD_DI_INTERRUPT0x6005数字输入中断触发
OD_DI_INTERRUPT_EDGE0x6006数字输入中断边沿
OD_DI_32BIT0x602032 位数字输入
OD_DO0x6200数字输出
OD_DO_16BIT0x620116 位数字输出
OD_DO_POLARITY0x6202数字输出极性
OD_DO_ERROR_MODE0x6206数字输出错误模式
OD_DO_ERROR_VALUE0x6207数字输出错误值
OD_DO_32BIT0x622032 位数字输出
OD_AI0x6400模拟输入
OD_AI_SI_UNIT0x6420模拟输入量程
OD_AI_GLOBAL_INTERRUPT0x6423模拟输入全局中断使能
OD_AI_UPPER_LIMIT0x6424模拟输入中断上限
OD_AI_LOWER_LIMIT0x6425模拟输入中断下限
OD_AO0x6411模拟输出
OD_AO_32BIT0x641232 位模拟输出
OD_AO_SI_UNIT0x6430模拟输出量程
OD_AO_ERROR_MODE0x6443模拟输出错误模式
OD_AO_ERROR_VALUE0x6444模拟输出错误值

完整示例

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);