EtherCAT主站SOEM源码解析----分布时钟DC
分布时钟(DC,Dsitributed Clock)可以使所有EtherCAT设备使用相同的系统时间,从而控制各设备任务的同步执行。
1、DC从站
支持分布式时钟的从站称为DC从站,同步原理如下所示:
其中,
Tref: 参考时间,网络中第一个DC从站的时间
Tsys_local(n): 第n个从站的本地系统时间副本(同步后等于Tref),这个时间用来产生同步信号和锁存信号时间标记,供从站微处理器使用。
Tdleay(n): 从第一个DC从站到从站n的传输延时。
Toffset(n):从站n的时间和参考时间的初始偏移量。
其中,Toffset(n)和Tdelay(n)在初始化时由主站测量,并写入从站对应寄存器中。Tref在运行过程中由主站使用FRMW命令定期更新。
SOEM中配置同步时钟的步骤如下:
2、获取从站DC特征信息
在/soem/EthercatConfig.c 的ecx_config_init(ecx_contextt *context, uint8 usetable)函数中,获取从站信息,判断从站是否为DC从站。
if ((etohs(ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3)) & 0x04) > 0) /* Support DC? */ { context->slavelist[slave].hasdc = TRUE; }else{context->slavelist[slave].hasdc = FALSE;}
3、锁存端口时间
在计算时间偏差Toffset(n)和传输延时之前,主站需要发送一个广播命令BWR,写所有从站端口0的接收时间寄存器0x0900,将所有从站捕捉数据帧第一个前导位到达每个端口的本地时间保存到寄存器0x0900~0x090F, 每个端口使用4个字节。
具体代码在/soem/Ethercatdc.c的函数ecx_configdc(ecx_contextt *context)中:
ecx_BWR(context->port, 0, ECT_REG_DCTIME0, sizeof(ht), &ht, EC_TIMEOUTRET); /* latch DCrecvTimeA of all slaves */
4、计算初始时间偏移
读取数据帧处理单元接收时间,与主站的系统时间比较,差值作为Toffset(n)写入从站寄存器0x0920. 计算代码为:
(void)ecx_FPRD(context->port, slaveh, ECT_REG_DCSOF, sizeof(hrt), &hrt, EC_TIMEOUTRET);//前导位到达的本地时间/* use it as offset in order to set local time around 0 + mastertime */hrt = htoell(-etohll(hrt) + mastertime64);//初始偏移量/* save it in the offset register */(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYSOFFSET, sizeof(hrt), &hrt, EC_TIMEOUTRET);
SOEM只在初始化时使从站时间同步主站时间,若要运行后使主从时间同步,需要定期修正主站时间或从站时间 。
5、计算传输延时
传输延时的计算比较复杂,与总线拓扑密切相关,计算原理图如下:
假设系统有5个从站,拓扑如上图所示,以计算从站4的传输延时Tdelay(4)为例。
Tdelay(4) = deltaT + Tdelay(2) + dt2 //deltaT为图中黄色粗箭头所示时间
而deltaT = (dt3-dt1)/2。 假设数据帧经过图中两段黄色粗箭头的时间相等。
dt3为数据帧从Slave2端口2离开到返回的时间,计算代码为:
dt3 = ecx_porttime(context, parent, context->slavelist[i].parentport) -ecx_porttime(context, parent, ecx_prevport(context, parent, context->slavelist[i].parentport));
dt1为从站4后续从站的传输时间,计算代码为:
/* current slave has children *//* those childrens delays need to be substacted */if (context->slavelist[i].topology > 1){dt1 = ecx_porttime(context, i, ecx_prevport(context, i, context->slavelist[i].entryport)) -ecx_porttime(context, i, context->slavelist[i].entryport);}
dt2为从站2其它接口所接从站的传输时间,计算代码为:
/* current slave is not the first child of parent *//* previous childs delays need to be added */if ((child - parent) > 1){dt2 = ecx_porttime(context, parent, ecx_prevport(context, parent, context->slavelist[i].parentport)) -ecx_porttime(context, parent, context->slavelist[parent].entryport);}
计算传输延时并写入从站寄存器0x0928,代码为:
/* calculate current slave delay from delta times *//* assumption : forward delay equals return delay */context->slavelist[i].pdelay = ((dt3 - dt1) / 2) + dt2 +context->slavelist[parent].pdelay;ht = htoel(context->slavelist[i].pdelay);/* write propagation delay*/(void)ecx_FPWR(context->port, slaveh, ECT_REG_DCSYSDELAY, sizeof(ht), &ht, EC_TIMEOUTRET);
6、广播参考时钟
在运行过程中,主站使用命令FRMW读取第一个DC从站的时间并写入到后续DC从站,达到时间同步的目的。
if(first)//第一个DC从站{context->DCl = sublength;/* FPRMW in second datagram */context->DCtO = ecx_adddatagram(context->port, &(context->port->txbuf[idx]), EC_CMD_FRMW, idx, FALSE,context->slavelist[context->grouplist[group].DCnext].configadr,ECT_REG_DCSYSTIME, sizeof(int64), context->DCtime);first = FALSE;}
EtherCAT主站SOEM源码解析----分布时钟DC相关推荐
- EtherCAT主站SOEM源码解析----ecx_siiPDO()
1.从站EEPROM的PDO信息 从站EEPROM存储的PDO信息如下如所示: TxPDO的类型名为50(0x0032),RxPDO的类型名为51(0x0033). 每个PDO占用的EEPROM字节数 ...
- SOEM 源码解析 ecx_LWR
/* LWR "logical memory write" primitive. Blocking.* 逻辑写(LWR) Logical write 原语 阻塞* @param[i ...
- SOEM 源码解析 ecx_FPWR
/* FPWR "configured address write" primitive. Blocking.* 配置的地址物理写(FPWR) Configured address ...
- SOEM 源码解析 ecx_LRD
/* LRD "logical memory read" primitive. Blocking.* 逻辑读(LRD) Logical read 原语 阻塞* @param[in] ...
- SOEM 源码解析 ecx_FRMW
/* FPRMW "configured address read, multiple write" primitive. Blocking.* 配置的地址物理读多次写(FRMW) ...
- SOEM 源码解析 ecx_set_slaves_to_default
寄存器0x0101 寄存器0x0200 寄存器0x0300 寄存器0x0600 寄存器0x0800 寄存器0x0981 寄存器0x0910 寄存器0x0930 寄存器0x0934 寄存器0x0103 ...
- SOEM 源码解析 ecx_APRD
/* APRD "auto increment address read" primitive. Blocking.* 自增式物理读(APRD) Auto increment ph ...
- SOEM 源码解析 ecx_SDOerror
/* Report SDO error.* 报告SDO错误* @param[in] context = context struct* 上下文结构体* @param[in] Slave = Slave ...
- SOEM 源码解析 ecx_FPWRw
/* FPWR "configured address write" primitive. Blocking.* 配置的地址物理写(FPWR) Configured address ...
最新文章
- mysql常用查询命令
- 【共享单车】—— React后台管理系统开发手记:权限设置和菜单调整(未完)...
- Android NFS文件系统挂载遇到的问题解决方法
- java登录的 验证码_java登录验证码
- [转] Oracle学习之创建数据库(新建实例)
- centos7 cuda测试_CentOS 7 安装 NVIDIA 显卡驱动以及CUDA驱动(自测可用)
- python ftp编程_【编程】Python FTP
- 条码打印软件如何批量导入图片和图片名称
- 回到现实的民营航天,离商业化还有多远?
- Vue绘制业务流程图(附源码)
- 英语 语义分割_语义分割该如何走下去?
- java 音乐识别_使用java获取歌曲的属性
- 席绢言情系列书评总序
- Java线程状态及转换
- 微信小程序开发之——用户登录-登录流程(1)
- 这不是广告!千万不要相信淘宝上卖的CSDN会员!!!
- 鸿蒙系统什么时候投入市场,华为鸿蒙系统市场占有率要达多少才可能存活
- chrome浏览器缓存 from disk cache
- html5 直线的两头弯曲,html5教程 (二)(canvas绘制简单的直线)
- 工作中使用了一些触发器