Ethercat学习-从站源码解析(ECAT_Main)

这篇具有很好参考价值的文章主要介绍了Ethercat学习-从站源码解析(ECAT_Main)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ECAT_Main函数在MainLoop中轮询,下面是ECAT_Main中的运行流程。

MBX_Main();

在MBX_Main中,获取sMbxReceiveQueue中的数据,包括COE的SDO和FOE。对SDO数据进行处理,然后回复Master。

    if ( bMbxRunning )
    {
        HW_EscReadWord(sm1Activate,(ESC_SYNCMAN_ACTIVE_OFFSET + SIZEOF_SM_REGISTER));
        sm1Activate = SWAPWORD(sm1Activate);
    }

bMbxRunning 在成功进入Bootstrap或者Pre-OP状态的时候变为TRUE。这里读取0x80E寄存器的值。SWAPWORD用于大小端的转换,ESC是小端芯片,如果从机的MCU是大端的话需要进行转换,这里用的小端的MCU,所以SWAPWORD没什么作用。

    ALEventReg = HW_GetALEventRegister();
    ALEventReg = SWAPWORD(ALEventReg);

读取AL事件请求寄存器0x220的值

    if ((ALEventReg & AL_CONTROL_EVENT) && !bEcatWaitForAlControlRes)
    {
        HW_EscReadWord( EscAlControl, ESC_AL_CONTROL_OFFSET);
        EscAlControl = SWAPWORD(EscAlControl);
        ALEventReg &= ~((AL_CONTROL_EVENT) | (SM_CHANGE_EVENT));
        AL_ControlInd((UINT8)EscAlControl, 0); 
    }

需要满足的判断条件有两个:

  1. 0x220的bit0置1,也就是产生了主站状态请求事件;
  2. bEcatWaitForAlControlRes标志位为FALSE。bEcatWaitForAlControlRes在一般状态下是FALSE的,只有在safeop到OP状态的转换的时候,会先将bEcatWaitForAlControlRes标记为TRUE,然后等待OP条件满足,例如:DC模式下,需要200ms内稳定收到PDO数据,或者其他模式下需要收到一帧PDO数据,如果nPdOutputSize为0,则不需要PDO接收PDO数据。在条件满足后,从站会将bEcatWaitForAlControlRes标记为FALSE,然后设置状态为OP。

进入这个判断后:

  1. 读取0x120寄存器的值,这个值就是主站请求的状态,
  2. 将ALEventReg的bit0和bit4清0。这里的清0主要是避免后续重复调用AL_ControlInd函数。这里清0只是清除变量里的值,若要寄存器清0,对0x120读操作,0x220的bit0清0;对0x806进行读操作,0x220的bit4清0。
  3. 调用AL_ControlInd设置状态
    if ( (ALEventReg & SM_CHANGE_EVENT) && !bEcatWaitForAlControlRes && (nAlStatus & STATE_CHANGE) == 0 && (nAlStatus & ~STATE_CHANGE) != STATE_INIT )
    {
        ALEventReg &= ~(SM_CHANGE_EVENT);
        AL_ControlInd(nAlStatus & STATE_MASK, 0);
    }

需要满足的判断条件有四个:

  1. 0x220的bit4置1,也就是SM激活寄存器(SM配置寄存器+0x6)产生了变化
  2. bEcatWaitForAlControlRes标志位为FALSE
  3. 当前从站的状态未报错
  4. 当前从站的状态不是INIT

进入这个判断以后:

  1. 将ALEventReg的bit4清0
  2. 调用AL_ControlInd设置状态,这里的目的不是为了改变状态,因为填入的请求状态参数是当前的状态值。这里主要目的是当SM激活寄存器发生改变后,使用AL_ControlInd函数中的CheckSmSettings来检查SM的配置。这也解释了为什么在上一步会将ALEventReg的bit0和bit4都清0了。因为在上一步调用AL_ControlInd已经检查过了,不需要重复检查了。
    if(bEcatWaitForAlControlRes)
    {
        AL_ControlRes();
    }

bEcatWaitForAlControlRes是在safeop转换OP的时候标记未TRUE的,AL_ControlRes主要是判断OP条件是否满足,当条件满足后会将从站状态改变为OP,并标记bEcatWaitForAlControlRes为FALSE。

    if (!(sm1Activate & SM_SETTING_ENABLE_VALUE))
    {
          AL_ControlInd(nAlStatus & STATE_MASK, 0);
    }

这里应该还是对邮箱配置进行检查,但是因为我的邮箱一直都是激活状态,所以全程没有进入到这个条件中去。

        if ( ALEventReg & (MAILBOX_READ_EVENT) )
        {
            u16dummy = 0;
            HW_EscWriteWord(u16dummy,u16EscAddrSendMbx);
            ALEventReg &= ~(MAILBOX_READ_EVENT);
            MBX_MailboxReadInd();
        }

需要满足的判断条件一个:

  1. SM1通道有事件发生,主站读取了SM1中的数据;

进入这个判断后:

  1. 写取SM1的第一个字节,用于清除0x220中的SM1事件的置位。
  2. 清除变量中相应位置的置位。
  3. MBX_MailboxReadInd查看发送队列中是否还有待发送的数据,如果有,将数据写入SM1的缓存中
        if ( ( (sm1Activate & SM_SETTING_REPAET_REQ_MASK) && !bMbxRepeatToggle )
            ||( !(sm1Activate & SM_SETTING_REPAET_REQ_MASK) && bMbxRepeatToggle ))
        {
            MBX_MailboxRepeatReq();
            if (bMbxRepeatToggle)
            {
                sm1Activate |= SM_SETTING_REPEAT_ACK;
            }
            else
            {
                sm1Activate &= ~SM_SETTING_REPEAT_ACK; 
            }

            sm1Activate = SWAPWORD(sm1Activate);
            HW_EscWriteWord(sm1Activate,(ESC_SYNCMAN_ACTIVE_OFFSET + SIZEOF_SM_REGISTER));
        }

判断条件一个:

  1. 重复请求位(SM配置寄存器+0x6 的bit1)是否翻转,bMbxRepeatToggle是上一次bit1的值。

进入这个判断后:

  1. 调用MBX_MailboxRepeatReq将之前保存的上一包数据重新写入邮箱之中,并且更新bMbxRepeatToggle的值。
  2. 写重复请求应答位(SM配置寄存器+0x7 的bit1),该位与重复请求位相同时,表示PDI对前面设置的重复请求应答。其实也可以理解为主站翻转+0x6的bit1来告诉从站需要重传,然后主站一直检测+0x7的bit1,发现翻转后,说明重传数据已经放入邮箱了,主站再去读从站邮箱里的数据。
        ALEventReg = HW_GetALEventRegister();
        ALEventReg = SWAPWORD(ALEventReg);
        if ( ALEventReg & (MAILBOX_WRITE_EVENT) )
        {
            ALEventReg &= ~(MAILBOX_WRITE_EVENT);
            MBX_CheckAndCopyMailbox();
        }

重新读取0x220的寄存器的值,或者这个值已经变了。

判断SM0事件是否发生了,主机是否有数据写进来了

如果SM0数据发生了,那么先将变量ALEventReg相应的位清0,然后调用MBX_CheckAndCopyMailbox将有效数据写入 sMbxReceiveQueue中。sMbxReceiveQueue会在MBX_Main()里面进行处理。文章来源地址https://www.toymoban.com/news/detail-475496.html

到了这里,关于Ethercat学习-从站源码解析(ECAT_Main)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于STM32F407-LAN9252的EtherCAT从站协议移植过程

    EtherCAT移植过程 前言:刚拿到一个EtherCAT的开发需求,本来想安心当个CV战士的,结果在网上找了一圈,只有https://www.hexcode.cn/article/5e3ee9a835616641b2daef97 这篇写的相对详细,看来偷不了懒了,只有自己重新整理开发了。 1 、需求 基于STM32F407芯片、LAN9253芯片(自带PHY芯片),验

    2024年02月09日
    浏览(35)
  • HttpRunner3.x 源码解析(2)-main_run执行用例

    当在终端运行输入httprunner run 目录或者文件名,则会调用main_run函数,并传入目录/文件名来执行测试用例。 对于extra_args中的值,如果在os.path.exists不存在,则将其加入extra_args_new中。 如果存在,则将其加入用例列表  tests_path_list 1)如果列表  tests_path_list长度为0,说明用例文

    2023年04月09日
    浏览(29)
  • 学习C这么久了,main函数的这三个参数你见过吗?

    🌸作者简介: 花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。 🌸 专栏简介:本文收录于 Linux从入门到精通 ,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

    2024年02月05日
    浏览(62)
  • DEVICENET转ETHERCAT网关连接ethercat通讯协议详细解析

    你有没有遇到过生产管理系统中,设备之间的通讯问题?两个不同协议的设备进行通讯,是不是很麻烦?今天,我们为大家介绍一款神奇的产品,能够将不同协议的设备进行连接,让现场的数据交换不再困扰! 远创智控YC-ECT-DNT是一款DEVICENET从站功能的通讯网关,可以将DEVI

    2024年02月13日
    浏览(38)
  • Apache Doris 聚合函数源码阅读与解析|源码解读系列

    笔者最近由于工作需要开始调研 Apache Doris,通过阅读聚合函数代码切入 Apache Doris 内核,同时也秉承着开源的精神,开发了 array_agg 函数并贡献给社区。笔者通过这篇文章记录下对源码的一些理解,同时也方便后面的新人更快速地上手源码开发。 聚合函数,顾名思义,即对一

    2024年01月25日
    浏览(40)
  • React源码解析18(5)------ 实现函数组件【修改beginWork和completeWork】

    经过之前的几篇文章,我们实现了基本的jsx,在页面渲染的过程。但是如果是通过函数组件写出来的组件,还是不能渲染到页面上的。 所以这一篇,主要是对之前写得方法进行修改,从而能够显示函数组件,所以现在我们在index.js文件中,修改一下jsx的写法。修改成函数组件

    2024年02月13日
    浏览(37)
  • Ethercat学习-GD32以太网学习

    1、GD32F4以太网简介 GD32F4系列以太网模块包含10/100Mbps以太网MAC,数据的收发都通过DMA进行操作,支持MII(媒体独立接口)与RMII(简化的媒体独立接口)两种与物理层(PHY)通讯的标准接口。 2、以太网模框图简介 ​ 以太网需要外接一个PHY(以太网芯片)才可以进行通信。与PH

    2024年02月06日
    浏览(47)
  • Init函数和main函数

    go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性。 有下面的特征: 两个函数的执行顺序: 对同一个go文件的init()调用顺序是从上到下的。 对同一个package中不同文件是按文件名字符串比较“从小到大”顺序调用各文件中的init()函数。 对于不同的packa

    2024年02月09日
    浏览(33)
  • 【深度学习】分类损失函数解析

    在分类任务中,我们通常使用各种损失函数来衡量模型输出与真实标签之间的差异。有时候搞不清楚用什么,下面是几种常见的分类相关损失函数及其 解析,与代码示例 。 二元交叉熵损失(Binary Cross Entropy Loss,BCELoss): torch.nn.BCELoss() 是用于二元分类的损失函数。它将模型

    2024年02月09日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包