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

📄 combase.cpp

📁 基于PC104的24位数据采集器的完整源码
💻 CPP
字号:

  /*------------------------------------------------------------------*
	  SERIAL.CPP

      The following code shows how to take advantage of some of
	  the Turbo C++ extensions to the C++ language to do asynchronous
      communications without having to write supporting assembly-
      language routines.

      This program bypasses the less-than-adequate PC BIOS
	  communications routines and installs a serial interrupt
      handler. Direct access to PC hardware allows the program to
      run at faster baud rates and eliminates the need for
      the main program to continuously poll the serial port for
      data; thus implementing background communications. Data that
      enters the serial port is stored in a circular buffer.

	  * Compile this program with Test Stack Overflow OFF.

  *------------------------------------------------------------------*/

#include <dos.h>
#include <conio.h>
#include <iostream.h>
#include <stdio.h>
#include "combase.h"
#include "hello.h"
#include "SendTeam.h"
#include "InteTeam.h"


static const int SERIALSPEED[] =
{
	1200,2400,4800,9600,14400,
	19200,38400,56000,57600,115200,
	// the serial limit nSpeed <= 115200
	128000,256000
};

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

/* Handle communications interrupts and put them in receivebuf */
uint nCom1TeamOutPos = 0;
uint nCom2TeamOutPos = 0;
uint nCom1Index = 0;
uint nCom2Index = 0;
uchar SCom1Error = NOERROR;
uchar SCom2Error = NOERROR;
void interrupt com1_int(...)
{
	disable();
	while(1)
	{
		unsigned char nBits = inportb(COM1BASE + IIR) & RX_MASK;
		if( nBits == TX_ID)
		{
			if(nCom1TeamOutPos == g_nSendTeamPos)
			{
				SCom1Error = BUFEMPY;
			}
			else
			{
				char nChar = g_pSendTeam[nCom1TeamOutPos]->GetNext(nCom1Index);
				outportb(COM1BASE + TXR,nChar);
				if(!nCom1Index)
					nCom1TeamOutPos = (nCom1TeamOutPos + 1)&(SENDTEAM_LENGTH-1);
			}
		}
		else if ( nBits == RX_ID)
		{
			g_nInterTeam.TeamIn(inportb(COM1BASE + RXR));
		}
		else if(nBits == NO_ID)
			break;
	}

	/* Signal end of hardware interrupt */
	outportb(ICR, EOI);
	enable();
}

void interrupt com2_int(...)
{
	disable();
	while(1)
	{
		unsigned char nBits = inportb(COM2BASE + IIR) & RX_MASK;
		if( nBits == TX_ID)
		{
			if(nCom2TeamOutPos == g_nSendTeamPos)
			{
				SCom2Error = BUFEMPY;
			}
			else
			{
				char nChar = g_pSendTeam[nCom2TeamOutPos]->GetNext(nCom2Index);
				outportb(COM2BASE + TXR,nChar);
				if(!nCom2Index)
					nCom2TeamOutPos = (nCom2TeamOutPos + 1)&(SENDTEAM_LENGTH-1);
			}
		}
		else if ( nBits == RX_ID)
		{
			g_pGpsIn[g_nGpsInPos++] = inportb(COM2BASE + RXR);
			g_nGpsInPos &= g_nGpsInLength - 1;
		}
		else if(nBits == NO_ID)
			break;
	}

	/* Signal end of hardware interrupt */
	outportb(ICR, EOI);
	enable();
}

void StartSend(void)
{
	if(SCom1Error)
	{
		char nChar = g_pSendTeam[nCom1TeamOutPos]->GetNext(nCom1Index);
		outportb(COM1BASE + TXR,nChar);
	}
	if(SCom2Error)
	{
		char nChar = g_pSendTeam[nCom2TeamOutPos]->GetNext(nCom2Index);
		outportb(COM2BASE + TXR,nChar);
	}
}

/* Install our functions to handle communications */
void serial::setvects(void)
{
	if(m_nPort == COM1)
	{
		oldvects[1] = getvect(0x0C);
		setvect(0x0C,com1_int);
	}
	else if(m_nPort == COM2)
	{
		oldvects[0] = getvect(0x0B);
		setvect(0x0B, com2_int);
	}
}



/* Uninstall our vectors before exiting the program */
void serial::resvects(void)
{
	disable();
	if(m_nPort == COM1)
	{
		setvect(0x0C, oldvects[1]);
	}
	else if(m_nPort == COM2)
	{
		setvect(0x0B, oldvects[0]);
	}
	enable();
}

/* Turn on communications interrupts */
void serial::i_enable(int pnum)
{
	int                c;

	disable();
	c = inportb(portbase + MCR) | MC_INT;
	outportb(portbase + MCR, c);

	if(pnum == COM1)
		outportb(portbase + IER, TX_INT|RX_INT);
	else
		outportb(portbase + IER, TX_INT|RX_INT);

	c = inportb(IMR) & (pnum == COM1 ? IRQ4 : IRQ3);
	outportb(IMR, c);
	enable();
}

/* Turn off communications interrupts */
void serial::i_disable(void)
{
	int                c;
	disable();
	if(m_nPort == COM1)
		c = inportb(IMR) | ~IRQ4;
	else
		c = inportb(IMR) | ~IRQ3;

	outportb(IMR, c);
	outportb(portbase + IER, 0);
	c = inportb(portbase + MCR) & ~MC_INT;
	outportb(portbase + MCR, c);
	enable();
}

/* Tell modem that we're ready to go */
void serial::comm_on(void)
{
	int                c, pnum;

	pnum = (portbase == COM1BASE ? COM1 : COM2);
	i_enable(pnum);
	c = inportb(portbase + MCR) | DTR | RTS;
	outportb(portbase + MCR, c);
}

/* Go off-line */
void serial::comm_off(void)
{
	i_disable();
	outportb(portbase + MCR, 0);
}

void serial::init_serial(void)
{
	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   : return (-1);
	}

	RS232_Addr = (int far *)MK_FP(0x0040, Offset);  /* Find out where the port is. */
	if (*RS232_Addr == NULL) 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();

	m_nSpeed = Speed;

	return (0);
}

/* Set other communications parameters */
int serial::SetOthers(int Parity, int Bits, int StopBit)
{
	m_nParity = Parity;
	m_nBits = Bits;
	m_nStopBit = StopBit;
	int                setting;

	 if (portbase == 0)					return (-1);
	 if (Bits < 5 || Bits > 8)				return (-1);
	 if (StopBit != 1 && StopBit != 2)			return (-1);
	 if (Parity != NO_PARITY && Parity != ODD_PARITY && Parity != 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()
{
	flag = -1;
}

void serial::Open(int Port, int Speed, int Parity, int Bits, int StopBit)
{
	m_nPort = Port;
	if(Port == COM1)
		SCom1Error = BUFEMPY;
	else if(Port == COM2)
		SCom2Error = BUFEMPY;
	portbase        = 0;
	flag = 0;
	if (SetPort(Port))
	  flag = -1;
	if (SetSpeed(Speed))
	  flag = -1;
	if (SetOthers(Parity, Bits, StopBit))
	  flag = -1;

	if (!flag)
		init_serial();
}

void serial::ResetSpeed(int nSpeed)
{
	comm_off();
	resvects();
	delay(5000);

	flag = 0;
	if (SetPort(m_nPort))
	  flag = -1;
	if (SetSpeed(nSpeed))
	  flag = -1;
	if (SetOthers(m_nParity, m_nBits, m_nStopBit))
	  flag = -1;

	if (!flag)
		init_serial();
}

⌨️ 快捷键说明

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