跳到主要内容

CiA 401 -- 通用 I/O 模块

CiA 401 (IEC 61131-9) 是基于 CoE 的通用数字/模拟 I/O 设备协议。

备注

CiA 401 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。通过 GetSlaveCoEDetails(master, slave) 返回值判断从站是否支持 CoE。

IO 属性

CiA 401 设备有 4 类标准 IO,每类通过 SDO 索引和 PDO 偏移访问。

DI

数字输入(Digital Input)。SDO 索引 0x6000(UINT8 8位)/ 0x6001(UINT16 16位)/ 0x6020(UINT32 32位)。subindex 标识通道(1-based)。每个通道返回一个 bit 状态。

DO

数字输出(Digital Output)。SDO 索引 0x6200(UINT8)/ 0x6201(UINT16)/ 0x6220(UINT32)。subindex 标识通道,可读可写。

AI

模拟输入(Analog Input)。SDO 索引 0x6400(INT16,16 位有符号,slave/cia401.hCIA401_OD_AI),0x6401 为同设备类型别名(CIA401_OD_AI_16BIT)。subindex 标识通道,仅读。无符号读取由 cia401_read_ai_unsigned() 包装同一索引完成。

AO

模拟输出(Analog Output)。SDO 索引 0x6411(INT16)/ 0x6412(INT32)。subindex 标识通道,可读可写。

PDO 数据访问

CiA 401 的数字/模拟 IO 数据通过 PDO 映射交换。具体偏移量取决于从站的 PDO 映射配置。使用 GetIO() 获取 IO 指针后,根据从站手册确定各通道的偏移量;类型化 PDO 读写函数可直接按偏移量访问:

uint8_t di = dll.PDOReadInputU8(master, slave, 0);   /* 数字输入 */
dll.PDOWriteOutputU8(master, slave, 0, 0xFF); /* 数字输出 */
int16_t ai = dll.PDOReadInputI16(master, slave, 2); /* 模拟输入 */
dll.PDOWriteOutputI16(master, slave, 0, 16384); /* 模拟输出 */
实时控制

高频率 I/O 控制应使用 PDO 映射 而非 SDO。SDO 适合参数配置和诊断。

方便函数 API (slave/cia401.h)

slave/cia401.h 提供一组 static inline 便捷函数, 把 SDO 索引/子索引封装为按通道访问的形式。

签名说明

这些是头文件内联函数 (不是 ethercat_advanced.h, 也不在 dll_t 字段中), 首参不带 dll_t* —— 它们内部直接调 dx_sdo_read / dx_sdo_write 裸符号, 因此仅静态链接模式 (!DYNAMIC_LOAD) 可用。 读类函数直接返回值 (失败时返回 0); 写类函数返回 BOOL

cia401_read_di / cia401_write_do

uint8_t cia401_read_di(uint16_t master, uint16_t slave, int channel);
uint8_t cia401_read_do(uint16_t master, uint16_t slave, int channel);
BOOL cia401_write_do(uint16_t master, uint16_t slave, int channel, uint8_t value);

按通道 (从 0 开始) 读数字输入 / 读回数字输出 / 写数字输出 (读-改-写, 不影响同组其他通道)。cia401_read_di / cia401_read_do 返回通道电平 (1/0)。

cia401_read_ai / cia401_write_ao

int16_t  cia401_read_ai(uint16_t master, uint16_t slave, int channel);
uint16_t cia401_read_ai_unsigned(uint16_t master, uint16_t slave, int channel);
int32_t cia401_read_ai32(uint16_t master, uint16_t slave, int channel);
uint32_t cia401_read_ai32_unsigned(uint16_t master, uint16_t slave, int channel);
int16_t cia401_read_ao(uint16_t master, uint16_t slave, int channel);
BOOL cia401_write_ao(uint16_t master, uint16_t slave, int channel, int16_t value);

按通道读模拟输入 (有符号/无符号, 16/32 位; cia401_read_ai32 自适应 16/32 位返回) / 读回模拟输出 / 写 16 位模拟输出。

32 位模拟输出

int32_t cia401_read_ao32(uint16_t master, uint16_t slave, int channel);
BOOL cia401_write_ao32(uint16_t master, uint16_t slave, int channel, int32_t value);

32 位模拟输出 (0x6412) 读写。

模拟输入中断与限值 (slave/cia401.h)

cia401_get/set_global_interrupt_enable

BOOL cia401_get_global_interrupt_enable(uint16_t master, uint16_t slave);
BOOL cia401_set_global_interrupt_enable(uint16_t master, uint16_t slave, BOOL enabled);

模拟输入全局中断使能 (SDO 0x6423)。get 返回当前使能状态; set 返回写入是否成功。

cia401_get/set_ai_upper_limit

int16_t cia401_get_ai_upper_limit(uint16_t master, uint16_t slave, int channel);
BOOL cia401_set_ai_upper_limit(uint16_t master, uint16_t slave, int channel, int16_t value);

设置/读取通道上限告警值 (SDO 0x6424, 有符号 16 位),AI 值超过上限时触发中断。

cia401_get/set_ai_lower_limit

int16_t cia401_get_ai_lower_limit(uint16_t master, uint16_t slave, int channel);
BOOL cia401_set_ai_lower_limit(uint16_t master, uint16_t slave, int channel, int16_t value);

设置/读取通道下限告警值 (SDO 0x6425, 有符号 16 位),AI 值低于下限时触发中断。

批量 IO 函数 (slave/cia401.h)

以下函数 group 参数为 SDO 子索引 (1-based)。

uint16_t cia401_read_di16(uint16_t master, uint16_t slave, uint8_t group);   /* 0x6001 */
uint32_t cia401_read_di32(uint16_t master, uint16_t slave, uint8_t group); /* 0x6020 */
uint16_t cia401_read_do16(uint16_t master, uint16_t slave, uint8_t group); /* 0x6201 */
BOOL cia401_write_do16(uint16_t master, uint16_t slave, uint8_t group, uint16_t value);
uint32_t cia401_read_do32(uint16_t master, uint16_t slave, uint8_t group); /* 0x6220 */
BOOL cia401_write_do32(uint16_t master, uint16_t slave, uint8_t group, uint32_t value);

读类函数直接返回值, 写类函数返回 BOOL

数字输入配置 (slave/cia401.h)

uint16_t cia401_get_di_polarity(uint16_t master, uint16_t slave, uint8_t group);  /* 0x6002 */
BOOL cia401_set_di_polarity(uint16_t master, uint16_t slave, uint8_t group, uint8_t polarity);
uint16_t cia401_get_di_filter(uint16_t master, uint16_t slave, uint8_t group); /* 0x6003 */
BOOL cia401_set_di_filter(uint16_t master, uint16_t slave, uint8_t group, uint8_t filter);

设置/读取数字输入极性 (0x6002, 每位 1=反转) 与滤波使能 (0x6003)。

错误状态读取 (slave/cia401.h)

/* 数字输出错误模式 (0=保持, 1=安全值) / 错误值 */
uint8_t cia401_get_do_error_mode(uint16_t master, uint16_t slave, uint8_t group);
BOOL cia401_set_do_error_mode(uint16_t master, uint16_t slave, uint8_t group, uint8_t mode);
uint16_t cia401_get_do_error_value(uint16_t master, uint16_t slave, uint8_t group);
BOOL cia401_set_do_error_value(uint16_t master, uint16_t slave, uint8_t group, uint8_t value);

/* 模拟输出错误模式 / 错误值 */
uint8_t cia401_get_ao_error_mode(uint16_t master, uint16_t slave, int channel);
BOOL cia401_set_ao_error_mode(uint16_t master, uint16_t slave, int channel, uint8_t mode);
int16_t cia401_get_ao_error_value(uint16_t master, uint16_t slave, int channel);
BOOL cia401_set_ao_error_value(uint16_t master, uint16_t slave, int channel, int16_t value);

错误处理

DOErrorMode

数字输出错误模式(SDO 0x6206)。0=保持最后值,1=切换到安全值。

#define CIA401_ERROR_MODE_HOLD       0
#define CIA401_ERROR_MODE_SAFE_VALUE 1

DOErrorValue

数字输出错误值(SDO 0x6207)。错误模式为 1 时使用此值作为安全输出。

AOErrorMode

模拟输出错误模式(SDO 0x6443),同 DOErrorMode 语义。

AOErrorValue

模拟输出错误值(SDO 0x6444)。

标准对象索引常量

slave/cia401.h 中定义的对象索引宏 (注意带 CIA401_OD_ 前缀):

说明
CIA401_OD_DI0x6000数字输入 (8 位组)
CIA401_OD_DI_16BIT0x600116 位数字输入组
CIA401_OD_DI_POLARITY0x6002数字输入极性
CIA401_OD_DI_FILTER0x6003数字输入滤波使能
CIA401_OD_DI_INTERRUPT0x6005数字输入中断触发
CIA401_OD_DI_INTERRUPT_EDGE0x6006数字输入中断边沿
CIA401_OD_DI_32BIT0x602032 位数字输入组
CIA401_OD_DO0x6200数字输出 (8 位组)
CIA401_OD_DO_16BIT0x620116 位数字输出组
CIA401_OD_DO_POLARITY0x6202数字输出极性
CIA401_OD_DO_ERROR_MODE0x6206数字输出错误模式
CIA401_OD_DO_ERROR_VALUE0x6207数字输出错误值
CIA401_OD_DO_32BIT0x622032 位数字输出组
CIA401_OD_AI0x6400模拟输入 (16 位有符号)
CIA401_OD_AI_16BIT0x6401模拟输入 16 位 (别名)
CIA401_OD_AI_SI_UNIT0x6420模拟输入量程
CIA401_OD_AI_GLOBAL_INTERRUPT0x6423模拟输入全局中断使能
CIA401_OD_AI_UPPER_LIMIT0x6424模拟输入中断上限
CIA401_OD_AI_LOWER_LIMIT0x6425模拟输入中断下限
CIA401_OD_AO0x6411模拟输出 (16 位有符号)
CIA401_OD_AO_32BIT0x641232 位模拟输出
CIA401_OD_AO_SI_UNIT0x6430模拟输出量程
CIA401_OD_AO_ERROR_MODE0x6443模拟输出错误模式
CIA401_OD_AO_ERROR_VALUE0x6444模拟输出错误值

错误模式枚举宏: CIA401_ERROR_MODE_HOLD (0) / CIA401_ERROR_MODE_SAFE_VALUE (1)。

类型化 SDO 读写

ethercat_advanced.h 提供类型化 SDO 包装:

#include "ethercat_advanced.h"

uint8_t polarity;
sdo_read_u8(&dll, master, 1, 0x6002, 0x01, &polarity);

int16_t ai;
sdo_read_i16(&dll, master, 1, 0x6401, 0x01, &ai);

sdo_write_i16(&dll, master, 1, 0x6411, 0x01, 16384);

完整示例

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

int main(void) {
dll_t dll;
LOAD_DLL(&dll, "DarraEtherCAT.dll");
uint16_t master = dll.Initialize();
dll.SetNetwork(master, "\\Device\\NPF_{GUID}", "");
dll.SetStateSequence(master, EC_STATE_OPERATIONAL, 10000);
dll.Start(master);

uint16_t slave = 1;

/* PDO 数字 / 模拟 IO */
uint8_t di = dll.PDOReadInputU8(master, slave, 0);
int16_t ai = dll.PDOReadInputI16(master, slave, 2);
dll.PDOWriteOutputU8(master, slave, 0, 0xFF);
dll.PDOWriteOutputI16(master, slave, 0, 16384);
printf("DI=0x%02X AI=%d\n", di, ai);

/* 配置错误模式 (slave/cia401.h 内联函数, 首参不带 dll_t*) */
cia401_set_do_error_mode(master, slave, 0, CIA401_ERROR_MODE_SAFE_VALUE);
cia401_set_do_error_value(master, slave, 0, 0x00);

/* 模拟输入告警 */
cia401_set_global_interrupt_enable(master, slave, TRUE);
cia401_set_ai_upper_limit(master, slave, 0, 30000);
cia401_set_ai_lower_limit(master, slave, 0, 1000);

getchar();
dll.Stop(master);
dll.Dispose(master);
UNLOAD_DLL(&dll);
return 0;
}