void MainLoop(void)
{
/* 当运行在FreeRun-Mode: bEscIntEnabled = FALSE, bDcSyncActive = FALSE
当运行在Synchron-Mode: bEscIntEnabled = TRUE, bDcSyncActive = FALSE
当运行在DC-Mode: bEscIntEnabled = FALSE, bDcSyncActive = TRUE */
if ( (!bEscIntEnabled || !bEcatFirstOutputsReceived) /* SM同步方式,但是没有SM事件接收 */
#if DC_SUPPORTED
&& !bDcSyncActive /* DC同步方式 */
#endif
)
{
/* 如果应用程序是运行在ECAT同步模式当中,函数ECAT_Application将会在ESC中断里面被调用(在mcihw.c和spihw.c) 在ECAT同步模式当中,它可以被另外得检查,如果SM事件被接受至少一次(bEcatFirstOutputReceived=1),否则,没有中断会产生和函数ECAT_Application将会在这里被调用(中断禁止,因为当执行ECAT_Application的时候,SM事件可以产生)*/
if ( !bEscIntEnabled )
{
/* 应用程序正在运行在ECAT 自由运行模式,首先,我们需要检查是否有输出被接受 */
UINT16 ALEvent = HW_GetALEventRegister();
ALEvent = SWAPWORD(ALEvent);
if ( ALEvent & PROCESS_OUTPUT_EVENT )
{
/* 设置标志位给状态机处理 */
bEcatFirstOutputsReceived = TRUE;
#if !ESC_SM_WD_SUPPORTED
/* 重置看门狗计数器 */
EcatWdCounter = 0;
#endif
if ( bEcatOutputUpdateRunning )
{
/* 更新输出的状态量 */
PDO_OutputMapping();
}
}
else if ( nPdOutputSize == 0 )
{
/* 如果没有输出被传输,当有输入被读,看门狗需要被重置 */
if ( ALEvent & PROCESS_INPUT_EVENT )
{
/* 输出被更新,设置标志位给看门狗检测 */
bEcatFirstOutputsReceived = TRUE;
#if !ESC_SM_WD_SUPPORTED
/* 重置看门狗的计数器 */
EcatWdCounter = 0;
#endif
}
}
}
#if AL_EVENT_ENABLED
DISABLE_ESC_INT();
#endif
ECAT_Application();
#if AL_EVENT_ENABLED
ENABLE_ESC_INT();
#endif
}
#if !ECAT_TIMER_INT
/* 这里没有中断服务程序来处理硬件定时器,所以,检查定时器的寄存器看是否想要的周期已经过了*/
{
UINT32 CurTimer = HW_GetTimer();
if(CurTimer>= ECAT_TIMER_INC_P_MS)
{
ECAT_CheckTimer();
HW_ClearTimer();
}
}
#endif
/* 调用EtherCAT函数 */
ECAT_Main();
#if COE_SUPPORTED
/* 调用低优先级的应用程序部分 */
COE_Main();
#endif
CheckIfEcatError();
#if CiA402_DEVICE
if(bEcatInputUpdateRunning)
{
CiA402_StateMachine();//调用CIA402的处理机,来处理COE,这里没有用到
}
#endif
}
void PDO_OutputMapping()
{
HW_EscReadIsr(((MEM_ADDR *)aPdOutputData), nEscAddrOutputData, nPdOutputSize );
APPL_OutputMapping((UINT16*) aPdOutputData);
}
/
/**
\param 指针指向输出处理数据
\brief 这个函数将拷贝输出从ESC内存到本地内存到硬件
*
void APPL_OutputMapping(Uint16* pData)
{
Uint16 j = 0;
Uint8 *pTmpData = (Uint8 *)pData;// 允许数据处理
for (j = 0; j < sRxPDOassign.u16SubIndex0; j++)
{
switch (sRxPDOassign.aEntries[j])
{
/* RxPDO 2 */
case 0x1601:
sDOOutputs.LEDs = *pTmpData++;
break;
case 0x1602:
sDO1Outputs.Count = *pTmpData++;
sDO1Outputs.Cmd = *pTmpData++;
sDO1Outputs.MotorData = *pTmpData++;
sDO1Outputs.MotorData |= (*pTmpData++ << 8);
break;
}
}
}
void ECAT_Application(void)
{
#if CiA402_DEVICE
/*轴的配置被写,在状态转换从PREOP到SAFEOP=>触发CiA402应用程序,如果设备是在SAFEOP或者OP状态
(电机控制器的函数只有被触发,如果DC同步被激活和有效的运行模式被设置)*/
if(bEcatInputUpdateRunning)
#endif
{
APPL_Application();
}
if ( bEcatInputUpdateRunning )
{
/* EtherCAT 从站是至少在SAFE-OPERATIONAL,更新输入 */
PDO_InputMapping();
}
}
/
/**
\brief 这个函数将被调用从同步的中断程序或者从mainloop当中,如果没有同步被支持
*
void APPL_Application(void)
{
Uint8 LED; // 初始化测试数据
static Uint8 prevState = 55;
LED = sDOOutputs.LEDs;
if(LED != prevState)
set_led(LED); //调用底层程序设置LED
prevState = LED;
appState = sDO1Outputs.Cmd; // 设置应用程序的状态
sDIInputs.switchs = (Uint8)Read_HVS2();
if(appState == 0)
appState = sDIInputs.switchs;//special mode to control app state by input switchs!
sAI1Inputs.info1 = 0x12345678;
sAI1Inputs.info2 = bsp_read_word(0x10);
}
void PDO_InputMapping()
{
APPL_InputMapping((UINT16*)aPdInputData);
HW_EscWriteIsr(((MEM_ADDR *) aPdInputData), nEscAddrInputData, nPdInputSize );
}
/
/**
\param pData 指针指向输入过程数据
\brief 这个函数将会拷贝从本地内存到ESC内存到硬件
*
void APPL_InputMapping(Uint16* pData)
{
Uint16 j = 0;
Uint8 *pTmpData = (Uint8 *)pData;
for (j = 0; j < sTxPDOassign.u16SubIndex0; j++)
{
switch (sTxPDOassign.aEntries[j])
{
/* TxPDO 1 */
case 0x1A00:
*pTmpData++ = sDIInputs.switchs;
break;
case 0x1A03: // 注意:可能是不对称的字节接近.
*pTmpData++ = sAI1Inputs.info1 & 0xFF;
*pTmpData++ = (sAI1Inputs.info1 & 0xFF00) >> 8;
*pTmpData++ = (sAI1Inputs.info1 & 0xFF0000) >> 16;
*pTmpData++ = (sAI1Inputs.info1 & 0xFF000000) >> 24;
*pTmpData++ = sAI1Inputs.info2 & 0xFF;
*pTmpData++ = (sAI1Inputs.info2 & 0xFF00) >> 8;
break;
}
}
}