www.gusucode.com > VC++6.0GSerial类控制多个串口实例 > VC++6.0GSerial类控制多个串口实例/0603/GSerial.cpp
/*------------------------------------------------------------------* GSERIAL.CPP For asynchronous serial port communications 适用于DOS环境下异步串口通信编程 ATTENTION: Compile this program with Test Stack Overflow OFF. 在Turbo C++3.0中选项设置 Options/Compiler/Entry中关闭Test Stack Overflow *------------------------------------------------------------------*/ #include "GSerial.h" char inbuf[IBUF_LEN]; // in buffer char outbuf[OBUF_LEN]; // out buffer unsigned int startbuf = 0; unsigned int endbuf = 0; unsigned int inhead = 0; unsigned int intail = 0; unsigned int outhead = 0; unsigned int outtail = 0; unsigned int PortBase = 0; GSerial::GSerial() { } GSerial::~GSerial() { } //* get status of the port */ int GSerial::ReadStatus(void) { return(inp(m_unPortBase+5)); } /* send one valid char from the port */ void GSerial::SendChar(unsigned char unCh) { while ((ReadStatus() & 0x40) == 0); outportb(m_unPortBase,unCh); } /* send one string from the port */ void GSerial::SendString(int nStrlen, unsigned char *unChBuf) { int k=0; do { SendChar(*(unChBuf + k)); k++; } while ((k < nStrlen)); } /* Install our functions to handle communications */ void GSerial::SetVects(void interrupt(*New_Int)(...)) { disable(); OldVects = getvect(InterruptNo[m_unPortNo-1]); setvect(InterruptNo[m_unPortNo-1], New_Int); enable(); } /* Uninstall our vectors before exiting the program */ void GSerial::ResetVects(void) { setvect(InterruptNo[m_unPortNo-1], OldVects); } /* Tell modem that we're ready to go */ void GSerial::CommOn(void) { int temp; disable(); //temp = inportb(m_unPortBase + MCR) | MCR_INT; //outportb(m_unPortBase + MCR, temp); outportb(m_unPortBase + MCR, MCR_INT); //temp = inportb(m_unPortBase + MCR) | MCR_DTR | MCR_RTS; //outportb(m_unPortBase + MCR, temp); temp = (inportb(m_unPortBase + IER)) | IER_RX_INT;//|IER_TX_INT; outportb(m_unPortBase + IER, temp); temp = inportb(PIC8259_IMR) & ComIRQ[m_unPortNo-1]; outportb(PIC8259_IMR, temp); enable(); } /* Go off-line */ void GSerial::CommOff(void) { int temp; disable(); temp = inportb(PIC8259_IMR) | ~ComIRQ[m_unPortNo-1]; outportb(PIC8259_IMR, temp); outportb(m_unPortBase + IER, 0); outportb(m_unPortBase + MCR, 0); enable(); } /* Set the port number to use */ int GSerial::SetPortBaseAddr(int Port) { if((Port<1)||(Port>6)) return(-1); m_unPortNo = Port; m_unPortBase = PortBaseAddr[m_unPortNo-1]; return (0); } /* This routine sets the speed; will accept funny baud rates. */ /* Setting the speed requires that the DLAB be set on. */ int GSerial::SetSpeed(int Speed) { char c; int divisor; if (Speed == 0) /* Avoid divide by zero */ return (-1); else divisor = (int) (115200L/Speed); if (m_unPortBase == 0) return (-1); disable(); c = inportb(m_unPortBase + LCR); outportb(m_unPortBase + LCR, (c | 0x80)); /* Set DLAB */ outportb(m_unPortBase + DLL, (divisor & 0x00FF)); outportb(m_unPortBase + DLH, ((divisor >> 8) & 0x00FF)); outportb(m_unPortBase + LCR, c); /* Reset DLAB */ enable(); return (0); } /* Set other DATA Format communications parameters */ int GSerial::SetDataFormat(int Parity, int Bits, int StopBit) { int setting; if (m_unPortBase == 0) return (-1); if (Bits < 5 || Bits > 8) return (-1); if (StopBit != 1 && StopBit != 2) return (-1); if (Parity != LCR_NO_PARITY && Parity != LCR_ODD_PARITY && Parity != LCR_EVEN_PARITY) return (-1); setting = Bits-5; setting |= ((StopBit == 1) ? 0x00 : 0x04); setting |= Parity; disable(); outportb(m_unPortBase + LCR, setting); enable(); return (0); } void GSerial::CloseSerialPort(void) { CommOff(); ResetVects(); } /* Set up the port */ int GSerial::InitSerialPort(int Port, int Speed, int Parity, int Bits, int StopBit) { int flag = 0; if (SetPortBaseAddr(Port)) flag = -1; if (SetSpeed(Speed)) flag = -1; if (SetDataFormat(Parity, Bits, StopBit)) flag = -1; return(flag); } void interrupt ComIntServ(...) { int temp; disable(); temp = (inportb(PortBase+IIR)) & IIR_MASK; // why interrupt was called switch(temp) { case 0x00: // modem status changed inportb(PortBase+MSR); // read in useless char break; case 0x02: // Request To Send char if (outhead != outtail) // there's a char to send { outportb(PortBase+TXR,outbuf[outhead++]); // send the character if (outhead == OBUF_LEN) outhead=0; // if at end of buffer, reset pointer } break; case 0x04: // character ready to be read in //inbuf[inhead++] = inportb(m_unPortBase+RXR);// read character into inbuffer inbuf[inhead] = inportb(PortBase+RXR);// read character into inbuffer inhead++; if (inhead == IBUF_LEN) // if at end of buffer inhead=0; // reset pointer break; case 0x06: // line status has changed inportb(PortBase+LSR); // read in useless char break; default: break; } outportb(PIC8259_ICR, PIC8259_EOI); // Signal end of hardware interrupt enable(); // reenable interrupts at the end of the handler } // Returns either the character to be received from modem if there is one // waiting in the buffer, or returns a 0 if there is no character waiting. char ReadChar(void) { char ch; if (inhead != intail) // there is a character { disable(); // disable irqs while getting char ch = inbuf[intail++]; // get character from buffer if (intail == IBUF_LEN) // if at end of in buffer intail=0; // reset pointer enable(); // re-enable interrupt return(ch); // return the char } ch = -1; return(ch); // return nothing } /////// main() { /* Communications parameters */ int port = COM1; int speed = 9600; int parity = LCR_NO_PARITY; int bits = 8; int stopbits = 1; int done = FALSE; char c; int temp; int SError=0; GSerial gs; if (!gs.InitSerialPort(port, speed, parity, bits, stopbits)) { PortBase = PortBaseAddr[port-1]; gs.SetVects(ComIntServ); gs.CommOn(); } else SError=2; fprintf(stdout, "\nCOM%d, PortBase=0X%x, IntVect=0X%x\n\n",gs.m_unPortNo,gs.m_unPortBase,ComIRQ[gs.m_unPortNo-1]); fprintf(stdout, "TURBO C TERMINAL\n" "...You're now in terminal mode, " "press [ESC] to quit...\n\n"); /* The main loop a MSR_CTS as a dumb terminal. We repeatedly check the keyboard buffer, and communications buffer. */ do { if (kbhit()) { c = getch(); /* Look for an Escape key */ switch (c) { case ESC: done = TRUE; /* Exit program */ break; } if (!done) { gs.SendChar( c ); fprintf(stdout,"%c",c); } } c = ReadChar(); if (c != -1) //'-1' is the END signal of a string { fprintf(stdout,"%c",c); } // fprintf(stdout,"%d",testtemp); } while ((!done) && (!SError)); gs.CloseSerialPort(); /* Check for errors */ switch (SError) { case NO_ERROR: fprintf(stderr, "\nbye.\n"); return (0); case BUF_OVFL: fprintf(stderr, "\nBuffer Overflow.\n"); return (99); case 2: fprintf(stderr,"\n Cannot init serial port"); return(2); default: fprintf(stderr, "\nUnknown Error, SError = %d\n", SError); return (99); } }