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

📄 pc8250.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 3 页
字号:

int PC8250::write_buffer( char *buffer, unsigned int count )
{
    ByteCount = 0;
    if ( error_status < 0 )
        return error_status;
    for ( ; ; ) {
        if ( count == 0 )
            break;
        if ( !isr_data->TXQueue.Insert( *buffer ) )
            break;
        buffer++;
        count--;
        ByteCount++;
    }
    if ( !isr_data->tx_running && !isr_data->blocked )
        jump_start( isr_data );
    if ( count > 0 )
        return RS232_TIMEOUT;
    else
        return RS232_SUCCESS;
}

// The Queue functions make it easy to flush the RX queue.
// After emptying it all, we need to be sure that handshaking
// gets managed.

int PC8250::FlushRXBuffer( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    _disable();
    isr_data->RXQueue.Clear();
    _enable();
    check_rx_handshaking();
    return RS232_SUCCESS;

}

// write_settings() is a protected routine called by the
// constructor and the public Set() function.   It is long and
// stringy, mostly because setting up the UART is just a long
// case of setting or clearing bits in control registers.  It
// might be possible to modularize this code, but it wouldn't be
// particularly useful.

RS232Error PC8250::write_settings( void )
{
    int lcr;
    int divisor_high;
    int divisor_low;
    RS232Error status = RS232_SUCCESS;
    long result_baud;

    if ( settings.BaudRate <= 0 || settings.BaudRate > 115200L ) {
        settings.BaudRate = 9600;
        status = RS232_ILLEGAL_BAUD_RATE;
    }
    divisor_low = (int) ( ( 115200L / settings.BaudRate ) & 0xff );
    divisor_high = (int) ( ( 115200L / settings.BaudRate ) >> 8 );
    result_baud = 115200L / ( 115200L / settings.BaudRate );
    if ( result_baud != settings.BaudRate ) {
        settings.BaudRate = result_baud;
        status = RS232_ILLEGAL_BAUD_RATE;
    }
    lcr = inp( isr_data->uart + LINE_CONTROL_REGISTER );
    lcr |= LCR_DLAB;
    _disable();
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    outp( isr_data->uart + DIVISOR_LATCH_LOW, divisor_low );
    outp( isr_data->uart + DIVISOR_LATCH_HIGH, divisor_high );
    lcr &= ~LCR_DLAB;
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    _enable();
    lcr &= ~LCR_PARITY_MASK;
    switch ( toupper( settings.Parity ) ) {
        case 'O' :
            lcr |= LCR_PARITY_ENABLE;
            break;
        case 'E' :
            lcr |= LCR_PARITY_ENABLE + LCR_EVEN_PARITY_SELECT;
            break;
        case 'M' :
            lcr |= LCR_PARITY_ENABLE + LCR_STICK_PARITY;
            break;
        case 'S' :
            lcr |= LCR_PARITY_ENABLE +
                   LCR_EVEN_PARITY_SELECT +
                   LCR_STICK_PARITY;
            break;
        default :
            settings.Parity = 'N';
            status = RS232_ILLEGAL_PARITY_SETTING;
        case 'N' :
            break;
    }
    lcr &= ~LCR_WORD_LENGTH_MASK;
    switch ( settings.WordLength ) {
        case 5 :
            break;
        case 6 :
            lcr |= LCR_WORD_LENGTH_SELECT_0;
            break;
        case 7 :
            lcr |= LCR_WORD_LENGTH_SELECT_1;
            break;
        default :
            settings.WordLength = 8;
            status = RS232_ILLEGAL_WORD_LENGTH;
        case 8 :
            lcr |= LCR_WORD_LENGTH_SELECT_0 +
                   LCR_WORD_LENGTH_SELECT_1;
            break;
    }
    lcr &= ~LCR_STOP_BITS;
    switch ( settings.StopBits ) {
        default :
            settings.StopBits = 1;
            status = RS232_ILLEGAL_STOP_BITS;
        case 1 :
            break;
        case 2 :
            lcr |= LCR_STOP_BITS;
            break;
    }
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    return status;
}

// read_settings() is the protected inverse of
// write_settings().  This routine just reads in the state of the
// UART into a settings object.  This is done when the routine
// starts up, so that the RS232 class will always have the saved
// settings available for restoration when the RS232 port is
// closed.

void PC8250::read_settings( void )
{
    int lcr;
    int mcr;
    int divisor_low;
    int divisor_high;

    lcr = inp( isr_data->uart + LINE_CONTROL_REGISTER );
    lcr |= LCR_DLAB;
    _disable();
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    divisor_low = inp( isr_data->uart + DIVISOR_LATCH_LOW );
    divisor_high = inp( isr_data->uart + DIVISOR_LATCH_HIGH );
    lcr &= ~LCR_DLAB;
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    _enable();

    if ( divisor_high | divisor_low )
        settings.BaudRate =
                115200L / ( ( divisor_high << 8 ) + divisor_low );
    else
        settings.BaudRate = -1;
    switch ( lcr & LCR_PARITY_MASK ) {
        case LCR_PARITY_ENABLE :
            settings.Parity = 'O';
            break;
        case LCR_PARITY_ENABLE + LCR_EVEN_PARITY_SELECT :
            settings.Parity = 'E';
            break;
        case LCR_PARITY_ENABLE + LCR_STICK_PARITY :
            settings.Parity = 'M';
            break;
        case LCR_PARITY_ENABLE +
             LCR_EVEN_PARITY_SELECT +
             LCR_STICK_PARITY :
            settings.Parity = 'S';
            break;
        default :
            settings.Parity = 'N';
            break;
    }
    switch ( lcr & LCR_WORD_LENGTH_MASK ) {
        case 0 :
            settings.WordLength = 5;
            break;
        case LCR_WORD_LENGTH_SELECT_0 :
            settings.WordLength = 6;
            break;
        case LCR_WORD_LENGTH_SELECT_1 :
            settings.WordLength = 7;
            break;
        case LCR_WORD_LENGTH_SELECT_0 + LCR_WORD_LENGTH_SELECT_1 :
            settings.WordLength = 8;
            break;
    }
    switch ( lcr & LCR_STOP_BITS ) {
        case 0 :
            settings.StopBits = 1;
            break;
        default :
            settings.StopBits = 2;
            break;
    }
    mcr = inp( isr_data->uart + MODEM_CONTROL_REGISTER );
    settings.Dtr = ( mcr & MCR_DTR ) != 0;
    settings.Rts = ( mcr & MCR_RTS ) != 0;
    settings.XonXoff = -1;
    settings.RtsCts = -1;
    settings.DtrDsr = -1;
}

// Set() takes advantage of code used by the constructor to
// set up some of the UART parameters.

RS232Error PC8250::Set( long baud_rate,
                        int parity,
                        int word_length,
                        int stop_bits )
{
    settings.Adjust( baud_rate,
                     parity,
                     word_length,
                     stop_bits,
                     UNCHANGED,
                     UNCHANGED,
                     UNCHANGED,
                     UNCHANGED,
                     UNCHANGED );
    return write_settings();
}

// This virtual routine is easily handled by a Queue member
// function.

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

// The same thing is true here.

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

// The 8250 UART doesn't have an intelligent BREAK function,
// so we have to just sit on the line while the BREAK goes out.
// Hopefully the IdleFunction() can do something useful while
// this takes place.

int PC8250::Break( long milliseconds )
{
    int lcr;
    long timer;

    if ( error_status < RS232_SUCCESS )
        return error_status;
    timer = ReadTime() + milliseconds;
    lcr = inp( isr_data->uart + LINE_CONTROL_REGISTER);
    lcr |= LCR_SET_BREAK;
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    while ( ReadTime() < timer )
        IdleFunction();
    lcr &= ~LCR_SET_BREAK;
    outp( isr_data->uart + LINE_CONTROL_REGISTER, lcr );
    return RS232_SUCCESS;
}

// The four modem status functions just check the bits that
// were read in the last time a modem status interrupt took
// place, and return them to the calling routine.

int PC8250::Cd( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return ( isr_data->modem_status & MSR_CD ) ? 1 : 0;
}

int PC8250::Ri( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return ( isr_data->modem_status & MSR_RI ) ? 1 : 0;
}

int PC8250::Cts( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return ( isr_data->modem_status & MSR_CTS ) ? 1 : 0;
}

int PC8250::Dsr( void )
{
    if ( error_status < RS232_SUCCESS )
        return error_status;
    return ( isr_data->modem_status & MSR_DSR ) ? 1 : 0;
}

// The four line status routines are similar to the modem
// status routines in that they just check a bit in a data
// member.  However, they also have an optional parameter that
// can be used to clear the error flag.  This is just a matter of
// clearing the same bit.

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

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

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

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

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

    if ( error_status < RS232_SUCCESS )
        return error_status;
    return_value =
          ( isr_data->line_status & LSR_FRAMING_ERROR ) ? 1 : 0;
    if ( reset != UNCHANGED && reset != 0 ) {

⌨️ 快捷键说明

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