中国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
查看资料  发短消息 网志   编辑帖子  回复  引用回复

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


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



论坛跳转: