ECAT_Main函數(shù)在MainLoop中輪詢,下面是ECAT_Main中的運行流程。
MBX_Main();
在MBX_Main中,獲取sMbxReceiveQueue中的數(shù)據(jù),包括COE的SDO和FOE。對SDO數(shù)據(jù)進行處理,然后回復Master。
if ( bMbxRunning )
{
HW_EscReadWord(sm1Activate,(ESC_SYNCMAN_ACTIVE_OFFSET + SIZEOF_SM_REGISTER));
sm1Activate = SWAPWORD(sm1Activate);
}
bMbxRunning 在成功進入Bootstrap或者Pre-OP狀態(tài)的時候變?yōu)門RUE。這里讀取0x80E寄存器的值。SWAPWORD用于大小端的轉(zhuǎn)換,ESC是小端芯片,如果從機的MCU是大端的話需要進行轉(zhuǎn)換,這里用的小端的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);
}
需要滿足的判斷條件有兩個:
- 0x220的bit0置1,也就是產(chǎn)生了主站狀態(tài)請求事件;
- bEcatWaitForAlControlRes標志位為FALSE。bEcatWaitForAlControlRes在一般狀態(tài)下是FALSE的,只有在safeop到OP狀態(tài)的轉(zhuǎn)換的時候,會先將bEcatWaitForAlControlRes標記為TRUE,然后等待OP條件滿足,例如:DC模式下,需要200ms內(nèi)穩(wěn)定收到PDO數(shù)據(jù),或者其他模式下需要收到一幀PDO數(shù)據(jù),如果nPdOutputSize為0,則不需要PDO接收PDO數(shù)據(jù)。在條件滿足后,從站會將bEcatWaitForAlControlRes標記為FALSE,然后設(shè)置狀態(tài)為OP。
進入這個判斷后:
- 讀取0x120寄存器的值,這個值就是主站請求的狀態(tài),
- 將ALEventReg的bit0和bit4清0。這里的清0主要是避免后續(xù)重復調(diào)用AL_ControlInd函數(shù)。這里清0只是清除變量里的值,若要寄存器清0,對0x120讀操作,0x220的bit0清0;對0x806進行讀操作,0x220的bit4清0。
- 調(diào)用AL_ControlInd設(shè)置狀態(tài)
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);
}
需要滿足的判斷條件有四個:
- 0x220的bit4置1,也就是SM激活寄存器(SM配置寄存器+0x6)產(chǎn)生了變化
- bEcatWaitForAlControlRes標志位為FALSE
- 當前從站的狀態(tài)未報錯
- 當前從站的狀態(tài)不是INIT
進入這個判斷以后:
- 將ALEventReg的bit4清0
- 調(diào)用AL_ControlInd設(shè)置狀態(tài),這里的目的不是為了改變狀態(tài),因為填入的請求狀態(tài)參數(shù)是當前的狀態(tài)值。這里主要目的是當SM激活寄存器發(fā)生改變后,使用AL_ControlInd函數(shù)中的CheckSmSettings來檢查SM的配置。這也解釋了為什么在上一步會將ALEventReg的bit0和bit4都清0了。因為在上一步調(diào)用AL_ControlInd已經(jīng)檢查過了,不需要重復檢查了。
if(bEcatWaitForAlControlRes)
{
AL_ControlRes();
}
bEcatWaitForAlControlRes是在safeop轉(zhuǎn)換OP的時候標記未TRUE的,AL_ControlRes主要是判斷OP條件是否滿足,當條件滿足后會將從站狀態(tài)改變?yōu)镺P,并標記bEcatWaitForAlControlRes為FALSE。
if (!(sm1Activate & SM_SETTING_ENABLE_VALUE))
{
AL_ControlInd(nAlStatus & STATE_MASK, 0);
}
這里應(yīng)該還是對郵箱配置進行檢查,但是因為我的郵箱一直都是激活狀態(tài),所以全程沒有進入到這個條件中去。
if ( ALEventReg & (MAILBOX_READ_EVENT) )
{
u16dummy = 0;
HW_EscWriteWord(u16dummy,u16EscAddrSendMbx);
ALEventReg &= ~(MAILBOX_READ_EVENT);
MBX_MailboxReadInd();
}
需要滿足的判斷條件一個:
- SM1通道有事件發(fā)生,主站讀取了SM1中的數(shù)據(jù);
進入這個判斷后:
- 寫取SM1的第一個字節(jié),用于清除0x220中的SM1事件的置位。
- 清除變量中相應(yīng)位置的置位。
- MBX_MailboxReadInd查看發(fā)送隊列中是否還有待發(fā)送的數(shù)據(jù),如果有,將數(shù)據(jù)寫入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));
}
判斷條件一個:
- 重復請求位(SM配置寄存器+0x6 的bit1)是否翻轉(zhuǎn),bMbxRepeatToggle是上一次bit1的值。
進入這個判斷后:
- 調(diào)用MBX_MailboxRepeatReq將之前保存的上一包數(shù)據(jù)重新寫入郵箱之中,并且更新bMbxRepeatToggle的值。
- 寫重復請求應(yīng)答位(SM配置寄存器+0x7 的bit1),該位與重復請求位相同時,表示PDI對前面設(shè)置的重復請求應(yīng)答。其實也可以理解為主站翻轉(zhuǎn)+0x6的bit1來告訴從站需要重傳,然后主站一直檢測+0x7的bit1,發(fā)現(xiàn)翻轉(zhuǎn)后,說明重傳數(shù)據(jù)已經(jīng)放入郵箱了,主站再去讀從站郵箱里的數(shù)據(jù)。
ALEventReg = HW_GetALEventRegister();
ALEventReg = SWAPWORD(ALEventReg);
if ( ALEventReg & (MAILBOX_WRITE_EVENT) )
{
ALEventReg &= ~(MAILBOX_WRITE_EVENT);
MBX_CheckAndCopyMailbox();
}
重新讀取0x220的寄存器的值,或者這個值已經(jīng)變了。
判斷SM0事件是否發(fā)生了,主機是否有數(shù)據(jù)寫進來了文章來源:http://www.zghlxwxcb.cn/news/detail-475496.html
如果SM0數(shù)據(jù)發(fā)生了,那么先將變量ALEventReg相應(yīng)的位清0,然后調(diào)用MBX_CheckAndCopyMailbox將有效數(shù)據(jù)寫入 sMbxReceiveQueue中。sMbxReceiveQueue會在MBX_Main()里面進行處理。文章來源地址http://www.zghlxwxcb.cn/news/detail-475496.html
到了這里,關(guān)于Ethercat學習-從站源碼解析(ECAT_Main)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!