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

📄 ser_gen.c

📁 一个C语言写的读入位置跟踪器数据的源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*****************************************************************************
    ser_gen.c       Generic Serial Routines for
		    RS232 PC Compatible and
		    RS485 Quatech Card (w/16550 UART Support)

    written for:    Ascension Technology Corporation
		    PO Box 527
		    Burlington, Vermont  05402
		    802-655-7879


    written by:     Jeff Finkelstein
		    Microprocessor Designs, Inc
		    PO Box 160
		    Shelburne, Vermont  05482
		    802-985-2535

    Modification History:

    9/16/93         jf  - created from serdpcin.c
    12/30/93        jf  - updated to allow this module to send data
			  out the RS232 port if the comport is configured for
			  an RS232 port
    1/8/94          jf  - restore comport now disables the FIFO

	   <<<< Copyright 1993 Ascension Technology Corporation >>>>
*****************************************************************************
****************************************************************************/
#include <stdio.h>          /* general I/O */
#include <time.h>           /* clock functions */
#include <dos.h>            /* needed for SETVECT/GETVECT */
#include "compiler.h"
#include "asctech.h"
#include "menu.h"
#include "pctimer.h"
#include "pcpic.h"
#include "birdmain.h"
#include "ser_gen.h"

/*
    Local Prototypes
*/
void interrupt far serialisr_com1(void);
void interrupt far serialisr_com2(void);
void interrupt far serialisr_com3(void);
void interrupt far serialisr_com4(void);
void serial_isr(short comport);
short ckuartfifo(short comport);


/*
    Base address of all the UARTS
*/
short com_base[NUMCOMPORTS] = {COM1BASE,COM2BASE,COM3BASE,COM4BASE};

/*
    flag indicates serial port saved
*/
short serialconfigsaved[NUMCOMPORTS] = {FALSE,FALSE,FALSE,FALSE};

/*
    Flag indicates the the FIFO is enabled
*/
short fifo_enabled[NUMCOMPORTS] = {FALSE,FALSE,FALSE,FALSE};

/*
    Value indicates that the Port is an RS485 Port
*/
short port_type[NUMCOMPORTS];

/*
    UART variable Storage
*/
unsigned char olddivisorlow[NUMCOMPORTS];            /* holds the old divisor low value */
unsigned char olddivisorhigh[NUMCOMPORTS];           /* holds the old divisor high value */
unsigned char oldlinecont[NUMCOMPORTS];              /* holds the old line control value */
unsigned char oldinterenable[NUMCOMPORTS];           /* holds the old interrupt enable value */
unsigned char oldmodemcont[NUMCOMPORTS];             /* holds the old modem control value */


/*
    Storage for the old serial interrupt vector
*/
void (interrupt far * oldserialintvect[NUMCOMPORTS])();  /* old serial interrupt vector */

/*
    Error Counters
*/

    short phaseerror_count[NUMCOMPORTS] = {0,0,0,0};                  /* holds the phase errors */
    short rxerrorvalue[NUMCOMPORTS] = {0,0,0,0};                      /* holds the rx error value */
	short rxbufoverruns[NUMCOMPORTS] = {FALSE,FALSE,FALSE,FALSE};     /* rx buffer overrun flag */
	short rxerrors[NUMCOMPORTS] = {FALSE,FALSE,FALSE,FALSE};          /* rx line errors flag */
	short txbufempty[NUMCOMPORTS] = {TRUE,TRUE,TRUE,TRUE};            /* tx buffer empty flag */

/*
    RX buffer
*/
    unsigned char rxbuf[NUMCOMPORTS][RXBUFSIZE];  /* rx buffer */
    unsigned char * rxbufinptr[NUMCOMPORTS];      /* rx buffer input pointer */
    unsigned char * rxbufoutptr[NUMCOMPORTS];     /* rx buffer output pointer */

/*
    TX buffer
*/
    unsigned char txbuf[NUMCOMPORTS][TXBUFSIZE];  /* tx buffer */
    unsigned char * txbufinptr[NUMCOMPORTS];      /* tx buffer input pointer */
    unsigned char * txbufoutptr[NUMCOMPORTS];     /* tx buffer output pointer */

/*
	tick timing varaible
*/

    unsigned int tick_msec = 18;        /* dos tick time in msec */


/*
    configserialport    -   Configure the Serial Port connected to the BIRD

    Prototype in:       serial.h

    Parameters Passed:  short comport

    Return Value:       TRUE if successfull, else FALSE

    Remarks:            Routine assumes that the current comports parameters
			have been saved prior to the call.
					    ** NOTE **
			Unfortunately, the PC ROM BIOS does NOT support baud
			rates upto 19200. Therefore, this routine must talk
			directly to the hardware to configure the serial port
			...this is not a problem in a PC environment since the
			I/O map is fixed for COM1 and COM2.
*/
int configserialport(comport,baud,type)
short comport;
long baud;
short type;
{
    unsigned divisor;

    /*
	Disable the interrupts
    */
    OUTPORTB(com_base[comport] + INTERENABLE, 0);

    /*
	Set the Global Port Type
    */
    port_type[comport] = type;

    /*
	Verify the comport and set the Base Address
    */
    switch (comport)
    {
	case COM1:
	    PCPIC_MASK(COM1IRQ);
	    SETVECT(COM1INTERRUPT,serialisr_com1);
	    break;

	case COM2:
	    PCPIC_MASK(COM2IRQ);
	    SETVECT(COM2INTERRUPT,serialisr_com2);
	    break;

	case COM3:
	    PCPIC_MASK(COM3IRQ);
	    SETVECT(COM3INTERRUPT,serialisr_com3);
	    break;

	case COM4:
	    PCPIC_MASK(COM4IRQ);
	    SETVECT(COM4INTERRUPT,serialisr_com4);
	    break;

	default:
	    printf("\n** ERROR ** invalid COM port\n");
	    return(FALSE);
    }

    /*
	assume that there are NO CHARACTERS CURRENTLY in the Tx Buffer
	and change the baud rate
    */
    OUTPORTB(com_base[comport] + LINECONT, DLAB);

    /*
	Set the least significant byte and then the most significant
	byte of the baud rate divisor
    */
    switch (port_type[comport])
    {
	case RS485_PORT:
	    divisor = 500000L/baud;
	    break;
	case RS232_PORT:
	    divisor = 115200L/baud;
	    break;
	default:
	    printf("\n\r** ERROR **  illegal Port Type in configserial\n\r");
	    return(FALSE);
    }
    OUTPORTB(com_base[comport], (divisor & 0xff));
    OUTPORTB(com_base[comport] + 1, ((divisor & 0xff00) >> 8));

    /*
	Set the Stop Bits = 1, Word Length = 8 and Parity = None
    */
    OUTPORTB(com_base[comport] + LINECONT, STOP_WORDLEN_PARITY);

    /*
	Deassert DTR...Make the TRANCEIVER go to Receive.. RS485
	Deassert DTR...Enable Output from the FOB.. RS232
	Deassert RTS...else the system will reset
	Assert OUT2...needed to allow interrupts to occur on PC compatible
	    serial I/O cards
    */
    switch(port_type[comport])
    {
	case RS232_PORT:
	    OUTPORTB(com_base[comport] + MODEMCONT, DTRON | OUT2);
	    break;
	case RS485_PORT:
	    OUTPORTB(com_base[comport] + MODEMCONT, OUT2);
	    break;
    }

    /*
	Check if it is a 16550 UART with a FIFO
	..use it if it is available..setup the receive trigger to 14 characters
    */
    OUTPORTB(com_base[comport] + FCR, 0);   /* disable the FIFO */
    fifo_enabled[comport] = ckuartfifo(comport);
    if (fifo_enabled[comport])
    {
	OUTPORTB(com_base[comport] + FCR, 0xC0 + 1);  /* enable the FIFO..0xc0 is for
						trigger level = 14 bytes */
    }
    else
    {
	/*
	    RS485 Ports Must have the FIFO for the DUAL system
	*/
	if (port_type[comport] == RS485_PORT)
	{
	    printf("\n\r** ERROR ** COM%d does not have a 16550 type UART\n\r",comport+1);
	    return(FALSE);
	}
    }

    /*
	Clear the Rx Buffer and Rx Errors
    */
    clear_rx(comport);

    /*
	Enable the 8259 Mask register for serial interrupts
    */
    switch (comport)
    {
	case COM1:
	     PCPIC_UNMASK(COM1IRQ);
	     break;
	case COM2:
	     PCPIC_UNMASK(COM2IRQ);
	     break;
	case COM3:
	     PCPIC_UNMASK(COM3IRQ);
	     break;
	case COM4:
	     PCPIC_UNMASK(COM4IRQ);
	     break;
    }

    return(TRUE);
}

/*
    ckuartfifo          Check for a Uart FIFO

    Prototype in:       serial.h

    Parameters Passed:  short comport - comport of the UART

    Return Value:       TRUE if the UART has a FIFO
			FALSE otherwise

    Remarks:            routine checks if the UART is a 16550 Type by
			trying to enable the FIFO and then checking if the
			FIFO did in fact become enabled

*/
short ckuartfifo(comport)
short comport;
{
    OUTPORTB(com_base[comport] + FCR, 7); /* Enable and Reset */
    if ((INPORTB(com_base[comport] + INTERIDENT) & 0xC0) != 0xC0)
	return(FALSE);
    OUTPORTB(com_base[comport] + FCR, 0); /* Disable */
    if ((INPORTB(com_base[comport] + INTERIDENT) & 0xC0) == 0xC0)
	return(FALSE);
    OUTPORTB(com_base[comport] + FCR, 1); /* Enable */
    if ((INPORTB(com_base[comport] + INTERIDENT) & 0xC0) != 0xC0)
	return(FALSE);

    return(TRUE);
}

/*
    saveserialconfig    -   save serial port configuration

    Prototype in:       serial.h

    Parameters Passed:  short comport

    Return Value:       void

    Remarks:            saves the current configuration of the serial port

*/
int saveserialconfig(comport)
short comport;
{
    /*
	Save the Serial interrupt Vector
    */
    switch (comport)
    {
	case COM1:
	    oldserialintvect[comport] = GETVECT(COM1INTERRUPT);
	    break;
	case COM2:
	    oldserialintvect[comport] = GETVECT(COM2INTERRUPT);
	    break;
	case COM3:
	    oldserialintvect[comport] = GETVECT(COM3INTERRUPT);
	    break;
	case COM4:
	    oldserialintvect[comport] = GETVECT(COM4INTERRUPT);
	    break;
    }

    /*
	Save the Current Com Port Configuration Regs including:
	    Divisor, Interrupt Enable, Line Control, Modem Control
    */
    oldlinecont[comport] = INPORTB(com_base[comport] + LINECONT);         /* save the old line control value */
    OUTPORTB(com_base[comport] + LINECONT, DLAB);                /* set DLAB to get the divisor */
    olddivisorlow[comport] = INPORTB(com_base[comport] + DIVISORLOW);     /* save the divisor low */
    olddivisorhigh[comport] = INPORTB(com_base[comport] + DIVISORHIGH);   /* save the divisor high */
    OUTPORTB(com_base[comport] + LINECONT,oldlinecont[comport] & 0x7f);   /* reset DLAB to get the divisor */
    oldinterenable[comport] = INPORTB(com_base[comport] + INTERENABLE);   /* save the interrupt enable reg */
    oldmodemcont[comport] = INPORTB(com_base[comport] + MODEMCONT);       /* save the modem control reg */

    serialconfigsaved[comport] = TRUE;

    return(TRUE);
}

/*
    restoreserialconfig -   Restore the original serial port configuration

    Prototype in:       serial.h

    Parameters Passed:  short comport

    Return Value:       void

    Remarks:            restores the configuration of the serial port
*/
void restoreserialconfig(comport)
short comport;
{
    /*
	Do not Restore if not previously stored
    */
    if (!serialconfigsaved[comport])
	return;

    /*
	Disable Serial Interrupts on 8259 while initializing port
	and switching interrupt vectors
    */
    switch (comport)
    {
	case COM1:
	    PCPIC_MASK(COM1IRQ);
	    break;

	case COM2:
	    PCPIC_MASK(COM2IRQ);
	    break;

	case COM3:
	    PCPIC_MASK(COM3IRQ);
	    break;

	case COM4:
	    PCPIC_MASK(COM4IRQ);
	    break;
    }

    /*
	Restore the Com Port Configuration Regs including:
	    Divisor, Interrupt Enable, Line Control, Modem Control
    */
    OUTPORTB(com_base[comport] + LINECONT, DLAB);                /* set DLAB to get the divisor */
    OUTPORTB(com_base[comport], olddivisorlow[comport]);                   /* restore the divisor low */
    OUTPORTB(com_base[comport] + 1,olddivisorhigh[comport]);              /* restore the divisor high */
    OUTPORTB(com_base[comport] + LINECONT,oldlinecont[comport]);          /* reset DLAB to get the divisor */
    OUTPORTB(com_base[comport] + INTERENABLE,oldinterenable[comport]);    /* restore the interrupt enable reg */
    OUTPORTB(com_base[comport] + MODEMCONT,oldmodemcont[comport]);        /* restore the interrupt enable reg */

    /*
	Restore the Serial Vector
	..disable interrupts during restoration
    */
    DISABLE();
    switch (comport)
    {
	case COM1:
	    SETVECT(COM1INTERRUPT,oldserialintvect[comport]);
	    break;
	case COM2:
	    SETVECT(COM2INTERRUPT,oldserialintvect[comport]);
	    break;
	case COM3:
	    SETVECT(COM3INTERRUPT,oldserialintvect[comport]);
	    break;
	case COM4:
	    SETVECT(COM4INTERRUPT,oldserialintvect[comport]);
	    break;
    }
    ENABLE();

    /*
	Disable the FIFO for other applications
    */
    if (fifo_enabled[comport])
	OUTPORTB(com_base[comport] + FCR, 0);   /* disable the FIFO */
}


/*
    clearrx             -   Read the characters out of the Rx buffer if available

    Prototype in:       serial.h

    Parameters Passed:  short comport

    Return Value:       void

    Remarks:            clears the rx buffer and rx errors if any

*/
void clear_rx(comport)
short comport;
{
    short i;

    phaseerror_count[comport] = 0;                       /* clear phase error cntr */
    rxerrorvalue[comport] = 0;                           /* clear error byte */
    rxerrors[comport] = FALSE;                           /* clear Rx error flag */
    rxbufoverruns[comport] = FALSE;                      /* clear Buf Overrun flag */
    rxbufinptr[comport] = rxbufoutptr[comport] = rxbuf[comport];           /* re initialize buffer ptrs */
    txbufinptr[comport] = txbufoutptr[comport] = txbuf[comport];           /* re initialize buffer ptrs */

    /*
       Clear the Interrupts
    */
    while (!(INPORTB(com_base[comport] + INTERIDENT) && 0x01))
    {
	INPORTB(com_base[comport] + RXBUF);       /* Clear the Data */
	INPORTB(com_base[comport] + MODEMSTATUS); /* Clear the Modem Status */
	INPORTB(com_base[comport] + LINESTATUS);  /* Clear the Line Status */
    }
}

/*
    get_serial_record   - Get a record from the serial port

    Prototype in:       serial.h

    Parameters Passed:  short comport
			rxbuf       -   pointer to a buffer to store the
					received characters
			recsize     -   number of characters to receive
			outputmode  -   POINT, CONTINUOUS or STREAM

    Return Value:       If successful, returns recsize
			else, RXERRORS if Rx errors were detected while
			receiving data, or RXPHASEERRORS if in POINT or
			CONTINUOUS mode and a phase error is detected.

    Remarks:            A record of data has the MSB of the first
			character set to a 1.  The routine verifies that
			the first character received is in PHASE.  If
			in STREAM mode, the routine resynches and tries
			to capture the data into the rxbuf.  If in POINT
			or CONTINUOUS mode, then the routine returns
			indicating a RXPHASEERROR.

*/
int get_serial_record(comport, rxbuffer, recsize, outputmode)
short comport;
unsigned char * rxbuffer;
short recsize;
short outputmode;
{
	short rxcount;
	short rxchar;
	short resynch;
    char * rxbufptr;

    resynch = TRUE;

    do
    {
	if  (resynch)
	{
	    rxcount = 0;                /* initialize char counter */
	    rxbufptr = rxbuffer;        /* setup buffer pointer */
	    resynch = FALSE;
	}

	/*
	    Get first character and if error and NOT in STREAM mode..return
	*/
	if (rxcount == 0)
	{
	    if ((rxchar = waitforchar(comport)) < 0)
	    {
		if ((outputmode != STREAM) || (rxchar == RXTIMEOUT))
		{
		    return(RXERRORS);
		}
	    }

	    /*
		Check to make sure the the phase bit is a '1'
		If not, then if STREAM mode, resynch
		else, return with error
	    */
	    if (!(rxchar & 0x80))
	    {
		if (outputmode == STREAM)
		{
		    /*
		       Resynch
		       ...and keep track of the phase error
		    */
		    phaseerror_count[comport]++;
		    resynch = TRUE;
		    continue;
		}
		else
		{
		     return(RXPHASEERROR);
		}
	    }
	}

⌨️ 快捷键说明

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