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

📄 biosport.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        case 0 :
            sprintf( buffer,
                     "Derived class: BIOSPort  "
                     "RI: %2d  CD: %2d  CTS: %2d  DSR: %2d",
                     Ri(), Cd(), Cts(), Dsr() );
            break;
        case 1 :
            Ri();
            sprintf( buffer,
                     "Parity Err: %d  "
                     "Break Det: %d  "
                     "Overrun Err: %d  "
                     "Framing Err: %d",
                     ( line_status & LSR_PARITY_ERROR ) ? 1 : 0,
                     ( line_status & LSR_BREAK_DETECT ) ? 1 : 0,
                     ( line_status & LSR_OVERRUN_ERROR ) ? 1 : 0,
                     ( line_status & LSR_FRAMING_ERROR ) ? 1 : 0 );
            break;
        default :
            return RS232_ILLEGAL_LINE_NUMBER;
    }
    return RS232_SUCCESS;
}

// The read_buffer routine is set up to continue reading in data
// as long as the data ready bit is set in the LSR.  With a true
// BIOS, this means that it will generally only read in a single
// byte before returning to the Read() routine.  It is up to the
// calling program to make sure a time value is set up so that
// multiple bytes can be read in.  Note that a BIOS emulation system
// will usually be able to feed in an entire buffer with a single
// call.

int BIOSPort::read_buffer( char *buffer, unsigned int count )
{
    union REGS rin;
    union REGS rout;

    ByteCount = 0;
    if ( error_status < 0 )
        return error_status;
    rin.x.dx = port_name;
    while ( count > 0 ) {
        rin.h.ah = 3;
        int86( 0x14, &rin, &rout );
        line_status |= rout.h.ah;
        if ( ( rout.h.ah & LSR_DATA_READY ) == 0 )
            break;
        rin.h.ah = 2;
        int86( 0x14, &rin, &rout );
        line_status |= rout.h.ah;
        if ( rout.h.ah & 0x80 )
            break;
        *buffer++ = rout.h.al;
        count--;
        ByteCount++;
    }
    *buffer = '\0';
    if ( count > 0 )
        return RS232_TIMEOUT;
    else
        return RS232_SUCCESS;
}

// Like read_buffer(), the write_buffer routine will usually only
// be able to write a single byte when using a true BIOS
// implementation.  It is up to the caller to invoke Write() with
// a long enough time delay to be able to send the entire buffer.
// A BIOS emulation system will usually be able to take in the
// entire buffer with one call to write_buffer().

int BIOSPort::write_buffer( char *buffer, unsigned int count )
{
    union REGS rin;
    union REGS rout;

    rin.x.dx = port_name;
    ByteCount = 0;
    if ( error_status < 0 )
        return error_status;
    while ( count > 0 ) {
        rin.h.ah = 3;
        int86( 0x14, &rin, &rout );
        line_status |= rout.h.ah;
        if ( ( rout.h.ah & LSR_THRE ) == 0 )
            break;
        rin.h.ah = 1;
        rin.h.al = (char) *buffer++;
        int86( 0x14, &rin, &rout );
        if ( rout.h.ah & 0x80 )
            break;
        line_status |= rout.h.ah;
        buffer++;
        count--;
        ByteCount++;
    }
    if ( count > 0 )
        return RS232_TIMEOUT;
    else
        return RS232_SUCCESS;
}

// If the THRE bit is set, there is room for one byte, if clear, there
// is room for 0 bytes.

int BIOSPort::TXSpaceFree( void )
{
    union REGS r;

    if ( error_status < RS232_SUCCESS )
        return error_status;
    r.x.dx = port_name;
    r.h.ah = 3;
    int86( 0x14, &r, &r );
    line_status |= r.h.ah;
    if ( r.h.ah & LSR_THRE )
        return 1;
    else
        return 0;
}

// If the data ready bit is set, there is one byte present in the
// buffer, else 0.

int BIOSPort::RXSpaceUsed( void )
{
    union REGS r;

    if ( error_status < RS232_SUCCESS )
        return error_status;
    r.x.dx = port_name;
    r.h.ah = 3;
    int86( 0x14, &r, &r );
    line_status |= r.h.ah;
    if ( r.h.ah & LSR_DATA_READY )
        return 1;
    else
        return 0;
}

// EBIOSPort has a few extra functions above and beyond BIOSPort.
// It has the ability to read in the old state of DTR and RTS,
// and can send a break signal.  It also has a few extra baud rates
// and other line settings.

EBIOSPort::EBIOSPort( RS232PortName port,
                      long baud_rate,
                      char parity,
                      int word_length,
                      int stop_bits,
                      int dtr,
                      int rts,
                      int xon_xoff,
                      int rts_cts,
                      int dtr_dsr )
{
    port_name = port;
    error_status = RS232_SUCCESS;

    first_debug_output_line = BIOSPort::FormatDebugOutput();
    debug_line_count = FormatDebugOutput();
    read_settings();
    saved_settings = settings;
    settings.Adjust( baud_rate,
                     parity,
                     word_length,
                     stop_bits,
                     dtr,
                     rts,
                     xon_xoff,
                     rts_cts,
                     dtr_dsr );
    break_on = 0;
    write_settings();
    line_status = 0;
}

EBIOSPort::~EBIOSPort( void )
{
}

// The only additional information that I have to offer with this
// output routine is the setting of the break flag, which will
// usually be clear.

int EBIOSPort::FormatDebugOutput( char *buffer, int line_number )
{
    if ( buffer == 0 )
        return( first_debug_output_line +  1 );
    if ( line_number < first_debug_output_line )
        return BIOSPort::FormatDebugOutput( buffer, line_number );
    switch( line_number - first_debug_output_line ) {
        case 0 :
            sprintf( buffer,
                     "Derived class: EBIOSPort  "
                     "Break flag: %2d",
                     break_on );
            break;
        default :
            return RS232_ILLEGAL_LINE_NUMBER;
    }
    return RS232_SUCCESS;
}

// There are exactly two settings that I can read here:  the state
// of Dtr and Rts.  It isn't much, but I read them both in and
// set the rest of the values to be invalid.

void EBIOSPort::read_settings( void )
{
    union REGS r;

    r.x.dx = port_name;
    r.h.ah = 5;
    r.h.al = 0;
    int86( 0x14, &r, &r );
    settings.Dtr = ( ( r.h.bl & 0x1 ) != 0 );
    settings.Rts = ( ( r.h.bl & 0x2 ) != 0 );
    settings.BaudRate = -1L;
    settings.Parity = '?';
    settings.WordLength = -1;
    settings.StopBits = -1;
    settings.XonXoff = -1;
    settings.RtsCts = -1;
    settings.DtrDsr = -1;
}

// write_settings() uses a different function for the EBIOS, so it has
// a few extra settings to support.

RS232Error EBIOSPort::write_settings( void )
{
    union REGS r;
    RS232Error status = RS232_SUCCESS;

    r.x.dx = port_name;
    r.h.ah = 4;
    if ( break_on )
        r.h.al = 1;
    else
        r.h.al = 0;
    switch ( toupper( settings.Parity ) ) {
        case 'E' : r.h.bh = 1; break;
        case 'O' : r.h.bh = 2; break;
        default  : settings.Parity = 'N';
                   status = RS232_ILLEGAL_PARITY_SETTING;
        case 'N' : r.h.bh = 0; break;
    }
    switch ( settings.StopBits ) {
        case 1  : r.h.bl = 0; break;
        default : settings.StopBits = 2;
                  status = RS232_ILLEGAL_STOP_BITS;
        case 2  : r.h.bl = 1; break;
    }
    switch ( settings.WordLength ) {
        case 5   : r.h.ch = 0; break;
        case 6   : r.h.ch = 1; break;
        case 7   : r.h.ch = 2; break;
        default  : settings.WordLength = 8;
                   status = RS232_ILLEGAL_WORD_LENGTH;
        case 8   : r.h.ch = 3; break;
    }
    switch ( settings.BaudRate ) {
        case 110L    : r.h.cl = 0x00; break;
        case 150L    : r.h.cl = 0x01; break;
        case 300L    : r.h.cl = 0x02; break;
        case 600L    : r.h.cl = 0x03; break;
        case 1200L   : r.h.cl = 0x04; break;
        case 2400L   : r.h.cl = 0x05; break;
        case 4800L   : r.h.cl = 0x06; break;
        default      : settings.BaudRate = 9600L;
                       status = RS232_ILLEGAL_BAUD_RATE;
        case 9600L   : r.h.cl = 0x07; break;
        case 19200L  : r.h.cl = 0x08; break;
    }
    int86( 0x14, &r, &r );
    r.x.dx = port_name;
    r.h.ah = 5;
    r.h.al = 1;
    r.h.bl = (unsigned char) ( ( settings.Dtr ) ? 1 : 0 );
    r.h.bl |= ( settings.Rts ) ? 2 : 0;
    int86( 0x14, &r, &r );
    if ( settings.RtsCts != -1 ) {
        settings.RtsCts = -1;
        status = RS232_RTS_CTS_NOT_SUPPORTED;
    }
    if ( settings.DtrDsr != -1 ) {
        settings.DtrDsr = -1;
        status = RS232_DTR_DSR_NOT_SUPPORTED;
    }
    if ( settings.XonXoff != -1 ) {
        settings.XonXoff = -1;
        status = RS232_XON_XOFF_NOT_SUPPORTED;
    }
    return status;
}

// EBIOSPort can set Dtr and Rts, BIOSPort can't.

int EBIOSPort::Dtr( int setting )
{
    if ( setting != UNCHANGED ) {
        settings.Dtr = ( setting != 0 );
        write_settings();
    }
    return ( settings.Dtr != 0 );
}

int EBIOSPort::Rts( int setting )
{
    if ( setting != UNCHANGED ) {
        settings.Rts = ( setting != 0 );
        write_settings();
    }
    return ( settings.Rts != 0 );
}

int EBIOSPort::Break( long milliseconds )
{
    long timer;

    if ( error_status < RS232_SUCCESS )
        return error_status;
    timer = ReadTime() + milliseconds;
    break_on = 1;
    write_settings();
    while ( ReadTime() < timer )
        IdleFunction();
    break_on = 0;
    write_settings();
    return RS232_SUCCESS;
}

RS232Error EBIOSPort::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();
}

⌨️ 快捷键说明

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