📄 combase.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 + -