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

📄 ibmcom.c

📁 串行通信C语言代码,用于DOS下编程,比较完整
💻 C
📖 第 1 页 / 共 2 页
字号:
 *****************************************************************************/

void com_set_speed(unsigned speed) {

    unsigned	divisor;			/* A local temp */

    if (com_installed) {
	if (speed < 2) speed = 2;		/* Force proper input */
	divisor = 115200L / speed;		/* Recond baud rate divisor */
	disable();				/* Interrupts off */
	outportb(uart_lcr,			/* Set up to load baud rate */
		 inportb(uart_lcr) | 0x80);	/*  divisor into UART */
	outport(uart_data, divisor);		/* Do so */
	outportb(uart_lcr,			/* Back to normal UART ops */
		 inportb(uart_lcr) & ~0x80);
	enable();				/* Interrupts back on */
	}					/* End "comm installed" */
    }						/* End com_set_speed() */

/*****************************************************************************
 *			       com_set_parity()				     *
 *****************************************************************************
 * DESCRIPTION: Sets the parity and stop bits.				     *
 *									     *
 * SYNOPSIS:	void com_set_parity(enum par_code parity, int stop_bits);    *
 *		int	code;		COM_NONE = 8 data bits, no parity    *
 *					COM_EVEN = 7 data, even parity	     *
 *					COM_ODD  = 7 data, odd parity	     *
 *					COM_ZERO = 7 data, parity bit = zero *
 *					COM_ONE  = 7 data, parity bit = one  *
 *		int	stop_bits;	Must be 1 or 2			     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal		     *
 *****************************************************************************/

const char	lcr_vals[] = {
		    DATA8 + NOPAR,
		    DATA7 + EVNPAR,
		    DATA7 + ODDPAR,
		    DATA7 + STKPAR,
		    DATA7 + ZROPAR
		    } ;

void com_set_parity(enum par_code parity, int stop_bits) {
    disable();
    outportb(uart_lcr, lcr_vals[parity] | ((stop_bits == 2) ? STOP2 : STOP1));
    enable();    
    }						/* End com_set_parity() */

/*****************************************************************************
 *				com_raise_dtr()				     *
 *				com_lower_dtr()				     *
 *****************************************************************************
 * DESCRIPTION:	These routines raise and lower the DTR line.  Lowering DTR   *
 *		causes most modems to hang up.				     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Transltated from the Pascal.		     *
 *****************************************************************************/

void com_lower_dtr(void) {
    if (com_installed) {
    	disable();
	outportb(uart_mcr, inportb(uart_mcr) & ~DTR);
    	enable();
	}					/* End 'comm installed' */
    }						/* End com_raise_dtr() */

void com_raise_dtr(void) {
    if (com_installed) {
    	disable();
	outportb(uart_mcr, inportb(uart_mcr) | DTR);
    	enable();
	}					/* End 'comm installed' */
    }						/* End com_lower_dtr() */

/*****************************************************************************
 *				   com_tx()				     *
 *				com_tx_string()				     *
 *****************************************************************************
 * DESCRIPTION: Transmit routines.  com_tx() sends a single character by     *
 *		waiting until the transmit buffer isn't full, then putting   *
 *		the character into it.  The interrupt driver will then send  *
 *		the character once it is at the head of the transmit queue   *
 *		and a transmit interrupt occurs.  com_tx_string() sends a    *
 *		string by repeatedly calling com_tx().			     *
 *									     *
 * SYNOPSES:	void	com_tx(char c);		Send the character c	     *
 *		void	com_tx_string(char *s);	Send the string s	     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal		     *
 *****************************************************************************/

void com_tx(char c) {
    if (com_installed) {
	while (!com_tx_ready()) ;		/* Wait for non-full buffer */
	disable();				/* Interrupts off */
	tx_queue[tx_in++] = c;			/* Stuff character in queue */
	if (tx_in == TX_QUEUE_SIZE) tx_in = 0;	/* Wrap index if needed */
	tx_chars++;				/* Number of char's in queue */
	outportb(uart_ier,			/* Enable UART tx interrupt */
		 inportb(uart_ier) | THRE);
	enable();				/* Interrupts back on */
	}					/* End 'comm installed' */
    }						/* End com_tx() */

void com_tx_string(char *s) {
    while (*s) com_tx(*s++);			/* Send the string! */
    }						/* End com_tx_string() */

/*****************************************************************************
 *				   com_rx()				     *
 *****************************************************************************
 * DESCRIPTION:	Returns the next character from the receive buffer, or a     *
 *		NULL character ('\0') if the buffer is empty.		     *
 *									     *
 * SYNOPSIS:	c = com_rx();						     *
 *		char	c;			The returned character	     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal.		     *
 *****************************************************************************/

char	com_rx(void) {

    char	rv;				/* Local temp */

    if (!rx_chars || !com_installed)		/* Return NULL if receive */
	return '\0';    			/*  buffer is empty */
    disable();					/* Interrupts off */
    rv = rx_queue[rx_out++];			/* Grab char from queue */
    if (rx_out == RX_QUEUE_SIZE)		/* Wrap index if needed */
	rx_out = 0;
    rx_chars--;					/* One less char in queue */
    enable();					/* Interrupts back on */
    return rv;					/* The answer! */
    }						/* End com_rx() */

/*****************************************************************************
 *			     Queue Status Routines			     *
 *****************************************************************************
 * DESCRIPTION:	Small routines to return status of the transmit and receive  *
 *		queues.							     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal.		     *
 *****************************************************************************/

int com_tx_ready(void) {			/* Return TRUE if the */
    return ((tx_chars < TX_QUEUE_SIZE) ||	/*  transmit queue can */
	    (!com_installed));			/*  accept a character */
    }						/* End com_tx_ready() */

int com_tx_empty(void) {			/* Return TRUE if the */
    return (!tx_chars || (!com_installed));	/*  transmit queue is empty */
    }						/* End com_tx_empty() */

int com_rx_empty(void) {			/* Return TRUE if the */
    return (!rx_chars || (!com_installed));	/*  receive queue is empty */
    }						/* End com_tx_empty() */

/*****************************************************************************
 *				com_flush_tx()				     *
 *				com_flush_rx()				     *
 *****************************************************************************
 * DESCRIPTION:	Buffer flushers!  These guys just initialize the transmit    *
 *		and receive queues (respectively) to their empty state.	     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal		     *
 *****************************************************************************/

void com_flush_tx() { disable(); tx_chars = tx_in = tx_out = 0; enable(); }
void com_flush_rx() { disable(); rx_chars = rx_in = rx_out = 0; enable(); }

/*****************************************************************************
 *				 com_carrier()				     *
 *****************************************************************************
 * DESCRIPTION:	Returns TRUE if a carrier is present.			     *
 *									     *
 * REVISIONS:	18 OCT 89 - RAC - Translated from the Pascal.		     *
 *****************************************************************************/

int com_carrier(void) {
    return com_installed && (inportb(uart_msr) & RLSD);
    }						/* End com_carrier() */

/*****************************************************************************
 *			    com_interrupt_driver()			     *
 *****************************************************************************
 * DESCRIPTION:	Handles communications interrupts.  The UART will interrupt  *
 *		whenever a character has been received or when it is ready   *
 *		to transmit another character.  This routine responds by     *
 *		sticking received characters into the receive queue and      *
 *		yanking characters to be transmitted from the transmit queue *
 *									     *
 * REVISIOSN:	18 OCT 89 - RAC - Translated from the Pascal.		     *
 *****************************************************************************/

void interrupt com_interrupt_driver() {

    char	iir;				/* Local copy if IIR */
    char	c;				/* Local character variable */

/*  While bit 0 of the IIR is 0, there remains an interrupt to process  */

    while (!((iir = inportb(uart_iir)) & 1)) {	/* While there is an int ... */
	switch (iir) {				/* Branch on interrupt type */

	    case 0:				/* Modem status interrupt */
		inportb(uart_msr);		/* Just clear the interrupt */
		break;

	    case 2:				/* Transmit register empty */

/*****************************************************************************
 *  NOTE:  The test of the line status register is to see if the transmit    *
 *	   holding register is truly empty.  Some UARTS seem to cause	     *
 *	   transmit interrupts when the holding register isn't empty,	     *
 *	   causing transmitted characters to be lost.			     *
 *****************************************************************************/

		if (tx_chars <= 0)		/* If tx buffer empty, turn */
		    outportb(uart_ier,		/*  off transmit interrupts */
			     inportb(uart_ier) & ~2);
		else {				/* Tx buffer not empty */
		    if (inportb(uart_lsr) & TXR) {
			outportb(uart_data, tx_queue[tx_out++]);
			if (tx_out == TX_QUEUE_SIZE)
			    tx_out = 0;
			tx_chars--;
			}
		    }				/* End 'tx buffer not empty */
		break;

	    case 4:				/* Received data interrupt */
		c = inportb(uart_data);		/* Grab received character */
		if (rx_chars < RX_QUEUE_SIZE) { /* If queue not full, save */
		    rx_queue[rx_in++] = c;	/*  the new character */
		    if (rx_in == RX_QUEUE_SIZE) /* Wrap index if needed */
			rx_in = 0;
		    rx_chars++;			/* Count the new character */
		    }				/* End queue not full */
		break;

	    case 6:				/* Line status interrupt */
		inportb(uart_lsr);		/* Just clear the interrupt */
		break;

	    }					/* End switch */
	}					/* End 'is an interrupt' */
    outportb(0x20, 0x20);			/* Send EOI to 8259 */
    }						/* End com_interrupt_driver() */

⌨️ 快捷键说明

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