/* Create an interrupt handler for the receive interrupt for your target * processor. This function should then call pxMBFrameCBByteReceived( ). The * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the * character. */ interrupt void prvvUARTRxISR( void ) { #if (TEST == TEST_RX) char cByte; (void) xMBPortSerialGetByte(&cByte); #else pxMBFrameCBByteReceived( ); #endif PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack }
BOOL xMBASCIIReceiveFSM( void ) { BOOL xNeedPoll = FALSE; UCHAR ucByte; UCHAR ucResult; assert( eSndState == STATE_TX_IDLE ); ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); switch ( eRcvState ) { /* A new character is received. If the character is a ':' the input * buffer is cleared. A CR-character signals the end of the data * block. Other characters are part of the data block and their * ASCII value is converted back to a binary representation. */ case STATE_RX_RCV: /* Enable timer for character timeout. */ vMBPortTimersEnable( ); if( ucByte == ':' ) { /* Empty receive buffer. */ eBytePos = BYTE_HIGH_NIBBLE; usRcvBufferPos = 0; } else if( ucByte == MB_ASCII_DEFAULT_CR ) { eRcvState = STATE_RX_WAIT_EOF; } else { ucResult = prvucMBCHAR2BIN( ucByte ); switch ( eBytePos ) { /* High nibble of the byte comes first. We check for * a buffer overflow here. */ case BYTE_HIGH_NIBBLE: if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) { ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 ); eBytePos = BYTE_LOW_NIBBLE; break; } else { /* not handled in Modbus specification but seems * a resonable implementation. */ eRcvState = STATE_RX_IDLE; /* Disable previously activated timer because of error state. */ vMBPortTimersDisable( ); } break; case BYTE_LOW_NIBBLE: ucASCIIBuf[usRcvBufferPos] |= ucResult; usRcvBufferPos++; eBytePos = BYTE_HIGH_NIBBLE; break; } } break; case STATE_RX_WAIT_EOF: if( ucByte == ucMBLFCharacter ) { /* Disable character timeout timer because all characters are * received. */ vMBPortTimersDisable( ); /* Receiver is again in idle state. */ eRcvState = STATE_RX_IDLE; /* Notify the caller of eMBASCIIReceive that a new frame * was received. */ xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED ); } else if( ucByte == ':' ) { /* Empty receive buffer and back to receive state. */ eBytePos = BYTE_HIGH_NIBBLE; usRcvBufferPos = 0; eRcvState = STATE_RX_RCV; /* Enable timer for character timeout. */ vMBPortTimersEnable( ); } else { /* Frame is not okay. Delete entire frame. */ eRcvState = STATE_RX_IDLE; } break; case STATE_RX_IDLE: if( ucByte == ':' ) { /* Enable timer for character timeout. */ vMBPortTimersEnable( ); /* Reset the input buffers to store the frame. */ usRcvBufferPos = 0;; eBytePos = BYTE_HIGH_NIBBLE; eRcvState = STATE_RX_RCV; } break; } return xNeedPoll; }
void main( void ) { eMBErrorCode eStatus; /* Use external 32.768 Hz crystal to generate 4.194.304 Hz bus clock */ ICGC1 = 0x38; // ??=0,RANGE=0,REFS=1,CLKS=1:1,OSCSTEN=0,??=0:0 while( ICGS2_DCOS == 0 ); #if 0 /* Test code for porting */ #if 1 /* Timer test * Comment out call to pxMBPortCBTimerExpired() in prvvTIMERExpiredISR when testing the timer */ /* Disable the COP watchdog */ SOPT = 0x53; // COPE=0,COPT=1,STOPE=0,??=1:0:0,BKGDPE=1,??=1 ( void )xMBPortTimersInit( 20000 ); EnableInterrupts; for( ;; ) { vMBPortTimersEnable( ); _Wait; // wait for an interrupt /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; PTFDD_PTFDD0 = 1; } #else /* Receiver test * Comment out call to pxMBFrameCBByteReceived() in prvvUARTRxISR() when testing the receiver */ /* Disable the COP watchdog */ SOPT = 0x53; // COPE=0,COPT=1,STOPE=0,??=1:0:0,BKGDPE=1,??=1 /* Enable the receiver. */ assert( xMBPortSerialInit( 0, 9600, 8, MB_PAR_NONE ) ); EnableInterrupts; for( ;; ) { UCHAR ucByte; vMBPortSerialEnable( TRUE, FALSE ); _Wait; // wait for an interrupt assert( xMBPortSerialGetByte( &ucByte ) ); /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; PTFDD_PTFDD0 = 1; /* Transmitter test * Comment out call to pxMBFrameCBTransmitterEmpty() in prvvUARTTxReadyISR() when testing the transmitter */ #if 0 vMBPortSerialEnable( FALSE, TRUE ); assert( xMBPortSerialPutByte( ucByte ) ); _Wait; // wait for an interrupt /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; #endif // Transmitter test } #endif // Receiver test #else /* Demo * NOTE: Make sure the callbacks in the three ISPs have been restored after above testing */ /* Initialization */ eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN ); // eStatus = eMBInit( MB_ASCII, 0x0A, 0, 38400, MB_PAR_EVEN ); /* Enable the Modbus Protocol Stack. */ eStatus = eMBEnable( ); /* Start polling */ EnableInterrupts; for( ;; ) { /* Poll for Modbus events */ ( void )eMBPoll( ); /* Count the number of polls */ usRegInputBuf[0]++; /* Count the number of timer overflows */ if( TPM1SC_TOF ) { TPM1SC_TOF = 0; ENTER_CRITICAL_SECTION( ); if( ++usRegInputBuf[1] == 0 ) // Happens every 2 seconds usRegInputBuf[2]++; // Happens every 36.4 hours EXIT_CRITICAL_SECTION( ); } /* Keep the COP watchdog happy */ __RESET_WATCHDOG( ); } #endif // Test code when porting }