当前位置: 首页 > news >正文

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()里面进行处理。

http://www.jsqmd.com/news/632118/

相关文章:

  • CST816触摸驱动库:Arduino平台电容触控手势识别与低功耗实践
  • 快速体验VoxCPM-1.5:一键脚本启动,开启语音合成之旅
  • 2026年流动检修车TOP5名录:流动改装车、东风途逸检修车、江淮帅铃检修车、江铃帅达检修车、江铃福顺加长版检修车选择指南 - 优质品牌商家
  • 终极Kinto权限系统完全指南:如何精细控制数据访问与安全共享
  • GeographicLib实战:在Windows/Visual Studio 2022下为你的C++项目添加地理计算能力
  • 为什么芯片工程师写的代码叫“脚本“?
  • 嵌入式FHT库:轻量级实数频谱分析核心
  • Laravel Cashier Stripe Webhook完整教程:实时处理支付事件
  • 7天掌握强化学习:从零开始在FrozenLake环境中实现Q-learning算法的完整指南
  • 《数论探微:进阶版》(Arithmetic Tales: Advanced Edition)敢
  • 终极指南:如何使用Wire将gRPC应用无缝部署到生产环境
  • 两个 Agent 就能搞定芯片研发?别再骗自己了
  • Arduino_KNN:嵌入式K近邻分类器的轻量实现
  • AI开发-python-langchain框架(--AI 直接生成并执行 Python 代码 )聊
  • 【微机原理】CPU 的结构和功能
  • LLM服务中断损失高达$2.3M/小时(2024 Gartner AI Infra报告数据):一文吃透大模型容灾备份的7个生死关卡
  • 量化入门-用Python筛选爆量上涨的股票酒
  • 终极Wire编译器教程:从基础配置到高级优化的完整指南
  • CowPi嵌入式教学平台:内存映射I/O与轮询中断实践
  • 为什么选择over-golang:Go语言学习者的终极资源宝库
  • 为什么选择r2?深度解析现代HTTP客户端的5大优势
  • 如何为HashMD编辑器添加多语言支持:从入门到精通的国际化实践指南
  • 终极Retina.js指南:10个专业技巧打造完美高清图片方案
  • AudioSeal保姆级教程:从零配置GPU驱动到AudioSeal Web服务上线
  • 嵌入式HTTPS客户端:基于WolfSSL的轻量级封装库
  • 如何利用Retina.js实现高分辨率图片自动适配:完整指南与核心原理
  • Qt 5.12+版本中QPalette::Background弃用问题及替代方案详解
  • chromeplugin叛
  • 终极Deno安全开发指南:从权限控制到依赖审计的完整实践
  • 终极Dig性能优化指南:5个减少反射开销的实用策略