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

📄 ibmcom.c

📁 串行通信C语言代码,用于DOS下编程,比较完整
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *				   ibmcom.c				     *
 *****************************************************************************
 * DESCRIPTION:	This file contains a set of routines for doing low-level     *
 *		serial communications on the IBM PC.  It was translated	     *
 *		directly from Wayne Conrad's IBMCOM.PAS version 3.1, with    *
 *		the goal of near-perfect functional correspondence between   *
 *		the Pascal and C versions.				     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Original translation from IBMCOM.PAS, with *
 *				  liberal plagiarism of comments from the    *
 *				  Pascal.				     *
 *****************************************************************************/

#include	<stdio.h>
#include	<dos.h>
#include	"ibmcom.h"

/*****************************************************************************
 *			       8250 Definitions				     *
 *****************************************************************************/

/*      Offsets to various 8250 registers.  Taken from IBM Technical         */
/*      Reference Manual, p. 1-225                                           */

#define TXBUFF  0                       /* Transmit buffer register */
#define RXBUFF  0                       /* Receive buffer register */
#define DLLSB   0                       /* Divisor latch LS byte */
#define DLMSB   1                       /* Divisor latch MS byte */
#define IER     1                       /* Interrupt enable register */
#define IIR     2                       /* Interrupt ID register */
#define LCR     3                       /* Line control register */
#define MCR     4                       /* Modem control register */
#define LSR     5                       /* Line status register */
#define MSR     6                       /* Modem status register */

/*      Modem control register bits                                          */

#define DTR     0x01                    /* Data terminal ready */
#define RTS     0x02                    /* Request to send */
#define OUT1    0x04                    /* Output #1 */
#define OUT2    0x08                    /* Output #2 */
#define LPBK    0x10                    /* Loopback mode bit */

/*      Modem status register bits                                           */

#define DCTS    0x01                    /* Delta clear to send */
#define DDSR    0x02                    /* Delta data set ready */
#define TERI    0x04                    /* Trailing edge ring indicator */
#define DRLSD   0x08                    /* Delta Rx line signal detect */
#define CTS     0x10                    /* Clear to send */
#define DSR     0x20                    /* Data set ready */
#define RI      0x40                    /* Ring indicator */
#define RLSD    0x80                    /* Receive line signal detect */

/*      Line control register bits                                           */

#define DATA5   0x00                    /* 5 Data bits */
#define DATA6   0x01                    /* 6 Data bits */
#define DATA7   0x02                    /* 7 Data bits */
#define DATA8   0x03                    /* 8 Data bits */

#define STOP1   0x00                    /* 1 Stop bit */
#define STOP2   0x04                    /* 2 Stop bits */

#define NOPAR   0x00                    /* No parity */
#define ODDPAR  0x08                    /* Odd parity */
#define EVNPAR  0x18                    /* Even parity */
#define STKPAR  0x28                    /* Stick parity */
#define ZROPAR	0x38			/* Zero parity */

/*      Line status register bits                                            */

#define RDR     0x01                    /* Receive data ready */
#define ERRS    0x1E                    /* All the error bits */
#define TXR     0x20                    /* Transmitter ready */

/*      Interrupt enable register bits                                       */

#define DR      0x01                    /* Data ready */
#define THRE    0x02                    /* Tx buffer empty */
#define RLS     0x04                    /* Receive line status */

/*****************************************************************************
 *			       Names for Numbers			     *
 *****************************************************************************/

#define MAX_PORT	4

#define TRUE		1
#define FALSE		0

/*****************************************************************************
 *				  Global Data				     *
 *****************************************************************************/

/*  UART i/o addresses.  Values depend upon which COMM port is selected  */

int	uart_data;		/* Data register */
int	uart_ier;		/* Interrupt enable register */
int	uart_iir;		/* Interrupt identification register */
int	uart_lcr;		/* Line control register */
int	uart_mcr;		/* Modem control register */
int	uart_lsr;		/* Line status register */
int	uart_msr;		/* Modem status register */

char	com_installed;		/* Flag: Communications routines installed */
int	intnum;			/* Interrupt vector number for chosen port */
char	i8259bit;		/* 8259 bit mask */
char	old_i8259_mask;		/* Copy as it was when we were called */
char	old_ier;		/* Modem register contents saved for */
char	old_mcr;		/*  restoring when we're done */
void interrupt (*old_vector)();	/* Place to save COM1 vector */

/*  Transmit queue.  Characters to be transmitted are held here until the  */
/*  UART is ready to transmit them.  */

#define TX_QUEUE_SIZE	16	/* Transmit queue size.  Change to suit */

char	tx_queue[TX_QUEUE_SIZE];
int	tx_in;			/* Index of where to store next character */
int	tx_out;			/* Index of where to retrieve next character */
int	tx_chars;		/* Count of characters in queue */

/*  Receive queue.  Received characters are held here until retrieved by  */
/*  com_rx()  */

#define RX_QUEUE_SIZE	4096	/* Receive queue size.  Change to suit */

char	rx_queue[RX_QUEUE_SIZE];
int	rx_in;			/* Index of where to store next character */
int	rx_out;			/* Index of where to retrieve next character */
int	rx_chars;		/* Count of characters in queue */

/*****************************************************************************
 *				 com_install()				     *
 *****************************************************************************
 * DESCRIPTION:	Installs the communications drivers.			     *
 *									     *
 * SYNOPSIS:	status = com_install(int portnum);			     *
 *		int	portnum;	Desired port number		     *
 *		int	status;		0 = Successful installation	     *
 *					1 = Invalid port number	   	     *
 *					2 = No UART for specified port	     *
 *					3 = Drivers already installed	     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from IBMCOM.PAS		     *
 *****************************************************************************/

const int	uart_base[] =	{ 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
const char	intnums[] =	{ 0x0C,  0x0B,  0x0C,  0x0B };
const char	i8259levels[] =	{ 4,     3,     4,     3 };

int com_install(int portnum) {

    if (com_installed)				/* Drivers already installed */
	return 3;
    if ((portnum < 1) || (portnum > MAX_PORT))	/* Port number out of bounds */
	return 1;

    uart_data = uart_base[portnum-1];		/* Set UART I/O addresses */
    uart_ier  = uart_data + IER;		/*  for the selected comm */
    uart_iir  = uart_data + IIR;		/*  port */
    uart_lcr  = uart_data + LCR;
    uart_mcr  = uart_data + MCR;
    uart_lsr  = uart_data + LSR;
    uart_msr  = uart_data + MSR;
    intnum    = intnums[portnum-1];		/* Ditto for interrupt */
    i8259bit  = 1 << i8259levels[portnum-1];	/*  vector and 8259 bit mask */

    old_ier = inportb(uart_ier);		/* Return an error if we */
    outportb(uart_ier, 0);			/*  can't access the UART */
    if (inportb(uart_ier) != 0)
	return 2;

    disable();					/* Save the original 8259 */
    old_i8259_mask = inportb(0x21);		/*  mask, then disable the */
    outportb(0x21, old_i8259_mask | i8259bit);	/*  8259 for this interrupt */
    enable();

    com_flush_tx();				/* Clear the transmit and */
    com_flush_rx();				/*  receive queues */

    old_vector = getvect(intnum);		/* Save old COMM vector, */
    setvect(intnum, &com_interrupt_driver);	/*  then install a new one, */
    com_installed = TRUE;			/*  and note that we did */

    outportb(uart_lcr, DATA8 + NOPAR + STOP1);	/* 8 data, no parity, 1 stop */

    disable();					/* Save MCR, then enable */
    old_mcr = inportb(uart_mcr);		/*  interrupts onto the bus, */
    outportb(uart_mcr,				/*  activate RTS and leave */
	     (old_mcr & DTR) | (OUT2 + RTS));	/*  DTR the way it was */
    enable();

    outportb(uart_ier, DR);			/* Enable receive interrupts */

    disable();					/* Now enable the 8259 for */
    outportb(0x21, inportb(0x21) & ~i8259bit);	/*  this interrupt */
    enable();
    return 0;					/* Successful installation */
    }						/* End com_install() */

/*****************************************************************************
 *				 com_deinstall()				     *
 *****************************************************************************
 * DESCRIPTION:	Deinstalls the communications drivers completely, without     *
 *		changing the baud rate or DTR.  It tries to leave the        *
 *		interrupt vectors and enables and everything else as they    *
 *		were when the driver was installed.			     *
 *									     *
 * NOTE:	This function MUST be called before returning to DOS, so the *
 *		interrupt vector won't point to our driver anymore, since it *
 *		will surely get overwritten by some other transient program  *
 *		eventually.						     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from IBMCOM.PAS		     *
 *****************************************************************************/

void com_deinstall(void) {

    if (com_installed) {			/* Don't de-install twice! */
	outportb(uart_mcr, old_mcr);		/* Restore the UART */
	outportb(uart_ier, old_ier);		/*  registers ... */
	disable();
	outportb(0x21,				/*  ... the 8259 interrupt */
		 (inportb(0x21)  & ~i8259bit) | /*  mask ... */
		 (old_i8259_mask &  i8259bit));
	enable();
	setvect(intnum, old_vector);		/*  ... and the comm */
	com_installed = FALSE;			/*  interrupt vector */
	}					/* End com_installed */
    }						/* End com_deinstall() */

/*****************************************************************************
 *				com_set_speed()				     *
 *****************************************************************************
 * DESCRIPTION:	Sets the baud rate.					     *
 *									     *
 * SYNOPSIS:	void com_set_speed(unsigned speed);			     *
 *		unsigned speed;			Desired baud rate	     *
 *									     *
 * NOTES:	The input parameter can be anything between 2 and 65535.     *
 *		However, I (Wayne) am not sure that extremely high speeds    *
 *		(those above 19200) will always work, since the baud rate    *
 *		divisor will be six or less, where a difference of one can   *
 *		represent a difference in baud rate of 3840 bits per second  *
 *		or more.)						     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from IBMCOM.PAS		     *

⌨️ 快捷键说明

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