中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 【求助】这个 串口通信控制 Class For Dos 怎样用?
作者:
标题: 【求助】这个 串口通信控制 Class For Dos 怎样用? 上一主题 | 下一主题
KookEu
新手上路





积分 13
发帖 4
注册 2005-8-6
状态 离线
『楼 主』:  【求助】这个 串口通信控制 Class For Dos 怎样用?

在一份产品的设计文档中找到一个封装成 Class 的串口通信 for DOS 的 C++代码,可少了 GSERIAL.CPP 文件, 加上对 C++ 不熟悉, 不知道怎样用,
请各位大大帮帮忙,看看怎用,最好能帮忙写个 Demo.谢谢!

/*---------------------------------------------------------------------*
FILENAME: GSERIAL.H
This file is used to define const and class for GSERIAL.CPP
TC++ 3.0 for DOS
*--------------------------------------------------------------------*/

#define COM1            1
#define COM2            2
#define COM3            3
#define COM4            4
#define COM5            5
#define COM6            6

#define COM1BASE        0x3F8   /*  Base port address for COM1  */
#define COM2BASE        0x2F8   /*  Base port address for COM2  */
#define COM3BASE        0x3E8   /*  Base port address for COM3  */
#define COM4BASE        0x2E8   /*  Base port address for COM4  */
#define COM5BASE        0x3A8   /*  Base port address for COM5  */
#define COM6BASE        0x2A8   /*  Base port address for COM6  */

/*
The 8250 UART has 10 registers accessible through 7 port addresses.
Here are their addresses relative to COM1BASE and COM2BASE. Note
that the baud rate registers, (DLL) and (DLH) are active only when
the Divisor-Latch Access-Bit (DLAB除数锁存器访问位) is on. The (DLAB)
is bit 7 of the (LCR--Line Control Register线路控制寄存器).

* TXR Output data to the serial port.
* RXR Input data from the serial port.
* LCR Initialize the serial port.
* IER Controls interrupt generation.
* IIR Identifies interrupts.
* MCR Send contorl signals to the modem.
* LSR Monitor the status of the serial port.
* MSR Receive status of the modem.
* DLL Low byte of baud rate divisor.
* DHH High byte of baud rate divisor.
*/

/*The following is the adress of the registers               DLAB status    */

#define TXR             0       /*  Transmit register (WRITE)   0           */
#define RXR             0       /*  Receive register  (READ)    0           */
#define IER             1       /*  Interrupt Enable            x           */
#define IIR             2       /*  Interrupt ID                x           */
#define LCR             3       /*  Line control                x           */
#define MCR             4       /*  Modem control               x           */
#define LSR             5       /*  Line Status                 x           */
#define MSR             6       /*  Modem Status                x           */


#define DLL             0       /*  Divisor Latch Low           1           */
#define DLH             1       /*  Divisor latch High          1           */

/*-------------------------------------------------------------------*
Bit values held in the Line Control Register (LCR).
bit     meaning
---     -------
0-1     00=5 bits, 01=6 bits, 10=7 bits, 11=8 bits. /word length select bit
2       Stop bits.                                  /
3       0=parity off, 1=parity on.                  /Parity Enable=1
4       0=parity odd, 1=parity even.                /Odd or Even select
5       Sticky parity.                              /
6       Set break.
7       Toggle port addresses.                      /1:access
*-------------------------------------------------------------------*/

#define LCR_NO_PARITY       0x00
#define LCR_EVEN_PARITY     0x18
#define LCR_ODD_PARITY      0x08

/*-------------------------------------------------------------------*
Bit values held in the Line Status Register (LSR).
bit     meaning
---     -------
0       Data ready.
1       Overrun error - Data register overwritten.
2       Parity error - bad transmission.
3       Framing error - No stop bit was found.
4       Break detect - End to transmission requested.
5       Transmitter holding register is empty.
6       Transmitter shift register is empty.
7               Time out - off line.
*-------------------------------------------------------------------*/

#define LSR_RCVRDY          0x01
#define LSR_OVRERR          0x02
#define LSR_PRTYERR         0x04
#define LSR_FRMERR          0x08
#define LSR_BRKERR          0x10
#define LSR_XMTRDY          0x20
#define LSR_XMTRSR          0x40
#define LSR_TIMEOUT         0x80


/*-------------------------------------------------------------------*
Bit values held in the Modem Output Control Register (MCR).
bit         meaning
---     -------
0       Data Terminal Ready. Computer ready to go.
1       Request To Send. Computer wants to send data.
2       auxillary output #1.
3       auxillary output #2.(Note: This bit must be
                  set to allow the communications card to send
                  interrupts to the system)
4       UART ouput looped back as input.
5-7     not used.
*------------------------------------------------------------------*/

#define MCR_DTR             0x01
#define MCR_RTS             0x02
#define MCR_INT             0x08

/*------------------------------------------------------------------*
Bit values held in the Modem Input Status Register (MSR).
bit     meaning
---     -------
0       delta Clear To Send.
1       delta Data Set Ready.
2       delta Ring Indicator.
3       delta Data Carrier Detect.
4       Clear To Send.
5       Data Set Ready.
6       Ring Indicator.
7       Data Carrier Detect.
*------------------------------------------------------------------*/

#define MSR_CTS             0x10
#define MSR_DSR             0x20

/*------------------------------------------------------------------*
Bit values held in the Interrupt Enable Register (IER).
bit     meaning
---     -------
0       Interrupt when data received.
1       Interrupt when transmitter holding reg. empty.
2       Interrupt when data reception error.
3       Interrupt when change in modem status register.
4-7     Not used.
*------------------------------------------------------------------*/

#define IER_RX_INT          0x01
#define IER_TX_INT          0x02

/*------------------------------------------------------------------*
Bit values held in the Interrupt Identification Register (IIR).
bit     meaning
---     -------
0       Interrupt pending
1-2             Interrupt ID code
00=Change in modem status register,
01=Transmitter holding register empty,
10=Data received,
11=reception error, or break encountered.
3-7     Not used.
*------------------------------------------------------------------*/

#define IIR_MS_ID           0x00   // Modem status
#define IIR_RX_ID           0x04   // Rceived data OK,and to read the receive buffer
#define IIR_TX_ID           0x02   // Transmitter holding register empty
#define IIR_MASK            0x07   // Get the low 3 bits of IIR

/*------------------------------------------------------------------*
These are the port addresses of the 8259 Programmable Interrupt
Controller (PIC).
*------------------------------------------------------------------*/

#define PIC8259_IMR             0x21   /* Interrupt Mask Register port */
#define PIC8259_ICR             0x20   /* Interrupt Control Port       */

/*------------------------------------------------------------------*
An end of interrupt needs to be sent to the Control Port of
the 8259 when a hardware interrupt ends.
*------------------------------------------------------------------*/

#define PIC8259_EOI            0x20   /* End Of Interrupt */

/*------------------------------------------------------------------*
The (IMR) tells the (PIC) to service an interrupt only if it
is not masked (FALSE).
*------------------------------------------------------------------*/

#define IRQ3            0xF7  /* COM2 */
#define IRQ4            0xEF  /* COM1 */
[ Last edited by KookEu on 2005-8-10 at 20:08 ]

2005-8-7 10:17
查看资料  发短消息 网志   编辑帖子  回复  引用回复
KookEu
新手上路





积分 13
发帖 4
注册 2005-8-6
状态 离线
『第 2 楼』:  


class serial{
        int  flag;
        int  SetSerial();
        int  SetOthers(int Parity, int Bits, int StopBit);
        int  SetSpeed(int Speed);
        int  SetPort(int Port);
        void init_serial(void);
        void comm_on(void);
        void comm_off(void);
public:
        serial(int Port, int Speed, int Parity, int Bits, int StopBit);
        serial &operator<<( char ch );
        serial &operator<<( char *str );
        serial &operator>>( char &ch );
        ~serial();
};

#define VERSION 0x0101
#define FALSE               0
#define TRUE                1
#define NO_ERROR            0       /* No error               */
#define BUF_OVFL            1       /* Buffer overflowed      */
#define IBUF_LEN            2048    // Incoming buffer
#define OBUF_LEN            1024    // Outgoing buffer

extern int            SError          = NO_ERROR;
extern int            portbase        = 0;
extern void           interrupt(*oldvects[2])(...);

//  char  ccbuf[SBUFSIZ];

unsigned int   startbuf        = 0;
unsigned int   endbuf          = 0;
unsigned int   inhead          = 0;
unsigned int   intail          = 0;
unsigned int   outhead         = 0;
unsigned int   outtail         = 0;
char  inbuf[IBUF_LEN];         // in buffer
char  outbuf[OBUF_LEN];        // out buffer

void           interrupt(*oldvects[2])(...);

/*  get status of the port  */
int read_status_com(int portn)
{
        return(inp(portn+5));
}

/*  send one valid char from the port  */
void send_char_com(int portn,int cc)
{
        while ((read_status_com(portn) & 0x40) == 0);
        outportb(portn,cc);
}

/*  send one string from the port  */

void send_string_com(int portn,int strlen,unsigned char *buf)
{
        int k;  k=0;
        do {
                send_char_com(portn,*(buf + k)); k++;
        } while ((k < strlen));
}

void interrupt com_int(...)
{
        int temp;
        disable();
        temp = (inportb(portbase+IIR)) & IIR_MASK;              // why interrupt was called
        switch(temp)
        {
        case 0x00:  // modem status changed
                inportb(portbase+MSR);   // read in useless char
                break;
        case 0x02:  // Request To Send char
                if (outhead != outtail)                         // there's a char to send
                {
                        outportb(portbase+TXR,outbuf[outhead++]);   // send the character
                        if (outhead == OBUF_LEN)
                                outhead=0;                              // if at end of buffer, reset pointer
                }
                break;
        case 0x04:  // character ready to be read in
                inbuf[inhead++] = inportb(portbase+RXR);// read character into inbuffer
                if (inhead == IBUF_LEN) // if at end of buffer
                        inhead=0;           // reset pointer
                break;
        case 0x06:  // line status has changed
                inportb(portbase+LSR);     // read in useless char
                break;

        default:
                break;
        }
        outportb(PIC8259_ICR, PIC8259_EOI); // Signal end of hardware interrupt
        enable();                           // reenable interrupts at the end of the handler
}

// Inserts the character to be outputted into the output buffer, checking
// for an open slot in the output buffer array.  If there is, insert
// the character, or if there isn't, wait until a slot opens up.

serial& serial::operator<<(char ch )
{
        if (ch)                             // If this is a valid char
        {
                enable();                       // turn on irqs to ensure data output
                //outportb(portbase + MCR,  MCR_INT | MCR_DTR | MCR_RTS);//modem control,
                outportb(portbase + IER,  IER_RX_INT);

                // check buffer, and if full, wait for an available opening
                //  fprintf(stdout,"\n %c is pressed!\n",ch);   //You can use this to verify which key is hit during your test
                while((outhead-1==outtail) ||(outtail==OBUF_LEN-1 && outhead==0));
                disable();                      // make sure nothing happens while changing buffer
                outbuf[outtail++] = ch;         // insert character into buffer;
                if (outtail == OBUF_LEN)        // if at end of out buffer
                        outtail = 0;                // reset pointer
                if((inportb(portbase+IER)&IER_TX_INT) == 0)
                        outportb(portbase+IER,IER_TX_INT | IER_RX_INT);
                enable();                       // re-enable interrupts
        }
        return(*this);
}

serial &serial::operator<<(char *str)
// Outputs a string to the serial port
{

        while (*str)
        {
                (*this) << (*str);
                str++;
        }
        return(*this);
}

serial &serial::operator>>( char &ch )
// Returns either the character to be received from modem if there is one
// waiting in the buffer, or returns a 0 if there is no character waiting.
{
        if (inhead != intail)               // there is a character
        {
                disable();                        // disable irqs while getting char
                ch = inbuf[intail++];             // get character from buffer
                if (intail == IBUF_LEN)         // if at end of in buffer
                        intail=0;                   // reset pointer
                enable();                        // re-enable interrupt
                return(*this);                   // return the char
        }
        ch = -1;
        return(*this);                       // return nothing
}

/* Install our functions to handle communications */

void setvects(void)
{
        oldvects[0] = getvect(0x0B);
        oldvects[1] = getvect(0x0C);
        setvect(0x0B, com_int);
        setvect(0x0C, com_int);
}

/* Uninstall our vectors before exiting the program */
void resvects(void)
{
        setvect(0x0B, oldvects[0]);
        setvect(0x0C, oldvects[1]);
}

/* Tell modem that we're ready to go */
void serial::comm_on(void)

{

        int temp, pnum;

        disable();
        temp = inportb(portbase + MCR) | 0x0f;//MCR_INT;
        outportb(portbase + MCR, temp);
        temp = (inportb(portbase + IER)) | IER_RX_INT;//|IER_TX_INT;
        outportb(portbase + IER, temp);
        pnum = (portbase == COM1BASE ? COM1 : COM2);
        temp = inportb(PIC8259_IMR) & (pnum == COM1 ? IRQ4 : IRQ3);
        outportb(PIC8259_IMR, temp);
        // temp = inportb(portbase + MCR) | MCR_DTR | MCR_RTS;
        // outportb(portbase + MCR, temp);
        enable();
}

/* Go off-line */

void serial::comm_off(void)
{
        int  temp;

        disable();
        temp = inportb(PIC8259_IMR) | ~IRQ3 | ~IRQ4;
        outportb(PIC8259_IMR, temp);
        outportb(portbase + IER, 0);
        outportb(portbase + MCR, 0);
        enable();
}



void serial::init_serial(void)
{
        endbuf = startbuf = 0;
        setvects();
        comm_on();
}

serial::~serial()
{
        comm_off();
        resvects();
}

/* Set the port number to use */
int serial::SetPort(int Port)
{
        int  Offset, far *RS232_Addr;
        switch (Port)
        { /* Sort out the base address */
        case COM1 :
                Offset = 0x0000;
                break;
        case COM2 :
                Offset = 0x0002;
                break;
        default   :
                printf("\ncannot find the serial port.\n");
                return (-1);
        }

        RS232_Addr = (int far *)MK_FP(0x0040, Offset);  /* Find out where the port is. */
        if (*RS232_Addr == NULL)
        {
                printf("\ncannot find the serial port.\n");
                return (-1);                     /* If NULL then port not used. */
        }

        portbase = *RS232_Addr;              /* Otherwise set portbase      */
        return (0);
}

/* This routine sets the speed; will accept funny baud rates. */
/* Setting the speed requires that the DLAB be set on.        */

int serial::SetSpeed(int Speed)
{
        char    c;
        int     divisor;


        if (Speed == 0)            /* Avoid divide by zero */
                return (-1);
        else
                divisor = (int) (115200L/Speed);

        if (portbase == 0)
                return (-1);



        disable();
        c = inportb(portbase + LCR);
        outportb(portbase + LCR, (c | 0x80)); /* Set DLAB */
        outportb(portbase + DLL, (divisor & 0x00FF));
        outportb(portbase + DLH, ((divisor >> 8) & 0x00FF));
        outportb(portbase + LCR, c);          /* Reset DLAB */
        enable();

        return (0);
}

/* Set other communications parameters */

int serial::SetOthers(int Parity, int Bits, int StopBit)
{
        int  setting;

        if (portbase == 0)
                return (-1);

        if (Bits < 5 || Bits > 8)
                return (-1);

        if (StopBit != 1 && StopBit != 2)
                return (-1);

        if (Parity != LCR_NO_PARITY && Parity != LCR_ODD_PARITY && Parity != LCR_EVEN_PARITY)
                return (-1);

        setting  = Bits-5;
        setting |= ((StopBit == 1) ? 0x00 : 0x04);
        setting |= Parity;

        disable();
        outportb(portbase + LCR, setting);
        enable();

        return (0);

}

/* Set up the port */

serial::serial(int Port, int Speed, int Parity, int Bits, int StopBit)
{
        flag = 0;

        if (SetPort(Port))
                flag = -1;

        if (SetSpeed(Speed))
                flag = -1;

        if (SetOthers(Parity, Bits, StopBit))
                flag = -1;

        if (!flag)
                init_serial();
}

/*  Control-Break interrupt handler */

int c_break(void)
{
        int temp;

        disable();

        temp = inportb(PIC8259_IMR) | ~IRQ3 | ~IRQ4;

        outportb(PIC8259_IMR, temp);
        outportb(portbase + IER, 0);
        outportb(portbase + MCR, 0);

        enable();

        fprintf(stderr, "\nStill online.\n");
        return(0);
}


2005-8-10 20:09
查看资料  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: