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

📄 biosport.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ******************** START OF BIOSPORT.CPP ********************
//
// This file contains all of the code used by the BIOSPort and
// EBIOSPort classes.
//

#include <stdio.h>
#include <ctype.h>
#include "rs232.h"
#include "biosport.h"
#include "_8250.h"

// The BIOSPort constructor doesn't have very much work to do.  It
// sets all the saved settings to invalid values, since none of them
// can be accessed.  It has to set up the debug output, then set all
// of the port settings, and then return.  Note that there is no way
// to detect an error when attempting to access a BIOS port, so the
// constructor always succeeds.

BIOSPort::BIOSPort( 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 = RS232::FormatDebugOutput();
    debug_line_count = FormatDebugOutput();
    saved_settings.BaudRate = -1L;
    saved_settings.Parity = '?';
    saved_settings.WordLength = -1;
    saved_settings.StopBits = -1;
    saved_settings.Dtr = -1;
    saved_settings.Rts = -1;
    saved_settings.XonXoff = -1;
    saved_settings.RtsCts = -1;
    saved_settings.DtrDsr = -1;
    settings.Adjust( baud_rate,
                     parity,
                     word_length,
                     stop_bits,
                     dtr,
                     rts,
                     xon_xoff,
                     rts_cts,
                     dtr_dsr );
    write_settings();
    line_status = 0;
}

// The void constructor is called by the inherited class EBIOSPort when
// it is being constructed.  Since EBIOSPort will initialize all the
// settings, this constructor just initializes the debug output.
// Note that this constructor is protected, since it doesn't create a
// properly initialized port that could be used as an object by itself.

BIOSPort::BIOSPort( void )
{
    first_debug_output_line = RS232::FormatDebugOutput();
    debug_line_count = FormatDebugOutput();
}

// There is no BIOS function to close a port, so the destructor
// doesn't have to do anything.

BIOSPort::~BIOSPort( void )
{
}

// The write_settings function is fairly limited when it comes to
// options.  There are lots of opportunities for errors here.
// Note that if the constructor attempts an invalid settings, the
// error code never gets returned to the calling program, since
// the constructor doesn't return a value.

RS232Error BIOSPort::write_settings( void )
{
    union REGS r;
    RS232Error status = RS232_SUCCESS;
    r.x.dx = port_name;
    r.h.ah = 0;
    r.h.al = 0;
    switch ( toupper( settings.Parity ) ) {
        case 'E' : r.h.al |= 0x18; break;
        case 'O' : r.h.al |= 0x08; break;
        default  : settings.Parity = 'N';
                   status = RS232_ILLEGAL_PARITY_SETTING;
        case 'N' : r.h.al |= 0x00; break;
    }
    switch ( settings.StopBits ) {
        case 1  : r.h.al |= 0; break;
        default : settings.StopBits = 2;
                  status = RS232_ILLEGAL_STOP_BITS;
        case 2  : r.h.al |= 4; break;
    }
    switch ( settings.WordLength ) {
        case 5   : r.h.al |= 0; break;
        case 6   : r.h.al |= 1; break;
        case 7   : r.h.al |= 2; break;
        default  : settings.WordLength = 8;
                   status = RS232_ILLEGAL_WORD_LENGTH;
        case 8   : r.h.al |= 3; break;
    }
    switch ( settings.BaudRate ) {
        case 110L    : r.h.al |= 0x00; break;
        case 150L    : r.h.al |= 0x20; break;
        case 300L    : r.h.al |= 0x40; break;
        case 600L    : r.h.al |= 0x60; break;
        case 1200L   : r.h.al |= 0x80; break;
        case 2400L   : r.h.al |= 0xa0; break;
        case 4800L   : r.h.al |= 0xc0; break;
        default      : settings.BaudRate = 9600L;
                       status = RS232_ILLEGAL_BAUD_RATE;
        case 9600L   : r.h.al |= 0xe0; break;
    }
    int86( 0x14, &r, &r );
    if ( settings.Dtr != -1 ) {
        settings.Dtr = -1;
        status = RS232_DTR_NOT_SUPPORTED;
    }
    if ( settings.Rts != -1 ) {
        settings.Rts = -1;
        status = RS232_RTS_NOT_SUPPORTED;
    }
    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;
}

// If the data ready bit is set in the UART LSR, this routine calls
// the BIOS function to read the character.  Otherwise it returns
// a timeout.  Even if the data ready bit is set, this routine is still
// vulnerable to hanging up in a several second delay if the
// incoming DSR line is not set.

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

    if ( error_status < 0 )
        return error_status;
    r.h.ah = 3;
    r.x.dx = port_name;
    int86( 0x14, &r, &r );
    line_status |= r.h.ah;
    if ( r.h.ah & LSR_DATA_READY ) {
        r.h.ah = 2;
        r.x.dx = port_name;
        int86( 0x14, &r, &r );
        line_status |= r.h.ah;
        if ( ( r.h.ah & 0x80 ) == 0 )
            return( r.h.al );
    }
    return( RS232_TIMEOUT );
}

// This function also uses a standard BIOS function call.  It is also
// vulnerable to a delay in the event that DSR or CTS are not set.

int BIOSPort::write_byte( int c )
{
    union REGS r;

    if ( error_status < 0 )
        return error_status;
    r.x.dx = port_name;
    r.h.ah = 0x01;
    r.h.al = (char) c;
    int86( 0x14, &r, &r );
    line_status |= r.h.ah;
    if ( r.h.ah & 0x80 )
        return RS232_TIMEOUT;
    return RS232_SUCCESS;
}

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

// The next four routines all execute the BIOS call that reads
// in the MSR.  The appropriate bit is then masked out, and the
// result is returned to the calling routine.

int BIOSPort::Cd( 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;
    return ( r.h.al & MSR_CD ) != 0;
}

int BIOSPort::Ri( 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;
    return ( r.h.al & MSR_RI ) != 0;
}

int BIOSPort::Cts( 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;
    return ( r.h.al & MSR_CTS ) != 0;
}

int BIOSPort::Dsr( 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;
    return ( r.h.al & MSR_DSR ) != 0;
}

// The four routines that check line status bits operate almost
// identically to the modem status routines.  The only difference
// is that the line status bits are accumulated in a private data
// member, so instead of just checking the bit in the LSR, these
// routines have to check the current state ORed with the cumulative
// state.  In addition, each of the routines has the option of
// either leaving the bit set, or clearing it after reading it.

int BIOSPort::ParityError( int reset )
{
    union REGS r;
    int status;

    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;
    status = ( line_status & LSR_PARITY_ERROR ) != 0;
    if ( reset != UNCHANGED && reset != 0 )
        line_status &= ~LSR_PARITY_ERROR;
    return status;
}

int BIOSPort::BreakDetect( int reset )
{
    union REGS r;
    int status;

    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;
    status = ( line_status & LSR_BREAK_DETECT ) != 0;
    if ( reset != UNCHANGED && reset != 0 )
        line_status &= ~LSR_BREAK_DETECT;
    return status;
}

int BIOSPort::FramingError( int reset )
{
    union REGS r;
    int status;

    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;
    status = ( line_status & LSR_FRAMING_ERROR ) != 0;
    if ( reset != UNCHANGED && reset != 0 )
        line_status &= ~LSR_FRAMING_ERROR;
    return status;
}

int BIOSPort::HardwareOverrunError( int reset )
{
    union REGS r;
    int status;

    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;
    status = ( line_status & LSR_OVERRUN_ERROR ) != 0;
    if ( reset != UNCHANGED && reset != 0 )
        line_status &= ~LSR_OVERRUN_ERROR;
    return status;
}

// The formatted debug output for BIOSPort is sparse.  It prints out
// two lines of information that dump the states of the MSR and LSR.

int BIOSPort::FormatDebugOutput( char *buffer, int line_number )
{
    if ( buffer == 0 )
        return( first_debug_output_line +  2 );
    if ( line_number < first_debug_output_line )
        return RS232::FormatDebugOutput( buffer, line_number );
    switch( line_number - first_debug_output_line ) {

⌨️ 快捷键说明

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