SOEM源码解析——ecx_writeeeprom(写EEPROM)

news2024/11/26 16:26:28

0 工具准备

1.SOEM-master-1.4.0源码

1 ecx_writeeeprom函数总览

/** Write EEPROM to slave bypassing cache.:绕过从站缓存写EEPROM数据
 * @param[in] context   = context struct 句柄
 * @param[in] slave     = Slave number 从站序号
 * @param[in] eeproma   = (WORD) Address in the EEPROM EEPROM地址(以字为单位)
 * @param[in] data      = 16bit data 16bit数据
 * @param[in] timeout   = Timeout in us.
 * @return >0 if OK
 */
int ecx_writeeeprom(ecx_contextt *context, uint16 slave, uint16 eeproma, uint16 data, int timeout)
{
   uint16 configadr;
   /* set eeprom control to master */
   /* 将EEPROM控制权设置为主站 */
   ecx_eeprom2master(context, slave);
   configadr = context->slavelist[slave].configadr;
   return (ecx_writeeepromFP(context, configadr, eeproma, data, timeout));
}

从以上代码可以看到,SOEM主站写从站EEPROM的操作可以分成2块:
(1)通过ecx_eeprom2master函数夺取EEPROM访问控制权
(2)通过ecx_writeeepromFP函数写入数据到从站EEPROM

1.1 ecx_eeprom2master函数解析

ECT_REG_EEPCFG      = 0x0500, // EEPROM控制寄存器
/** Set eeprom control to master. Only if set to PDI.:设置EEPROM访问控制权为主站,仅当它设置为PDI时
 * @param[in] context   = context struct 句柄
 * @param[in] slave     = Slave number 从站序号
 * @return >0 if OK
 */
int ecx_eeprom2master(ecx_contextt *context, uint16 slave)
{
   int wkc = 1, cnt = 0;
   uint16 configadr;
   uint8 eepctl;

   if ( context->slavelist[slave].eep_pdi )
   {
      configadr = context->slavelist[slave].configadr;
      eepctl = 2;
      do
      {
         /* force Eeprom from PDI */
         /* 强制PDI操作释放,复位0x0501.0为0,将EEPROM访问控制权分配给主站 */
         wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET);
      }
      while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
      eepctl = 0;
      cnt = 0;
      do
      {
         /* set Eeprom to master */
         /* 设置EEPRO访问权限分配给主站 */
         wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET);
      }
      while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
      context->slavelist[slave].eep_pdi = 0;
   }

   return wkc;
}

该函数实际上就是通过设置ESC的EEPROM控制寄存器来夺取EEPROM访问控制权,涉及的寄存器功能描述如下:
在这里插入图片描述
主站首先发送FPWR配置写报文设置0x0500.1=1,强制PDI操作释放,将EEPROM的访问控制权分配给主站,相关语句如下:

wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET);

然后发送FPWR配置写报文设置0x0500.0=0,将EEPROM访问权限分配给主站,完成对EEPROM访问控制权的夺取,相关语句如下:

wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET);

1.2 ecx_eeprom2master函数解析

/** Write EEPROM to slave bypassing cache. FPWR method.:绕过从站缓存写EEPROM,FPWR方法
 * @param[in]  context        = context struct 句柄
 * @param[in] configadr   = configured address of slave 从站配置地址
 * @param[in] eeproma     = (WORD) Address in the EEPROM EEPROM地址(以字为单位)
 * @param[in] data        = 16bit data 16bit数据
 * @param[in] timeout     = Timeout in us.
 * @return >0 if OK
 */
int ecx_writeeepromFP(ecx_contextt *context, uint16 configadr, uint16 eeproma, uint16 data, int timeout)
{
   uint16 estat;
   ec_eepromt ed;
   int wkc, rval = 0, cnt = 0, nackcnt = 0;

   if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, timeout))
   {
      /* error bits are set */
      /* 如果EEPROM错误标志置位 */
      if (estat & EC_ESTAT_EMASK) 
      {
         /* clear error bits */
         /* 清除错误标志 */
         estat = htoes(EC_ECMD_NOP);
         wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET3);
      }
      do
      {
         cnt = 0;
         do
         {
            /* 将待写入数据写入到0x0508EEPROM数据寄存器 */
            wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
         }
         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
         ed.comm = EC_ECMD_WRITE;
         ed.addr = eeproma;
         ed.d2   = 0x0000;
         cnt = 0;
         do
         {
            /* 发送主站写命令及写地址 */
            wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
         }
         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
         if (wkc)
         {
            osal_usleep(EC_LOCALDELAY * 2);
            estat = 0x0000;
            /* 等待EEPROM接口空闲,完成写入操作 */
            if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, timeout))
            {
               if (estat & EC_ESTAT_NACK)
               {
                  nackcnt++;
                  osal_usleep(EC_LOCALDELAY * 5);
               }
               else
               {
                  nackcnt = 0;
                  rval = 1;
               }
            }
         }
      }
      while ((nackcnt > 0) && (nackcnt < 3));
   }

   return rval;
}

该函数涉及的寄存器如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
(1)主站发送FPRD配置读报文检查0x0502寄存器bit15是否为0,为0则表示EEPROM接口空闲,相关语句和函数如下:

if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, timeout))
uint16 ecx_eeprom_waitnotbusyFP(ecx_contextt *context, uint16 configadr,uint16 *estat, int timeout)
{
   int wkc, cnt = 0, retval = 0;
   osal_timert timer;

   osal_timer_start(&timer, timeout);
   do
   {
      if (cnt++)
      {
         osal_usleep(EC_LOCALDELAY);
      }
      *estat = 0;
      wkc=ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(*estat), estat, EC_TIMEOUTRET);
      *estat = etohs(*estat);
   }
   while (((wkc <= 0) || ((*estat & EC_ESTAT_BUSY) > 0)) && (osal_timer_is_expired(&timer) == FALSE)); /* wait for eeprom ready */
   if ((*estat & EC_ESTAT_BUSY) == 0)
   {
      retval = 1;
   }

   return retval;
}

在确认EEPROM为空闲状态时,需要检查EEPROM错误标志位,如果错误标志置位需要首先清除错误标志,使用FPWR配置地址写报文设置0x0502寄存器为0x0:

/* error bits are set */
      /* 如果EEPROM错误标志置位 */
      if (estat & EC_ESTAT_EMASK) 
      {
         /* clear error bits */
         /* 清除错误标志 */
         estat = htoes(EC_ECMD_NOP);
         wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET3);
      }

(2)将待写入数据写入到EEPROM数据寄存器
主站发送FPWR配置写报文设置0x0508EEPROM数据寄存器,将16bit的数据写入到该寄存器,相关语句如下:

do
         {
            /* 将待写入数据写入到0x0508EEPROM数据寄存器 */
            wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
         }

(3)发送主站写命令及写地址
主站发送FPWR配置写报文设置0x0502寄存器bit0和bit9为1表示写命令,这2bit的操作必须通过一个EtherCAT报文完成。同时该报文设置0x0504-0x0507EEPROM地址寄存器值为目标地址(以字为单位),相关语句如下:

ed.comm = EC_ECMD_WRITE;
         ed.addr = eeproma;
         ed.d2   = 0x0000;
         cnt = 0;
         do
         {
            /* 发送主站写命令及写地址 */
            wkc = ecx_FPWR(context->port, configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
         }
         while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));

(4)等待ESC完成EEPROM写入工作
主站发送FPRD报文读取0x0502寄存器的bit15,等待bit15为0也就是EEPROM接口空闲,这时去读取bit13命令应答位,查看命令是否正确执行(bit13=0表示无错误,bit13=1表示EEPROM无应答或命令无效)。相关语句如下:

if (wkc)
         {
            osal_usleep(EC_LOCALDELAY * 2);
            estat = 0x0000;
            /* 等待EEPROM接口空闲,完成写入操作 */
            if (ecx_eeprom_waitnotbusyFP(context, configadr, &estat, timeout))
            {
               if (estat & EC_ESTAT_NACK)
               {
                  nackcnt++;
                  osal_usleep(EC_LOCALDELAY * 5);
               }
               else
               {
                  nackcnt = 0;
                  rval = 1;
               }
            }
         }

值得注意的是,上述(3)(4)步骤在一个while循环里执行,在(4)中出现了命令没有正确执行情况时会执行重复(3)(4)步骤最多3次。

2 总结

ecx_writeeeprom函数写从站EEPROM操作可以分为以下2个大块:
(1)通过ecx_eeprom2master函数夺取EEPROM访问控制权
(2)通过ecx_writeeepromFP函数写入数据到从站EEPROM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Voice vlan、ICMP、单臂路由、mux-vlan

目录 一&#xff0c;Voice VLAN Voice vlan配置命令 一&#xff0c;问&#xff1a;已知网络中一台服务器的IP地址&#xff0c;如何找到这太服务器在哪台交换机的哪个接口上​编辑 思路&#xff1a; 二&#xff0c;ICMP协议 三&#xff0c;ICMP案例分析​编辑 四&#xf…

学习c++的第十一天

目录 继承和派生 基类 & 派生类 访问控制和继承 派生类的构造函数 派生类的析构函数 继承类型 多继承 重载运算符和重载函数 函数重载 运算符重载 可重载运算符/不可重载运算符 运算符重载实例 继承和派生 先来说继承&#xff0c;这与现实生活中的继承意思差不…

2023年电工杯数学建模B题人工智能对大学生学习影响的评价求解全过程论文及程序

2023年电工杯数学建模 B题 人工智能对大学生学习影响的评价 原题再现&#xff1a; 人工智能简称AI&#xff0c;最初由麦卡锡、明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出。   2016年&#xff0c;人工智能AlphaGo 4:1战胜韩国围棋高手李世石&#xff0c;期后波…

【亚马逊云科技产品测评】活动征文|亚马逊云科技AWS之EC2详细测评

引言 &#xff08;授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道&#xff09; 在当前的数字化时代&#xff0c;云服务已…

小饭店点餐系统,小餐馆点餐怎么方便,操作简单的酒店点单软件

小饭店点餐系统&#xff0c;小餐馆点餐怎么方便&#xff0c;操作简单的酒店点单软件 今天给大家分享是 佳易王酒店点餐管理系统软件V16.0版本&#xff0c;点餐界面如下图&#xff0c; 1、开台的桌子醒目显示&#xff0c;结账后或没有开台的桌子为灰色显示。 2、多种点餐方式…

Pytho入门教程之Python运行的三种方式

文章目录 一、交互式编程二、脚本式编程三、方式三关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 一、交互式编…

AMD老电脑超频及性能提升方案及实施

收拾电子元件的时候找到了若干古董的CPU 其中有一个X3 440 是原来同学主板烧了之后给我的&#xff0c;我从网上配了AM2 昂达主板&#xff0c;然后又买了AMD兼容内存&#xff0c;组成了win7 64位电脑&#xff0c;用起来非常不错&#xff0c;我把硬件配置和升级过程说明下&#x…

C++对象模型

思考&#xff1a;对于实现平面一个点的参数化。C的class封装看起来比C的struct更加的复杂&#xff0c;是否意味着产生更多的开销呢&#xff1f; 实际上并没有&#xff0c;类的封装不会产生额外的开销&#xff0c;其实&#xff0c;C中在布局以及存取上的额外开销是virtual引起的…

unittest 通过loadTestsFromName执行多个测试case

这段代码是一个使用unittest模块编写的测试运行程序。它的主要功能是加载其他Python文件中的测试用例并运行这些测试用例。 首先&#xff0c;定义了一个主测试类MainTestCase&#xff0c;该类继承自unittest.TestCase。在这个类中&#xff0c;可以添加各种测试方法来测试不同的…

产品经理入门学习(四):项目立项

参考引用 黑马-产品经理入门基础课程 1. 项目方案 1.1 主要阶段 立项阶段 基本方案&#xff1a;要做个什么项目&#xff0c;为什么要做这个项目&#xff0c;这个项目的作用和价值分别有哪些 上线阶段 设计阶段 运营阶段 开发阶段 总结阶段 测试阶段 2. 可行性分析 可…

Python语言_single_color_共140种--全平台可用

Python语言_single_color_共140种–全平台可用

3、Dockerfile 深入与其他细节

Dockerfile 在 Docker 中创建镜像最常用的方式&#xff0c;就是使用 Dockerfile。Dockerfile 是一个 Docker 镜像 的描述文件&#xff0c;我们可以理解成火箭发射的 A、B、C、D…的步骤。Dockerfile 其内部包含了一 条条的指令&#xff0c;每一条指令构建一层&#xff0c;因此每…

045_第三代软件开发-U盘监测

第三代软件开发-U盘监测 文章目录 第三代软件开发-U盘监测项目介绍U盘监测原理解释源代码 关键字&#xff1a; Qt、 Qml、 USB、 Disk、 文件 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Language&#xff09;和…

1.如何实现统一的API前缀-web组件篇

文章目录 1. 问题的由来2.实现原理3. 总结 1. 问题的由来 系统提供了 2 种类型的用户&#xff0c;分别满足对应的管理后台、用户 App 场景。 两种场景的前缀不同&#xff0c;分别为/admin-api/和/app-api/&#xff0c;都写在一个controller里面&#xff0c;显然比较混乱。分开…

storm安装手册及笔记

图解Storm相关概念 图解storm的并发机制 安装Storm的步骤 1、安装一个zookeeper集群 2、上传storm的安装包&#xff0c;解压 3、修改配置文件storm.yaml #所使用的zookeeper集群主机 storm.zookeeper.servers: - "weekend05" - "weekend06"…

亚马逊 JDK下载地址

下载地址 https://docs.aws.amazon.com/corretto/选择版本 选择操作系统 比如 windows64 位 可以选择安装包或者解压版本 msi 的为安装版 zip 的为解压版

微积分第一章函数与极限

1.正反三角函数的导数 2.常用等价无穷小 3.正反三角函数转化&#xff1a; 1.secx1/cosx 2.cecx1/sinx 3.cotx1/tanx 4.基本数学思想&#xff1a; 1.有限式子与无限式子&#xff1a;在面对无限个式子运算时&#xff0c;大体思路为两个方面&#xff0c;第一个为放缩&#xff…

静态、友好、内在:解析C++中的这些特殊元素和对象复制的优化

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 前面我们学习了C中关于类与对象的许多知识点&#xff0c;今天我们继续学习类与对象&#xff0c;最后再总结一下类与对象中的一些关键字内容&#xff0c;以及需要注意的细节。满满的干货…

【H.264】RTP h264 码流 实例解析分析 3 : webrtc

【srs】SRS检测IBMF还是annexb 【H.264】RTP h264 码流 实例解析分析 2 : mediasoup收包 mediasoup 并没完整解析rtp包的内容,可能与mediasoup 只需要转发,不需要解码有关系。 webrtc 本身都是全的。 m98代码,先说关键: webrtc的VideoRtpDepacketizer 第一:对RTPVideoType…

年终述职技巧

一个共识 给个交代 复盘 给自己的交代 展示 给公司的交代 三维构思法 认知与成长 以己为师 萃取与迭代 以事为师 响应与前瞻 以人为师&#xff08;“作者视角”转变为“观众视角”&#xff0c;听懂、感兴趣、认可、有收获&#xff09; 六点通关术 论证价值点 工作成果&#x…