#include #include #include #include #include #include #include #include "mbmstapp.h" #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "inc/hw_uart.h" #include "inc/hw_ints.h" #include "driverlib/gpio.h" #include "driverlib/uart.h" #include "driverlib/sysctl.h" #include "driverlib/pin_map.h" #if HW_PLATFORM == HW_PLATFORM_OLS1V #include "ols1v.h" #elif HW_PLATFORM == HW_PLATFORM_EAV1V #include "eav1v.h" #else #error Unknown hardware platform! #endif // HW_PLATFORM ///////////////////////////////////////////////////////////////////////////// #define _REQ_DELAY 10 #define _METRONIK_SENSOR_SLAVE_ID 0x40 #define _NEDAP_SLAVE_ID_1 1 #define _NEDAP_SLAVE_ID_2 2 #define TID_METRONIC_ILM_READ_UV 0x0101 #define TID_METRONIC_ILM_READ_TEMP 0x0102 #define TID_METRONIC_ILM_READ_SERIAL 0x0103 #define TID_METRONIC_ILM_READ_RANGE 0x0104 #define TID_NEDAP_CLEAR_CTRS_AND_DIAGNOSTIC_REG 0x0201 #define TID_NEDAP_REPORT_SLAVE_ID 0x0202 #define TID_NEDAP_PRESET_SINGLE_REGISTER_7 0x0203 #define TID_NEDAP_WRITE_MULTIPLE_REGISTERS_7_2 0x0204 #define TID_NEDAP_RETURN_BUS_EXCEPTION_ERROR_COUNT 0x0205 #define TID_NEDAP_READ_REGISTERS_0_50 0x0206 ///////////////////////////////////////////////////////////////////////////// static HMBRTUMST g_hMbMst = NULL; static uint64_t g_nSendTick = 0; static bool g_bCTS = false; static uint16_t g_nRegs[MODBUS_MAX_READ_REGISTERS] = {0}; ///////////////////////////////////////////////////////////////////////////// static void _OnMasterStateChanged(GFA_MODBUS_RTU_MST_STATES newState, GFA_MODBUS_RTU_MST_STATES oldState) { switch(newState) { case MB_RTU_MST_Idle: // OlsClearLeds(OLS_LED_MASK); break; case MB_RTU_MST_TxStart: // OlsSetLeds(OLS_LED_GREEN_RIGHT); break; case MB_RTU_MST_TxDone: // OlsClearLeds(OLS_LED_GREEN_RIGHT); break; case MB_RTU_MST_RxSlvID: // OlsSetLeds(OLS_LED_GREEN_LEFT); break; case MB_RTU_MST_RxError: // OlsClearSetLeds(OLS_LED_MASK, OLS_LED_RED_TOP); break; case MB_RTU_MST_ReportError: // OlsClearSetLeds(OLS_LED_MASK, OLS_LED_RED_BOTTOM); break; } } ///////////////////////////////////////////////////////////////////////////// static void _RetriggerRequestTimer(void) { g_nSendTick = GfaSystickGetCount() + _REQ_DELAY; } ///////////////////////////////////////////////////////////////////////////// static bool _RequestTimerElapsed(void) { return g_nSendTick < GfaSystickGetCount(); } ///////////////////////////////////////////////////////////////////////////// static void _ReportError(uint16_t errcode) { // Report error. See gfambrtumst.h for error codes } ///////////////////////////////////////////////////////////////////////////// static void _FinishRequest(void) { _RetriggerRequestTimer(); g_bCTS = true; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static void _OnReadRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, const uint16_t *pRegs, size_t nRegCount) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... if(nTID == TID_NEDAP_READ_REGISTERS_0_50) { // ... } } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnWriteRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, uint16_t nRegStart, uint16_t nRegsWritten) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnPresetRegisterComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnDiagnosisComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, uint16_t nSubFunc, uint16_t nData) { if(err) { _ReportError(err); } else { switch(nSubFunc) { case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG: // Success! Do whatever needs to be done ... break; case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT: // Success! Do whatever needs to be done ... break; } } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnReportSlaveIDComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, const void *pData, size_t nCbData) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnReadUVComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, uint16_t nVal) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnReadTempComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, uint8_t nVal) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnReadRangeComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, uint16_t nVal) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static void _OnReadSerialComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, const uint8_t *pVal, size_t nCbVal) { if(err) { _ReportError(err); } else { // Success! Do whatever needs to be done ... } _FinishRequest(); } ///////////////////////////////////////////////////////////////////////////// static bool _DoMetronik(uint8_t nSlaveID) { static uint32_t nState = 0; bool bRet = false; switch(nState++ % 4) { case 0: bRet = GfaModbusRTUMstILMReadUV(g_hMbMst, TID_METRONIC_ILM_READ_UV, nSlaveID, _OnReadUVComplete); break; case 1: bRet = GfaModbusRTUMstILMReadTemp(g_hMbMst, TID_METRONIC_ILM_READ_TEMP, nSlaveID, _OnReadTempComplete); break; case 2: bRet = GfaModbusRTUMstILMReadSerial(g_hMbMst, TID_METRONIC_ILM_READ_SERIAL, nSlaveID, _OnReadSerialComplete); break; case 3: bRet = GfaModbusRTUMstILMReadRange(g_hMbMst, TID_METRONIC_ILM_READ_RANGE, nSlaveID, _OnReadRangeComplete); break; } return bRet; } ///////////////////////////////////////////////////////////////////////////// static bool _DoNedap(uint8_t nSlaveID, uint32_t *pnState) { bool bRet = false; switch((*pnState)++) { case 0: bRet = GfaModbusRTUMstDiagnosis(g_hMbMst, TID_NEDAP_CLEAR_CTRS_AND_DIAGNOSTIC_REG, nSlaveID, MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG, 0, _OnDiagnosisComplete); break; case 1: bRet = GfaModbusRTUMstReportSlaveID(g_hMbMst, TID_NEDAP_REPORT_SLAVE_ID, nSlaveID, 4, _OnReportSlaveIDComplete); break; case 10: bRet = GfaModbusRTUMstPresetSingleRegister(g_hMbMst, TID_NEDAP_PRESET_SINGLE_REGISTER_7, nSlaveID, 7, 0x801E, _OnPresetRegisterComplete); break; case 50: g_nRegs[0] = 0x801E; g_nRegs[1] = 0x0015; bRet = GfaModbusRTUMstWriteMultipleRegisters(g_hMbMst, TID_NEDAP_WRITE_MULTIPLE_REGISTERS_7_2, nSlaveID, 7, 2, g_nRegs, _OnWriteRegistersComplete); break; case 100: bRet = GfaModbusRTUMstDiagnosis(g_hMbMst, TID_NEDAP_RETURN_BUS_EXCEPTION_ERROR_COUNT, nSlaveID, MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT, 0, _OnDiagnosisComplete); *pnState = 1; break; default: bRet = GfaModbusRTUMstReadHoldingRegisters(g_hMbMst, TID_NEDAP_READ_REGISTERS_0_50, nSlaveID, 0, 50, _OnReadRegistersComplete); break; } return bRet; } ///////////////////////////////////////////////////////////////////////////// static void _InitUARTConfig(LPGFA_UART_CONFIG puc) { memset(puc, 0, sizeof(LPGFA_UART_CONFIG)); puc->P_UART_BASE = UART_BASE; puc->P_UART_BASE_SYSCTL = UART_BASE_SYSCTL; puc->P_UART_PORT = UART_PORT; puc->P_UART_PORT_SYSCTL = UART_PORT_SYSCTL; puc->P_UART_RX_PIN = UART_RX_PIN; puc->P_UART_RX_PIN_MUX = UART_RX_PIN_MUX; puc->P_UART_TX_PIN = UART_TX_PIN; puc->P_UART_TX_PIN_MUX = UART_TX_PIN_MUX; puc->P_UART_INT = UART_INT; puc->P_UART_INT_PRIORITY = MODBUS_RTU_UART_INT_PRIORITY; puc->P_EN_485_PORT_SYSCTL = EN_485_PORT_SYSCTL; puc->P_EN_485_PORT = EN_485_PORT; puc->P_EN_485_PIN = EN_485_PIN; puc->nBaud = MODBUS_RTU_BAUDRATE; puc->nDatabits = MODBUS_RTU_DATABITS; puc->nStopbits = MODBUS_RTU_STOPBITS; puc->parity = MODBUS_RTU_PARITY; puc->nFifoIndexRx = 0; puc->nFifoIndexTx = 1; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// bool GfaInitModbusMasterApp(void) { GFA_UART_CONFIG uartParams; g_hMbMst = NULL; _InitUARTConfig(&uartParams); if(GfaMbUartInit(&uartParams)) { GFA_MODBUS_RTU_MASTER_PARAMETERS mstParams; memset(&mstParams, 0, sizeof(mstParams)); mstParams.hFifoRX = GfaMbUartGetRxFifo(); mstParams.hFifoTX = GfaMbUartGetTxFifo(); mstParams.nRxTimeoutUs = MODBUS_RTU_MASTER_RX_TIMEOUT_US; GfaMbUartGetProtocolTimeouts(&mstParams.mpt); mstParams.appItf.pfnStateChanged = _OnMasterStateChanged; if(!(g_hMbMst = GfaModbusRTUMstCreate(&mstParams))) GfaMbUartRelease(); else g_bCTS = true; } return !!g_hMbMst; } ///////////////////////////////////////////////////////////////////////////// void GfaDoModbusMasterApp(void) { static uint32_t nLoop = 0, nStateN1 = 0, nStateN2 = 0; bool bRet = false; if(g_bCTS && _RequestTimerElapsed()) { g_bCTS = false; switch(nLoop++ % 3) { case 0: bRet = _DoMetronik(_METRONIK_SENSOR_SLAVE_ID); break; case 1: bRet = _DoNedap(_NEDAP_SLAVE_ID_1, &nStateN1); break; case 2: bRet = _DoNedap(_NEDAP_SLAVE_ID_2, &nStateN2); break; } if(!bRet) { _ReportError(GFA_MB_MST_ERROR_UNEXPECTED); _FinishRequest(); } } GfaModbusRTUMstStateMachine(g_hMbMst); } /////////////////////////////////////////////////////////////////////////////