1 2 | SOEM(Simple Open EtherCAT Master)是一个开源的EtherCAT主站。 本文介绍其中读取从站EEPROM信息的步骤。 |
1、ESC EEPROM访问控制寄存器
从站控制芯片ESC EEPROM控制寄存器如下:
2、读EEPROM步骤
1 2 3 4 5 6 7 8 | 读的一般步骤为: (1) 读取EEPROM控制/状态寄存器0x0502:0x0503的内容,确认EEPROM没有处于Busy状态 (2) 向0x0502:0x0503写入读控制命令,写入的值为0x0100,向0x0504:0x0507写入需要读的EEPROM地址 (3) 重复步骤(1) (4) 从寄存器0x0508:0x050F中读取对应EEPROM地址的内容 读取一次SOEM主站需要发送4帧数据。 步骤(1)和(2)在SOEM源码中对应的实现函数为ecx_readeeprom1()。 步骤(3)和(4)在SOEM源码中对应的实现函数为ecx_readeeprom2()。 |
3、ecx_readeeprom1()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void ecx_readeeprom1(ecx_contextt *context, uint16 slave, uint16 eeproma) { uint16 configadr, estat; ec_eepromt ed; int wkc, cnt = 0; ecx_eeprom2master(context, slave); /* set eeprom control to master */ configadr = context->slavelist[slave].configadr; if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, EC_TIMEOUTEEP)) { if (estat & EC_ESTAT_EMASK) /* error bits are set */ { estat = htoes(EC_ECMD_NOP); /* clear error bits */ wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET3); } ed.comm = htoes(EC_ECMD_READ); //EC_ECMD_READ=0x0100 ed.addr = htoes(eeproma); ed.d2 = 0x0000; do { wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET); } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES)); } } |
4、ecx_readeeprom2()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | uint32 ecx_readeeprom2(ecx_contextt *context, uint16 slave, int timeout) { uint16 estat, configadr; uint32 edat; int wkc, cnt = 0; configadr = context->slavelist[slave].configadr; edat = 0; estat = 0x0000; if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, timeout)) { do { //ECT_REG_EEPDAT = 0x0508, wkc = ecx_FPRD(context->port, configadr, ECT_REG_EEPDAT, sizeof(edat), &edat, EC_TIMEOUTRET); } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES)); } return edat; } |
5、读VendorID
1 | VendorID在EEPROM中的地址为0x000a,在/soem/EtheratConfig.c文件中,函数ecx_config_init()读取VendorID的代码如下: |
1 2 3 4 5 6 7 8 9 10 11 12 | for (slave = 1; slave <= *(context->slavecount); slave++) { context->slavelist[slave].eep_man = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* Manuf */ ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */** //ECT_SII_ID = 0x000a } for (slave = 1; slave <= *(context->slavecount); slave++) { context->slavelist[slave].eep_id = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* ID */ ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */ } |
使用Wireshark监控可以看到对应的EtherCAT帧如下:
其中帧95、96、99和100对应步骤1,查询EEPROM状态。
帧97/98对应步骤2,向0x0502:0x0503中写入读命令0x0100,向0x0504:0x0507写入VendorID所在的EEPROM地址0x000a。
帧101/102从0x0508:0x050F读取VendorID的值。