Beispiel #1
0
void
eMBRTUStart( void )
{
    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(  );
}
Beispiel #2
0
/**
 * 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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
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
}