www.pudn.com > ethercat-slave-source-code.rar > el9800appl.c, change:2013-05-03,size:17506b
/** \addtogroup EL9800Appl EL9800 application @{ */ /** \file el9800appl.c \author EthercatSSC@beckhoff.com \brief Implementation \version 5.10 <br>Changes to version V5.01:<br> V5.10 ECAT6: Add "USE_DEFAULT_MAIN" to enable or disable the main function<br> <br>Changes to version V5.0:<br> V5.01 EL9800 2: Add TxPdo Parameter object 0x1802<br> <br>Changes to version V4.30:<br> V4.50 ECAT2: Create generic application interface functions. Documentation in Application Note ET9300.<br> V4.50 COE2: Handle invalid PDO assign values.<br> V4.30 : create file */ /*----------------------------------------------------------------------------------------- ------ ------ Includes ------ -----------------------------------------------------------------------------------------*/ #include "ecat_def.h" #if EL9800_APPLICATION #include "ecatslv.h" #if COE_SUPPORTED #include "objdef.h" #endif #include "el9800hw.h" #define _EVALBOARD_ #include "el9800appl.h" #undef _EVALBOARD_ /*-------------------------------------------------------------------------------------- ------ ------ local types and defines ------ --------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------- ------ ------ local variables and constants ------ -----------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------- ------ ------ application specific functions ------ -----------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------- ------ ------ generic functions ------ -----------------------------------------------------------------------------------------*/ ///////////////////////////////////////////////////////////////////////////////////////// /** \brief The function is called when an error state was acknowledged by the master *//////////////////////////////////////////////////////////////////////////////////////// void APPL_AckErrorInd(UINT16 stateTrans) { } ///////////////////////////////////////////////////////////////////////////////////////// /** \return AL Status Code (see ecatslv.h ALSTATUSCODE_....) \brief The function is called in the state transition from INIT to PREOP when all general settings were checked to start the mailbox handler. This function informs the application about the state transition, the application can refuse the state transition when returning an AL Status error code. The return code NOERROR_INWORK can be used, if the application cannot confirm the state transition immediately, in that case the application need to be complete the transition by calling ECAT_StateChange. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StartMailboxHandler(void) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \return 0, NOERROR_INWORK \brief The function is called in the state transition from PREEOP to INIT to stop the mailbox handler. This functions informs the application about the state transition, the application cannot refuse the state transition. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StopMailboxHandler(void) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \param pIntMask pointer to the AL Event Mask which will be written to the AL event Mask register (0x204) when this function is succeeded. The event mask can be adapted in this function \return AL Status Code (see ecatslv.h ALSTATUSCODE_....) \brief The function is called in the state transition from PREOP to SAFEOP when all general settings were checked to start the input handler. This function informs the application about the state transition, the application can refuse the state transition when returning an AL Status error code. The return code NOERROR_INWORK can be used, if the application cannot confirm the state transition immediately, in that case the application need to be complete the transition by calling ECAT_StateChange. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StartInputHandler(UINT16 *pIntMask) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \return 0, NOERROR_INWORK \brief The function is called in the state transition from SAFEOP to PREEOP to stop the input handler. This functions informs the application about the state transition, the application cannot refuse the state transition. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StopInputHandler(void) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \return AL Status Code (see ecatslv.h ALSTATUSCODE_....) \brief The function is called in the state transition from SAFEOP to OP when all general settings were checked to start the output handler. This function informs the application about the state transition, the application can refuse the state transition when returning an AL Status error code. The return code NOERROR_INWORK can be used, if the application cannot confirm the state transition immediately, in that case the application need to be complete the transition by calling ECAT_StateChange. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StartOutputHandler(void) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \return 0, NOERROR_INWORK \brief The function is called in the state transition from OP to SAFEOP to stop the output handler. This functions informs the application about the state transition, the application cannot refuse the state transition. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_StopOutputHandler(void) { return ALSTATUSCODE_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// /** \return 0(ALSTATUSCODE_NOERROR), NOERROR_INWORK \param pInputSize pointer to save the input process data length \param pOutputSize pointer to save the output process data length \brief This function calculates the process data sizes from the actual SM-PDO-Assign and PDO mapping *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize) { #if COE_SUPPORTED UINT16 result = ALSTATUSCODE_NOERROR; UINT16 PDOAssignEntryCnt = 0; OBJCONST TOBJECT OBJMEM * pPDO = NULL; UINT16 PDOSubindex0 = 0; UINT32 *pPDOEntry = NULL; UINT16 PDOEntryCnt = 0; UINT16 InputSize = 0; UINT16 OutputSize = 0; /*Scan object 0x1C12 RXPDO assign*/ for(PDOAssignEntryCnt = 0; PDOAssignEntryCnt < sRxPDOassign.u16SubIndex0; PDOAssignEntryCnt++) { pPDO = OBJ_GetObjectHandle(sRxPDOassign.aEntries[PDOAssignEntryCnt]); if(pPDO != NULL) { PDOSubindex0 = *((UINT16 *)pPDO->pVarPtr); for(PDOEntryCnt = 0; PDOEntryCnt < PDOSubindex0; PDOEntryCnt++) { pPDOEntry = (UINT32 *)((UINT8 *)pPDO->pVarPtr + (OBJ_GetEntryOffset((PDOEntryCnt+1),pPDO)>>3)); //goto PDO entry // we increment the expected output size depending on the mapped Entry OutputSize += (UINT16) ((*pPDOEntry) & 0xFF); } } else { /*assigned PDO was not found in object dictionary. return invalid mapping*/ OutputSize = 0; result = ALSTATUSCODE_INVALIDOUTPUTMAPPING; break; } } OutputSize = (OutputSize + 7) >> 3; if(result == 0) { /*Scan Object 0x1C13 TXPDO assign*/ for(PDOAssignEntryCnt = 0; PDOAssignEntryCnt < sTxPDOassign.u16SubIndex0; PDOAssignEntryCnt++) { pPDO = OBJ_GetObjectHandle(sTxPDOassign.aEntries[PDOAssignEntryCnt]); if(pPDO != NULL) { PDOSubindex0 = *((UINT16 *)pPDO->pVarPtr); for(PDOEntryCnt = 0; PDOEntryCnt < PDOSubindex0; PDOEntryCnt++) { pPDOEntry = (UINT32 *)((UINT8 *)pPDO->pVarPtr + (OBJ_GetEntryOffset((PDOEntryCnt+1),pPDO)>>3)); //goto PDO entry // we increment the expected output size depending on the mapped Entry InputSize += (UINT16) ((*pPDOEntry) & 0xFF); } } else { /*assigned PDO was not found in object dictionary. return invalid mapping*/ InputSize = 0; result = ALSTATUSCODE_INVALIDINPUTMAPPING; break; } } } InputSize = (InputSize + 7) >> 3; *pInputSize = InputSize; *pOutputSize = OutputSize; return result; #else *pInputSize = 6; *pOutputSize = 2; return ALSTATUSCODE_NOERROR; #endif } ///////////////////////////////////////////////////////////////////////////////////////// /** \param pData pointer to input process data \brief This function will copies the inputs from the local memory to the ESC memory to the hardware *//////////////////////////////////////////////////////////////////////////////////////// #if _PIC18 && AL_EVENT_ENABLED /* the pragma interrupt_level is used to tell the compiler that these functions will not be called at the same time from the main function and the interrupt routine */ #pragma interrupt_level 1 #endif void APPL_InputMapping(UINT16* pData) { UINT16 j = 0; UINT16 *pTmpData = (UINT16 *)pData; /* we go through all entries of the TxPDO Assign object to get the assigned TxPDOs */ for (j = 0; j < sTxPDOassign.u16SubIndex0; j++) { switch (sTxPDOassign.aEntries[j]) { /* TxPDO 1 */ case 0x1A00: *pTmpData++ = SWAPWORD(((UINT16 *) &sDIInputs)[1]); break; /* TxPDO 3 */ case 0x1A02: *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[1]); *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[2]); break; } } } ///////////////////////////////////////////////////////////////////////////////////////// /** \param pData pointer to output process data \brief This function will copies the outputs from the ESC memory to the local memory to the hardware *//////////////////////////////////////////////////////////////////////////////////////// #if _PIC18 && AL_EVENT_ENABLED /* the pragma interrupt_level is used to tell the compiler that these functions will not be called at the same time from the main function and the interrupt routine */ #pragma interrupt_level 1 #endif void APPL_OutputMapping(UINT16* pData) { UINT16 j = 0; UINT16 *pTmpData = (UINT16 *)pData; /* we go through all entries of the RxPDO Assign object to get the assigned RxPDOs */ for (j = 0; j < sRxPDOassign.u16SubIndex0; j++) { switch (sRxPDOassign.aEntries[j]) { /* RxPDO 2 */ case 0x1601: ((UINT16 *) &sDOOutputs)[1] = SWAPWORD(*pTmpData++); break; } } } ///////////////////////////////////////////////////////////////////////////////////////// /** \brief This function will called from the synchronisation ISR or from the mainloop if no synchronisation is supported *//////////////////////////////////////////////////////////////////////////////////////// void APPL_Application(void) { #if _PIC18 UINT16 analogValue; #endif LED_1 = sDOOutputs.bLED1; LED_2 = sDOOutputs.bLED2; LED_3 = sDOOutputs.bLED3; LED_4 = sDOOutputs.bLED4; #if _PIC24 LED_5 = sDOOutputs.bLED5; LED_7 = sDOOutputs.bLED7; LED_6 = sDOOutputs.bLED6; LED_8 = sDOOutputs.bLED8; #endif sDIInputs.bSwitch1 = SWITCH_1; sDIInputs.bSwitch2 = SWITCH_2; sDIInputs.bSwitch3 = SWITCH_3; sDIInputs.bSwitch4 = SWITCH_4; #if _PIC24 sDIInputs.bSwitch5 = SWITCH_5; sDIInputs.bSwitch6 = SWITCH_6; sDIInputs.bSwitch7 = SWITCH_7; sDIInputs.bSwitch8 = SWITCH_8; #endif /* start the conversion of the A/D converter */ #if _PIC24 AD1CON1bits.SAMP = 0; // start Converting while (!AD1CON1bits.DONE);// conversion done? sAIInputs.i16Analoginput = ADC1BUF0; // yes then get ADC value #else GODONE=1; while(GODONE); /* store the analog value */ ((UINT8 *) &analogValue)[0] = ADRESL; ((UINT8 *) &analogValue)[1] = ADRESH; sAIInputs.i16Analoginput = analogValue; #endif /* we toggle the TxPDO Toggle after updating the data of the corresponding TxPDO */ sAIInputs.bTxPDOToggle ^= 1; /* we simulate a problem of the analog input, if the Switch4 is on in this example, in this case the TxPDO State has to set to indicate the problem to the master */ if ( sDIInputs.bSwitch4 ) sAIInputs.bTxPDOState = 1; else sAIInputs.bTxPDOState = 0; } ///////////////////////////////////////////////////////////////////////////////////////// /** \param index index of the requested object. \param subindex subindex of the requested object. \param objSize size of the requested object data, calculated with OBJ_GetObjectLength \param pData Pointer to the buffer where the data can be copied to \param bCompleteAccess Indicates if a complete read of all subindices of the object shall be done or not \return ABORTIDX_XXX \brief Handles SDO read requests to TxPDO Parameter *//////////////////////////////////////////////////////////////////////////////////////// UINT8 ReadObject0x1802( UINT16 index, UINT8 subindex, UINT32 dataSize, UINT16 MBXMEM * pData, UINT8 bCompleteAccess ) { if(bCompleteAccess) return ABORTIDX_UNSUPPORTED_ACCESS; if(subindex == 0) { *pData = TxPDO1802Subindex0; } else if(subindex == 6) { /*clear destination buffer (no excluded TxPDO set)*/ if(dataSize > 0) MBXMEMSET(pData,0x00,dataSize); } else if(subindex == 7) { /*min size is one Byte*/ UINT8 *pu8Data = (UINT8*)pData; //Reset Buffer *pu8Data = 0; *pu8Data = sAIInputs.bTxPDOState; } else if(subindex == 9) { /*min size is one Byte*/ UINT8 *pu8Data = (UINT8*)pData; //Reset Buffer *pu8Data = 0; *pu8Data = sAIInputs.bTxPDOToggle; } else return ABORTIDX_SUBINDEX_NOT_EXISTING; return 0; } #if EXPLICIT_DEVICE_ID ///////////////////////////////////////////////////////////////////////////////////////// /** \return The Explicit Device ID of the EtherCAT slave \brief Calculate the Explicit Device ID *//////////////////////////////////////////////////////////////////////////////////////// UINT16 APPL_GetDeviceID() { UINT16 Value = (UINT16)(SWITCH_8<<7)|(SWITCH_7<<6)|(SWITCH_6<<5)|(SWITCH_5<<4)|(SWITCH_4<<3)|(SWITCH_3<<2)|(SWITCH_2<<1)|(SWITCH_1); return Value; } #endif /*ECATCHANGE_START(V5.10) ECAT6*/ #if USE_DEFAULT_MAIN /*ECATCHANGE_END(V5.10) ECAT6*/ ///////////////////////////////////////////////////////////////////////////////////////// /** \brief This is the main function *//////////////////////////////////////////////////////////////////////////////////////// #if _PIC24 int main(void) #else void main(void) #endif { /* initialize the Hardware and the EtherCAT Slave Controller */ HW_Init(); MainInit(); bRunApplication = TRUE; do { MainLoop(); } while (bRunApplication == TRUE); HW_Release(); #if _PIC24 return 0; #endif } #endif //#if USE_DEFAULT_MAIN #endif //#if EL9800_APPLICATION /** @} */