往死里写——mainloop函数

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;
      }
   }
}


你可能感兴趣的:(往死里写——mainloop函数)