一个串口通信 for Dos 的代码,请帮帮忙看看怎用. |
尚未結案
|
One2Free
一般會員 發表:26 回覆:28 積分:20 註冊:2004-05-12 發送簡訊給我 |
在一份产品的设计文档中找到一个封装成 Class 的串口通信代码,
可少了 GSERIAL.CPP 文件, 加上对 C++ 不熟悉, 不知道怎样用,
请各位大大帮帮忙,看看怎用,最好能帮忙写个 Demo.谢谢!
/*---------------------------------------------------------------------* FILENAME: GSERIAL.H This file is used to define const and class for GSERIAL.CPP TC 3.0 for DOS *--------------------------------------------------------------------*/ #define COM1 1 #define COM2 2 #define COM3 3 #define COM4 4 #define COM5 5 #define COM6 6 #define COM1BASE 0x3F8 /* Base port address for COM1 */ #define COM2BASE 0x2F8 /* Base port address for COM2 */ #define COM3BASE 0x3E8 /* Base port address for COM3 */ #define COM4BASE 0x2E8 /* Base port address for COM4 */ #define COM5BASE 0x3A8 /* Base port address for COM5 */ #define COM6BASE 0x2A8 /* Base port address for COM6 */ /* The 8250 UART has 10 registers accessible through 7 port addresses. Here are their addresses relative to COM1BASE and COM2BASE. Note that the baud rate registers, (DLL) and (DLH) are active only when the Divisor-Latch Access-Bit (DLAB除数锁存器访问位) is on. The (DLAB) is bit 7 of the (LCR--Line Control Register线路控制寄存器). * TXR Output data to the serial port. * RXR Input data from the serial port. * LCR Initialize the serial port. * IER Controls interrupt generation. * IIR Identifies interrupts. * MCR Send contorl signals to the modem. * LSR Monitor the status of the serial port. * MSR Receive status of the modem. * DLL Low byte of baud rate divisor. * DHH High byte of baud rate divisor. */ /*The following is the adress of the registers DLAB status */ #define TXR 0 /* Transmit register (WRITE) 0 */ #define RXR 0 /* Receive register (READ) 0 */ #define IER 1 /* Interrupt Enable x */ #define IIR 2 /* Interrupt ID x */ #define LCR 3 /* Line control x */ #define MCR 4 /* Modem control x */ #define LSR 5 /* Line Status x */ #define MSR 6 /* Modem Status x */ #define DLL 0 /* Divisor Latch Low 1 */ #define DLH 1 /* Divisor latch High 1 */ /*-------------------------------------------------------------------* Bit values held in the Line Control Register (LCR). bit meaning --- ------- 0-1 00=5 bits, 01=6 bits, 10=7 bits, 11=8 bits. /word length select bit 2 Stop bits. / 3 0=parity off, 1=parity on. /Parity Enable=1 4 0=parity odd, 1=parity even. /Odd or Even select 5 Sticky parity. / 6 Set break. 7 Toggle port addresses. /1:access *-------------------------------------------------------------------*/ #define LCR_NO_PARITY 0x00 #define LCR_EVEN_PARITY 0x18 #define LCR_ODD_PARITY 0x08 /*-------------------------------------------------------------------* Bit values held in the Line Status Register (LSR). bit meaning --- ------- 0 Data ready. 1 Overrun error - Data register overwritten. 2 Parity error - bad transmission. 3 Framing error - No stop bit was found. 4 Break detect - End to transmission requested. 5 Transmitter holding register is empty. 6 Transmitter shift register is empty. 7 Time out - off line. *-------------------------------------------------------------------*/ #define LSR_RCVRDY 0x01 #define LSR_OVRERR 0x02 #define LSR_PRTYERR 0x04 #define LSR_FRMERR 0x08 #define LSR_BRKERR 0x10 #define LSR_XMTRDY 0x20 #define LSR_XMTRSR 0x40 #define LSR_TIMEOUT 0x80 /*-------------------------------------------------------------------* Bit values held in the Modem Output Control Register (MCR). bit meaning --- ------- 0 Data Terminal Ready. Computer ready to go. 1 Request To Send. Computer wants to send data. 2 auxillary output #1. 3 auxillary output #2.(Note: This bit must be set to allow the communications card to send interrupts to the system) 4 UART ouput looped back as input. 5-7 not used. *------------------------------------------------------------------*/ #define MCR_DTR 0x01 #define MCR_RTS 0x02 #define MCR_INT 0x08 /*------------------------------------------------------------------* Bit values held in the Modem Input Status Register (MSR). bit meaning --- ------- 0 delta Clear To Send. 1 delta Data Set Ready. 2 delta Ring Indicator. 3 delta Data Carrier Detect. 4 Clear To Send. 5 Data Set Ready. 6 Ring Indicator. 7 Data Carrier Detect. *------------------------------------------------------------------*/ #define MSR_CTS 0x10 #define MSR_DSR 0x20 /*------------------------------------------------------------------* Bit values held in the Interrupt Enable Register (IER). bit meaning --- ------- 0 Interrupt when data received. 1 Interrupt when transmitter holding reg. empty. 2 Interrupt when data reception error. 3 Interrupt when change in modem status register. 4-7 Not used. *------------------------------------------------------------------*/ #define IER_RX_INT 0x01 #define IER_TX_INT 0x02 /*------------------------------------------------------------------* Bit values held in the Interrupt Identification Register (IIR). bit meaning --- ------- 0 Interrupt pending 1-2 Interrupt ID code 00=Change in modem status register, 01=Transmitter holding register empty, 10=Data received, 11=reception error, or break encountered. 3-7 Not used. *------------------------------------------------------------------*/ #define IIR_MS_ID 0x00 // Modem status #define IIR_RX_ID 0x04 // Rceived data OK,and to read the receive buffer #define IIR_TX_ID 0x02 // Transmitter holding register empty #define IIR_MASK 0x07 // Get the low 3 bits of IIR /*------------------------------------------------------------------* These are the port addresses of the 8259 Programmable Interrupt Controller (PIC). *------------------------------------------------------------------*/ #define PIC8259_IMR 0x21 /* Interrupt Mask Register port */ #define PIC8259_ICR 0x20 /* Interrupt Control Port */ /*------------------------------------------------------------------* An end of interrupt needs to be sent to the Control Port of the 8259 when a hardware interrupt ends. *------------------------------------------------------------------*/ #define PIC8259_EOI 0x20 /* End Of Interrupt */ /*------------------------------------------------------------------* The (IMR) tells the (PIC) to service an interrupt only if it is not masked (FALSE). *------------------------------------------------------------------*/ #define IRQ3 0xF7 /* COM2 */ #define IRQ4 0xEF /* COM1 */ class serial{ int flag; int SetSerial(); int SetOthers(int Parity, int Bits, int StopBit); int SetSpeed(int Speed); int SetPort(int Port); void init_serial(void); void comm_on(void); void comm_off(void); public: serial(int Port, int Speed, int Parity, int Bits, int StopBit); serial &operator<<( char ch ); serial &operator<<( char *str ); serial &operator>>( char &ch ); ~serial(); }; #define VERSION 0x0101 #define FALSE 0 #define TRUE 1 #define NO_ERROR 0 /* No error */ #define BUF_OVFL 1 /* Buffer overflowed */ #define IBUF_LEN 2048 // Incoming buffer #define OBUF_LEN 1024 // Outgoing buffer extern int SError = NO_ERROR; extern int portbase = 0; extern void interrupt(*oldvects[2])(...); // char ccbuf[SBUFSIZ]; unsigned int startbuf = 0; unsigned int endbuf = 0; unsigned int inhead = 0; unsigned int intail = 0; unsigned int outhead = 0; unsigned int outtail = 0; char inbuf[IBUF_LEN]; // in buffer char outbuf[OBUF_LEN]; // out buffer void interrupt(*oldvects[2])(...); /* get status of the port */ int read_status_com(int portn) { return(inp(portn 5)); } /* send one valid char from the port */ void send_char_com(int portn,int cc) { while ((read_status_com(portn) & 0x40) == 0); outportb(portn,cc); } /* send one string from the port */ void send_string_com(int portn,int strlen,unsigned char *buf) { int k; k=0; do { send_char_com(portn,*(buf k)); k ; } while ((k < strlen)); } void interrupt com_int(...) { 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(portbase RXR);// read character into inbuffer 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 } // Inserts the character to be outputted into the output buffer, checking // for an open slot in the output buffer array. If there is, insert // the character, or if there isn't, wait until a slot opens up. serial& serial::operator<<(char ch ) { if (ch) // If this is a valid char { enable(); // turn on irqs to ensure data output //outportb(portbase MCR, MCR_INT | MCR_DTR | MCR_RTS);//modem control, outportb(portbase IER, IER_RX_INT); // check buffer, and if full, wait for an available opening // fprintf(stdout,"\n %c is pressed!\n",ch); //You can use this to verify which key is hit during your test while((outhead-1==outtail) ||(outtail==OBUF_LEN-1 && outhead==0)); disable(); // make sure nothing happens while changing buffer outbuf[outtail ] = ch; // insert character into buffer; if (outtail == OBUF_LEN) // if at end of out buffer outtail = 0; // reset pointer if((inportb(portbase IER)&IER_TX_INT) == 0) outportb(portbase IER,IER_TX_INT | IER_RX_INT); enable(); // re-enable interrupts } return(*this); } serial &serial::operator<<(char *str) // Outputs a string to the serial port { while (*str) { (*this) << (*str); str ; } return(*this); } serial &serial::operator>>( char &ch ) // 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. { 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(*this); // return the char } ch = -1; return(*this); // return nothing } /* Install our functions to handle communications */ void setvects(void) { oldvects[0] = getvect(0x0B); oldvects[1] = getvect(0x0C); setvect(0x0B, com_int); setvect(0x0C, com_int); } /* Uninstall our vectors before exiting the program */ void resvects(void) { setvect(0x0B, oldvects[0]); setvect(0x0C, oldvects[1]); } /* Tell modem that we're ready to go */ void serial::comm_on(void) { int temp, pnum; disable(); temp = inportb(portbase MCR) | 0x0f;//MCR_INT; outportb(portbase MCR, temp); temp = (inportb(portbase IER)) | IER_RX_INT;//|IER_TX_INT; outportb(portbase IER, temp); pnum = (portbase == COM1BASE ? COM1 : COM2); temp = inportb(PIC8259_IMR) & (pnum == COM1 ? IRQ4 : IRQ3); outportb(PIC8259_IMR, temp); // temp = inportb(portbase MCR) | MCR_DTR | MCR_RTS; // outportb(portbase MCR, temp); enable(); } /* Go off-line */ void serial::comm_off(void) { int temp; disable(); temp = inportb(PIC8259_IMR) | ~IRQ3 | ~IRQ4; outportb(PIC8259_IMR, temp); outportb(portbase IER, 0); outportb(portbase MCR, 0); enable(); } void serial::init_serial(void) { endbuf = startbuf = 0; 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 : printf("\ncannot find the serial port.\n"); return (-1); } RS232_Addr = (int far *)MK_FP(0x0040, Offset); /* Find out where the port is. */ if (*RS232_Addr == NULL) { printf("\ncannot find the serial port.\n"); 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(); return (0); } /* Set other communications parameters */ int serial::SetOthers(int Parity, int Bits, int StopBit) { int setting; if (portbase == 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(portbase LCR, setting); enable(); return (0); } /* Set up the port */ serial::serial(int Port, int Speed, int Parity, int Bits, int StopBit) { flag = 0; if (SetPort(Port)) flag = -1; if (SetSpeed(Speed)) flag = -1; if (SetOthers(Parity, Bits, StopBit)) flag = -1; if (!flag) init_serial(); } /* Control-Break interrupt handler */ int c_break(void) { int temp; disable(); temp = inportb(PIC8259_IMR) | ~IRQ3 | ~IRQ4; outportb(PIC8259_IMR, temp); outportb(portbase IER, 0); outportb(portbase MCR, 0); enable(); fprintf(stderr, "\nStill online.\n"); return(0); } |
ATEIN
高階會員 發表:105 回覆:320 積分:125 註冊:2002-07-05 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |