/** * Start ModBus master */ void eMBRTUStart(void) { DEBUG_PUTSTRING("MODBUS Start"); ENTER_CRITICAL_SECTION( ); /* Initially the receiver is in the state STATE_RX_INIT. we start * the timer and if no character is received within t3.5 we change * to STATE_RX_IDLE. This makes sure that we delay startup of the * modbus protocol stack until the bus is free. */ eRcvState = STATE_RX_INIT; vMBPortSerialEnable( TRUE, FALSE ); vMBPortTimersEnable( ); EXIT_CRITICAL_SECTION( ); /* Give the target an initial kick */ xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); sleep(2); }
/* Create an interrupt handler for the transmit buffer empty interrupt * (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character. */ interrupt void prvvUARTTxReadyISR( void ) { static unsigned int uiCnt = 0; #if (TEST == TEST_TX) if(uiCnt++ < 10) xMBPortSerialPutByte('a'); else vMBPortSerialEnable(false,false); #elif (TEST == NO_TEST) pxMBFrameCBTransmitterEmpty( ); #endif PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack }
BOOL xMBASCIITransmitFSM( void ) { BOOL xNeedPoll = FALSE; UCHAR ucByte; assert( eRcvState == STATE_RX_IDLE ); switch ( eSndState ) { /* Start of transmission. The start of a frame is defined by sending * the character ':'. */ case STATE_TX_START: ucByte = ':'; xMBPortSerialPutByte( ( CHAR )ucByte ); eSndState = STATE_TX_DATA; eBytePos = BYTE_HIGH_NIBBLE; break; /* Send the data block. Each data byte is encoded as a character hex * stream with the high nibble sent first and the low nibble sent * last. If all data bytes are exhausted we send a '\r' character * to end the transmission. */ case STATE_TX_DATA: if( usSndBufferCount > 0 ) { switch ( eBytePos ) { case BYTE_HIGH_NIBBLE: ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) ); xMBPortSerialPutByte( ( CHAR ) ucByte ); eBytePos = BYTE_LOW_NIBBLE; break; case BYTE_LOW_NIBBLE: ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) ); xMBPortSerialPutByte( ( CHAR )ucByte ); pucSndBufferCur++; eBytePos = BYTE_HIGH_NIBBLE; usSndBufferCount--; break; } } else { xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR ); eSndState = STATE_TX_END; } break; /* Finish the frame by sending a LF character. */ case STATE_TX_END: xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter ); /* We need another state to make sure that the CR character has * been sent. */ eSndState = STATE_TX_NOTIFY; break; /* Notify the task which called eMBASCIISend that the frame has * been sent. */ case STATE_TX_NOTIFY: eSndState = STATE_TX_IDLE; xNeedPoll = xMBPortEventPost( EV_FRAME_SENT ); /* Disable transmitter. This prevents another transmit buffer * empty interrupt. */ vMBPortSerialEnable( TRUE, FALSE ); eSndState = STATE_TX_IDLE; break; /* We should not get a transmitter event if the transmitter is in * idle state. */ case STATE_TX_IDLE: /* enable receiver/disable transmitter. */ vMBPortSerialEnable( TRUE, FALSE ); break; }
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 }