⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbascii.c

📁 modbus的例程,非常不错,大家可以
💻 C
📖 第 1 页 / 共 2 页
字号:
                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] = 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;
                        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;
}

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( 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( *pucSndBufferCur >> 4 );
                        xMBPortSerialPutByte( ucByte );
                        eBytePos = BYTE_LOW_NIBBLE;
                        break;

                    case BYTE_LOW_NIBBLE:
                        ucByte = prvucMBBIN2CHAR( *pucSndBufferCur & 0x0F );
                        xMBPortSerialPutByte( 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( 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;
    }

    return xNeedPoll;
}

BOOL
xMBASCIITimerT1SExpired( void )
{
    switch ( eRcvState )
    {
            /* If we have a timeout we go back to the idle state and wait for
             * the next frame.
             */
        case STATE_RX_RCV:
        case STATE_RX_WAIT_EOF:
            eRcvState = STATE_RX_IDLE;
            break;

        default:
            assert( ( eRcvState == STATE_RX_RCV )
                    || ( eRcvState == STATE_RX_WAIT_EOF ) );
            break;
    }
    vMBPortTimersDisable(  );

    /* no context switch required. */
    return FALSE;
}


UCHAR
prvucMBCHAR2BIN( UCHAR ucCharacter )
{
    if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) )
    {
        return ucCharacter - '0';
    }
    else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) )
    {
        return ucCharacter - 'A' + 0x0A;
    }
    else
    {
        return 0xFF;
    }
}

UCHAR
prvucMBBIN2CHAR( UCHAR ucByte )
{
    if( ucByte <= 0x09 )
    {
        return '0' + ucByte;
    }
    else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) )
    {
        return ucByte - 0x0A + 'A';
    }
    else
    {
        /* Programming error. */
        assert( 0 );
    }
    return '0';
}


UCHAR
prvucMBLRC( UCHAR * pucFrame, USHORT usLen )
{
    UCHAR           ucLRC = 0;  /* LRC char initialized */

    while( usLen-- )
    {
        ucLRC += *pucFrame++;   /* Add buffer byte without carry */
    }

    /* Return twos complement */
    ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) );
    return ucLRC;
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -