check_states(); ready = io_is_ready();两函数位于ecrt_domain_process(domain)之后、应用逻辑之前。主站先接收并处理本周期的数据,然后再检查主站、过程数据域和从站状态,最后根据状态判断是否允许读取按键、控制 LED。
1.把工作计数状态转成可读文本
辅助函数:wc_state_to_string();
static const char *wc_state_to_string(ec_wc_state_t state) { switch (state) { case EC_WC_ZERO: return "ZERO"; case EC_WC_INCOMPLETE: return "INCOMPLETE"; case EC_WC_COMPLETE: return "COMPLETE"; default: return "UNKNOWN"; } }WC是工作计数,用来确定过程数据通信是否完整。
ZERO:工作计数为 0,通常说明过程数据没有正常响应。INCOMPLETE:工作计数不完整,说明有数据交换,但没有达到预期。COMPLETE:工作计数完整,说明本周期过程数据通信符合预期。
2.统一检查主站、域、从站状态
static void check_states(void) { ec_master_state_t next_master_state; ec_domain_state_t next_domain_state; ec_slave_config_state_t next_slave_state; ecrt_master_state(master, &next_master_state); ecrt_domain_state(domain, &next_domain_state); ecrt_slave_config_state(slave_config, &next_slave_state); if (next_master_state.link_up != master_state.link_up) { printf("主站链路变化: %s -> %s\n", master_state.link_up ? "up" : "down", next_master_state.link_up ? "up" : "down"); } if (next_master_state.slaves_responding != master_state.slaves_responding) { printf("响应从站数量变化: %u -> %u\n", master_state.slaves_responding, next_master_state.slaves_responding); } if (next_domain_state.wc_state != domain_state.wc_state || next_domain_state.working_counter != domain_state.working_counter) { printf("domain WC: %s(%u) -> %s(%u)\n", wc_state_to_string(domain_state.wc_state), domain_state.working_counter, wc_state_to_string(next_domain_state.wc_state), next_domain_state.working_counter); } if (next_slave_state.al_state != slave_state.al_state || next_slave_state.online != slave_state.online || next_slave_state.operational != slave_state.operational) { printf("从站状态变化: al=0x%02X online=%u op=%u -> al=0x%02X online=%u op=%u\n", slave_state.al_state, slave_state.online, slave_state.operational, next_slave_state.al_state, next_slave_state.online, next_slave_state.operational); } master_state = next_master_state; domain_state = next_domain_state; slave_state = next_slave_state; }一次性查询了三类状态:
ecrt_master_state(master, &next_master_state); //主站状态 ecrt_domain_state(domain, &next_domain_state); //过程数据域状态 ecrt_slave_config_state(slave_config, &next_slave_state); //目标从站状态2.1 ecrt_master_state(master, &next_master_state);
检查了两个字段:
next_master_state.link_up next_master_state.slaves_respondinglink_up:主站网口链路是否连接正常。
slaves_responding:当前有多少个从站正在响应主站。
2.2 ecrt_domain_state(domain, &next_domain_state);
检查了两个字段:
next_domain_state.wc_state next_domain_state.working_counterwc_state表示工作计数状态。working_counter表示实际工作计数值。
2.3 ecrt_slave_config_state(slave_config, &next_slave_state);
检查了三个字段:
next_slave_state.al_state next_slave_state.online next_slave_state.operationalal_state表示从站当前 AL 状态。online表示从站是否在线。operational表示从站是否进入运行状态。
直接用十六进制打印al:
al=0x01 INIT al=0x02 PREOP al=0x04 SAFEOP al=0x08 OP3.判断是否允许执行应用 I/O
static bool io_is_ready(void) { return master_state.link_up && master_state.slaves_responding > 0 && slave_state.online && slave_state.operational && slave_state.al_state == EC_AL_STATE_OP && domain_state.wc_state == EC_WC_COMPLETE; }作用:根据当前保存的主站、从站和 domain 状态,判断本周期是否允许执行应用 I/O。返回BOOL值:
true 允许读 KEY、写 LED false 不允许正常 I/O,进入安全输出逻辑主循环里后面会根据其返回值决定:只有io_is_ready()返回真,程序才读取 KEY 并控制 LED。否则直接关闭 LED。
ready = io_is_ready(); if (ready) { key_mask = read_key_mask(); write_all_leds(key3_pressed); } else { write_all_leds(false); }小结
主站不仅能完成周期收发,也具备了基本的状态判断和安全输出逻辑。