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

📄 pc8250.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        _disable();
        isr_data->line_status &= ~LSR_FRAMING_ERROR;
        _enable();
    }
    return return_value;
}

int PC8250::HardwareOverrunError( int reset )
{
    int return_value;

    if ( error_status < RS232_SUCCESS )
        return error_status;
    return_value =
          ( isr_data->line_status & LSR_OVERRUN_ERROR ) ? 1 : 0;
    if ( reset != UNCHANGED && reset != 0 ) {
        _disable();
        isr_data->line_status &= ~LSR_OVERRUN_ERROR;
        _enable();
    }
    return return_value;
}

// This just reads in the status bit from the isr_data
// structure, and optionally clears it.

int PC8250::SoftwareOverrunError( int clear )
{
    int temp = isr_data->overflow;
    if ( clear ) {
        _disable();
        isr_data->overflow = 0;
        _enable();
    }
    return temp;
}

// The three handshaking functions all have approximately the
// same mode of operation.  If the setting parameter is set to
// UNCHANGED, they just return a boolean indicating whether or
// not handshaking is in effect.  If handshaking is being turned
// on or off, things become a little more complicated.  The
// major complication is that after setting the bits needed by
// the ISR to handshake, they also have to take action to make
// sure the control lines and XON/XOFF output are where they need
// to be to accurately get things started.

int PC8250::XonXoffHandshaking( int setting )
{
    if ( setting != UNCHANGED ) {
        if ( setting )
            isr_data->handshaking |= xon_xoff;
        else {
            isr_data->handshaking &= ~xon_xoff;
            isr_data->blocked &= ~xon_xoff;
// If blocking, I need to send an XON
            if ( isr_data->blocking & xon_xoff ) {
                _disable();
                if ( isr_data->send_handshake_char == -1 )
                    isr_data->send_handshake_char = XON;
                else
                    isr_data->send_handshake_char = -1;
                _enable();
            }
         // Restart TX if I was blocked, or have to send and XON
            jump_start( isr_data );
            isr_data->blocking &= ~xon_xoff;
        }
        settings.XonXoff = ( setting != 0 );
    }
    return( ( isr_data->handshaking & xon_xoff ) != 0 );
}

int PC8250::RtsCtsHandshaking( int setting )
{
    int old_setting;

    if ( setting != UNCHANGED ) {
        old_setting = isr_data->handshaking & rts_cts;
        isr_data->handshaking &= ~rts_cts;
        isr_data->blocking &= ~rts_cts;
        isr_data->blocked &= ~rts_cts;
        if ( setting ) {
            Rts( 1 );
            _disable();
            if ( ( isr_data->modem_status & MSR_CTS ) == 0 )
                isr_data->blocked |= rts_cts;
            isr_data->handshaking |= rts_cts;
            _enable();
            settings.Rts = REMOTE_CONTROL;
        } else {
            if ( old_setting )
                Rts( 1 ); //If handshaking to go off, set RTS high
            if ( isr_data->blocked == 0 )
                jump_start( isr_data );
        }
        settings.RtsCts = ( setting != 0 );
    }
    return( ( isr_data->handshaking & rts_cts ) != 0 );
}

int PC8250::DtrDsrHandshaking( int setting )
{
    int old_setting;

    if ( setting != UNCHANGED ) {
        old_setting = isr_data->handshaking & dtr_dsr;
        isr_data->handshaking &= ~dtr_dsr;
        isr_data->blocking &= ~dtr_dsr;
        isr_data->blocked &= ~dtr_dsr;
        if ( setting ) {
            Dtr( 1 );
            _disable();
            if ( ( isr_data->modem_status & MSR_DSR ) == 0 )
                isr_data->blocked |= dtr_dsr;
            isr_data->handshaking |= dtr_dsr;
            _enable();
            settings.Dtr = REMOTE_CONTROL;
        } else {
            if ( old_setting )
                Dtr( 1 ); //If handshaking to go off, set RTS high
            if ( isr_data->blocked == 0 )
                jump_start( isr_data );
        }
        settings.DtrDsr = ( setting != 0 );
    }
    return( ( isr_data->handshaking & dtr_dsr ) != 0 );
}

// Just reading the state of the control line is relatively
// easy.  The setting returned is just the stored value in the
// settings element.  However, both of the next two routines have
// to handle setting or clearing the line as well.  This only
// gets complicated if handshaking is turned on.  If it is, these
// routines refuse to play with the control lines.

int PC8250::Dtr( int setting )
{
    int mcr;

    if ( setting != UNCHANGED ) {
        if ( isr_data->handshaking & dtr_dsr )
            return PC8250_HANDSHAKE_LINE_IN_USE;
        else {
            settings.Dtr = setting;
            _disable();
            mcr = inp( isr_data->uart + MODEM_CONTROL_REGISTER );
            if ( setting )
                mcr |= MCR_DTR;
            else
                mcr &= ~MCR_DTR;
            outp( isr_data->uart + MODEM_CONTROL_REGISTER, mcr );
            _enable();
        }
    }
    return settings.Dtr;
}

int PC8250::Rts( int setting )
{
    int mcr;

    if ( setting != UNCHANGED ) {
        if ( isr_data->handshaking & rts_cts )
            return PC8250_HANDSHAKE_LINE_IN_USE;
        else {
            settings.Rts = setting;
            _disable();
            mcr = inp( isr_data->uart + MODEM_CONTROL_REGISTER );
            if ( setting )
                mcr |= MCR_RTS;
            else
                mcr &= ~MCR_RTS;
            outp( isr_data->uart + MODEM_CONTROL_REGISTER, mcr );
            _enable();
        }
    }
    return settings.Rts;
}

// PeekBuffer uses the class Queue function to read as many
// bytes as possible from the RXBuffer.

int PC8250::PeekBuffer( void *buffer, unsigned int count )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    ByteCount =
          isr_data->RXQueue.Peek( (unsigned char *) buffer, count );
    ( (char *) buffer )[ ByteCount ] = '\0';
    return RS232_SUCCESS;
}

// The next two functions just return a count using a Queue
// class primitive function.

int PC8250::RXSpaceFree( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return isr_data->RXQueue.FreeCount();
}

int PC8250::TXSpaceUsed( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return isr_data->TXQueue.InUseCount();
}

// Flushing the TX buffer is easy when using the Queue class
// primitive.

int PC8250::FlushTXBuffer( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    _disable();
    isr_data->TXQueue.Clear();
    _enable();
    return RS232_SUCCESS;
}

// The debug output routine has three possible modes.  If the
// buffer passed to it is a null, it means it should just return
// the total number of lines used by the the output, which is 6
// plus the number used by the base class.  If the line number
// requested is less than where we start, the request is passed
// up the line to the base class.  Finally, if it is one of our
// lines, the buffer is formatted and returned to the calling
// routine.

int PC8250::FormatDebugOutput( char *buffer, int line_number )
{
    if ( buffer == 0 )
        return( first_debug_output_line +  6 );
    if ( line_number < first_debug_output_line )
        return RS232::FormatDebugOutput( buffer, line_number );
    switch( line_number - first_debug_output_line ) {
        case 0 :
            sprintf( buffer,
                     "Derived class: PC8250   "
                     "UART: %04x  "
                     "Overflow: %1d  "
                     "TX Running: %1d  "
                     "Line Status: %02x",
                     isr_data->uart,
                     ( isr_data->overflow ) ? 1 : 0,
                     ( isr_data->tx_running ) ? 1 : 0,
                     isr_data->line_status );
            break;
        case 1 :
            sprintf( buffer,
                     "TX Head, Tail, Count %4d %4d %4d  "
                     "RX Head,Tail,Count %4d %4d %4d",
                     isr_data->TXQueue.Head(),
                     isr_data->TXQueue.Tail(),
                     isr_data->TXQueue.InUseCount(),
                     isr_data->RXQueue.Head(),
                     isr_data->RXQueue.Tail(),
                     isr_data->RXQueue.InUseCount() );
            break;
        case 2 :
          sprintf( buffer,
                   "Counts: TX: %5u  RX: %5u  MS: %5u  LS: %5u  "
                   "CTS/DSR/RI/CD: %d%d%d%d",
                   isr_data->tx_int_count,
                   isr_data->rx_int_count,
                   isr_data->ms_int_count,
                   isr_data->ls_int_count,
                   ( isr_data->modem_status & MSR_CTS ) ? 1 : 0,
                   ( isr_data->modem_status & MSR_DSR ) ? 1 : 0,
                   ( isr_data->modem_status & MSR_RI ) ? 1 : 0,
                   ( isr_data->modem_status & MSR_CD ) ? 1 : 0 );
          break;
        case 3 :
            sprintf( buffer,
                     "Handshake DTR/RTS/XON : %d%d%d  "
                     "Blocking: %d%d%d  "
                     "Blocked: %d%d%d  "
                     "Handshake char: %04x",
                     ( isr_data->handshaking & dtr_dsr ) ? 1 : 0,
                     ( isr_data->handshaking & rts_cts ) ? 1 : 0,
                     ( isr_data->handshaking & xon_xoff ) ? 1 : 0,
                     ( isr_data->blocking & dtr_dsr ) ? 1 : 0,
                     ( isr_data->blocking & rts_cts ) ? 1 : 0,
                     ( isr_data->blocking & xon_xoff ) ? 1 : 0,
                     ( isr_data->blocked & dtr_dsr ) ? 1 : 0,
                     ( isr_data->blocked & rts_cts ) ? 1 : 0,
                     ( isr_data->blocked & xon_xoff ) ? 1 : 0,
                     isr_data->send_handshake_char );
            break;
        case 4 :
          sprintf( buffer,
                   "Parity Err: %d  "
                   "Break Det: %d  "
                   "Overrun Err: %d  "
                   "Framing Err: %d  "
                   "FIFO Setting: %2d",
                   ( isr_data->line_status & LSR_PARITY_ERROR )
                      ? 1 : 0,
                   ( isr_data->line_status & LSR_BREAK_DETECT )
                      ? 1 : 0,
                   ( isr_data->line_status & LSR_OVERRUN_ERROR )
                      ? 1 : 0,
                   ( isr_data->line_status & LSR_FRAMING_ERROR )
                      ? 1 : 0,
                   fifo_setting );
          break;
        case 5 :
            char *uart_name;
            switch( isr_data->uart_type ) {
                case UART_8250  : uart_name = "8250";    break;
                case UART_16550 : uart_name = "16550";   break;
                default         : uart_name = "Unknown"; break;
            }
            sprintf( buffer,
                     "Uart type: %-7s",
                     uart_name );
            break;
        default :
            return RS232_ILLEGAL_LINE_NUMBER;
    }
    return RS232_SUCCESS;
}

// Just like the debug format routine, ErrorName has to pass
// most requests up the line to the base class, saving only a few
// for it to respond to.

char * PC8250::ErrorName( int error )
{
    if ( error < RS232_NEXT_FREE_ERROR && error >= RS232_ERROR )
        return RS232::ErrorName( error );
    if (error < RS232_NEXT_FREE_WARNING && error >= RS232_WARNING)
        return RS232::ErrorName( error );
    if ( error >= RS232_SUCCESS )
        return RS232::ErrorName( error );
    switch ( error ) {
        case PC8250_UART_NOT_FOUND        :
                return( "UART not found" );
        case PC8250_HANDSHAKE_LINE_IN_USE :
                return( "Handshake line in use" );
        default                           :
                return( "Undefined error" );
    }
}

⌨️ 快捷键说明

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