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

📄 comm.cpp

📁 串行通信编程源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ******************************************************************** //
//                                                                      //
//      COMM.CPP                                                        //
//      Copyright (c) 1993, Michael Holmes and Bob Flanders             //
//      C++ Communication Utilities                                     //
//                                                                      //
//      Chapter 7: Receiving a FAX                                      //
//      Last changed in chapter 7                                       //
//                                                                      //
//      This file contains the functions to implement the basic         //
//      communications class and facilities.  Each instance of the      //
//      Comm class will control a single communications port.           //
//                                                                      //
// ******************************************************************** //


class Comm
    {
    public:
        Comm(int b,                         // define a comm instance
             int i,                         //   base addr, interrupt
             int d,                         //   baud rate divisor
             int l,                         //   line control setting
             int fc = 0,                    //   flow control flag
             UINT si = 3200,                //   input queue size
             UINT so = 1500);               //   and output queue size
        UINT Read(char *c,                  // read a character from queue
                  char *m,                  // ..and get modem status reg
                  char *l),                 //   and line status register
             Set8n(void),                   // set 8 data bits, no parity
             ICount(void),                  // get depth of input queue
             OCount(void),                  // ..or output queue
             IFree(void),                   // free space in input queue
             OFree(void);                   // ..or output queue
        int  Modem(void),                   // rtn modem status register
             ModemChanged(void),            // rtn TRUE if msr changed
             IFlow(void),                   // rtn input flow ctrl status
             IEmpty(void),                  // rtn TRUE if input queue
             OEmpty(void);                  // ..or output queue empty
        long GetSpeed(void);                // rtn current speed in bps
        void SetSpeed(int d),               // set up port's divisor
             SetBPS(long s),                // set up port's speed
             SetLine(int l),                // ..and line control register
             Write(int c),                  // write a character
             Write(char *s),                // ..or a string of characters
             Write(char *s, int l),         // ..or a block of characters
             IClear(void),                  // clear input queue
             OClear(void),                  // ..and output queue
             DTR(long t = 1500L),           // lower DTR temporarily
             RTS(int),                      // RTS signal control
             IntRoutine(void);              // interrupt service routine
       ~Comm();                             // destructor

    private:
        UINT base,                          // base port address
             irq,                           // interrupt number
             divisor,                       // baud rate divisor
             line,                          // initial line control
             i_size,                        // input buffer size
             o_size,                        // output buffer size
             i_start,                       // flow ctl restart limit
             i_stop,                        // ..and upper stop limit
             i_count,                       // characters in input queue
             o_count,                       // ..and output queue
             Deque(void);                   // deque an output queue char
        char *i_buf,                        // input buffer
             *i_get,                        // ..and nxt user get location
             *i_put,                        // ..and nxt comm put location
             *i_limit,                      // ..and last location
             *i_last,                       // ..and last i_put location
             i_of,                          // ..and input overflow flag
             *o_buf,                        // output buffer
             *o_get,                        // ..and nxt comm get location
             *o_put,                        // ..and nxt user put location
             *o_limit,                      // ..and last location
             msr_changed,                   // msr changed flag
             int_msr,                       // last interrupt msr
             int_lsr,                       // ..and last interrupt lsr
             fifo,                          // 16550 flag
             flow,                          // flow control enable flag
             o_flow,                        // output flow controlled flag
             i_flow,                        // input flow controlled flag
             empty_trans;                   // empty transmitter flag
        void InstallInt(void),              // install interrupt svc rtn
             DeInstallInt(void),            // de-install interrupt rtn
             SetLimits(void),               // set up flow ctl limits
             CheckFifo(void),               // set up fifo flags
             Queue(int c,                   // queue char to input queue
                   int m,                   //   saving modem status reg
                   int l),                  //   and line status register
             interrupt (*old_comm)(...);    // old comm interrupt pointer
    };


extern
Comm   *comm;                               // current Comm instance
void    interrupt far comm_int(...);        // comm interrupt routine



/* ******************************************************************** *
 *
 *  Comm -- define communications port instance
 *
 * ******************************************************************** */

Comm::Comm(int b,                           // comm port base address
           int i,                           // interrupt number
           int d,                           // baud rate divisor
           int l,                           // line control setting
           int fc,                          // flow control flag
           UINT si,                         // input queue size
           UINT so)                         // output queue size
{
UINT    max_size = 64535U / 3;              // max number of input chars

base = b;                                   // set up instance base addr
irq = i;                                    // ..interrupt request
o_size = so;                                // ..output buffer size
flow = fc;                                  // ..flow control flag
CheckFifo();                                // ..fifo flag if available
SetSpeed(d);                                // ..line speed
SetLine(l);                                 // ..line format

if (si < 512)                               // q. less than .5k of buffer?
    si = 512;                               // a. yes .. set to minimum

if (si > max_size)                          // q. greater than maximum?
    si = max_size;                          // a. yes .. set to max size

if (so < 256)                               // q. really small output buf?
    so = 256;                               // a. yes .. set to minimum

i_size = si;                                // save input buffer size
empty_trans = 1;                            // ..set empty transmitter flag
msr_changed = 1;                            // ..set msr changed flag
o_flow = i_flow = 0;                        // ..clear active flags
o_count = i_count = 0;                      // ..and current queue counts

i_buf = i_get = i_put =                     // allocate input buffer
            new char[i_size * 3];           // ..for data, lsr and msr
i_limit = i_buf + (i_size - 1) * 3;         // ..set limit address
memset(i_buf, 0, i_size * 3);               // ..and clear area to nulls

o_buf = o_get = o_put = new char[o_size];   // allocate output buffer
o_limit = o_buf + o_size - 1;               // ..set limit address
memset(o_buf, 0, o_size);                   // ..and clear area to nulls

SetLimits();                                // set up flow ctl limits
InstallInt();                               // ..and interrupt routine

int_msr = IN(MSR);                          // set up initial MSR

}



/* ******************************************************************** *
 *
 *  SetLimits -- set up receive buffer flow control limits
 *
 *  This routine sets up the flow control limits for receive
 *  operations.  Flow control will be asserted when the buffer
 *  reaches a point when there is not enough room to receive
 *  a second worth of data in the input buffer.  Flow control will
 *  be de-asserted when 50% of the upper limit is read by the
 *  application.
 *
 * ******************************************************************** */

void    Comm::SetLimits(void)
{

i_stop = (UINT) (115200L / 10) / divisor;   // get 1 second in characters

if (i_stop > i_size)                        // q. limit too high?
    i_stop = i_size / 2;                    // a. yes .. set at half
 else
    i_stop = i_size - i_stop;               // else .. set limit point

i_start = i_stop / 2;                       // set restart point at 50%

}



/* ******************************************************************** *
 *
 *  CheckFifo -- if UART is a 16550, set FIFO variable to true
 *
 * ******************************************************************** */

void    Comm::CheckFifo(void)
{

fifo = 0;                                   // assume standard uart
OUT(FCR, 0xcf);                             // try to enable FIFOs

if ((IN(IIR) & 0xc0) != 0xc0)               // q. FIFO bits found?
    return;                                 // a. no .. just return

OUT(FCR, 0);                                // turn off FIFOs
fifo = 1;                                   // set fifo available flag

}



/* ******************************************************************** *
 *
 *  SetSpeed -- set up port baud rate divisor
 *
 * ******************************************************************** */

void    Comm::SetSpeed(int d)               // baud rate divisor
{

divisor = d;                                // save divisor for later
OUT(IER, 0);                                // clear interrupts enable

if (fifo)                                   // q. is UART a 16550 chip?
    OUT(FCR, FCR_16550);                    // a. yes .. enable fifo

IN(LSR);                                    // read/reset line status reg
IN(MSR);                                    // ..and modem status register
IN(IIR);                                    // ..and interrupt id register
IN(RBR);                                    // ..and receive buffer reg

__asm   cli                                 // stop interrupts
OUT(LCR, IN(LCR) | LCR_DLAB);               // set divisor latch bit
OUT(DLM, d >> 8);                           // out msb portion of divisor
OUT(DLL, d & 0xff);                         // ..then the lsb portion
OUT(LCR, IN(LCR) & ~LCR_DLAB);              // clear divisor latch bit
OUT(MCR, MCR_DO);                           // enable DTR, OUT2 and RTS
__asm   sti                                 // ..and interrupts

OUT(IER, IER_RBF | IER_TBE | IER_MSI);      // then enable UART interrupts

}



/* ******************************************************************** *
 *
 *  SetBPS -- set port's speed
 *
 * ******************************************************************** */

void    Comm::SetBPS(long s)                // speed in BPS
{

SetSpeed((int)(115200L / s));               // calc and set divisor

}



/* ******************************************************************** *
 *
 *  GetSpeed -- retrieve current port speed
 *
 * ******************************************************************** */

long   Comm::GetSpeed(void)
{

return((long) (115200L / (long) divisor));  // return current speed

}



/* ******************************************************************** *
 *
 *  SetLine -- set up port's line control register
 *
 * ******************************************************************** */

void    Comm::SetLine(int l)                // new line control setting
{

line = l & ~LCR_DLAB;                       // save new value in instance
OUT(LCR, line);                             // ..and write new LCR

}



⌨️ 快捷键说明

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