请求帮助:修改C程序使之在VC++6.0下编译运行
0603.rar
(18.47 KB)
请高手帮忙修改一下这段串口通信程序,使之能够在VC下编译运行。程序代码见附件0603.rar。
程序代码:
/*--------------------------------------------------------------------- FILENAME: GSERIAL.H This file is used to define const and class for GSERIAL.CPP 此文件用于定义常量和serial类的变量 --------------------------------------------------------------------*/ #include <dos.h> #include <conio.h> #include <stdio.h> #include <string.h> //Define Serial port Const 定义串口逻辑名常量 #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 IRQ0 0xFE // COM? 1111 1110 #define IRQ1 0xFD // COM? 1111 1101 #define IRQ2 0xFB // COM? 1111 1011 #define IRQ3 0xF7 // COM2 1111 0111 /* COM2 */ #define IRQ4 0xEF // COM1 1110 1111 /* COM1 */ #define IRQ5 0xDF // COM? 1101 1111 #define IRQ6 0xBF // COM? 1011 1111 #define IRQ7 0x7F // COM? 0111 1111 #define IRQ8 0xFE // COM? 1111 1110 #define IRQ9 0xFD // COM? 1111 1101 #define IRQ10 0xFB // COM? 1111 1011 #define IRQ11 0xF7 // COM? 1111 0111 #define IRQ12 0xEF // COM? 1110 1111 #define IRQ13 0xDF // COM? 1101 1111 #define IRQ14 0xBF // COM? 1011 1111 #define IRQ15 0x7F // COM? 0111 1111 #define FALSE 0 #define TRUE 1 #define ESC 0x1B /* ASCII Escape character */ #define ASCII 0x007F /* Mask ASCII characters */ #define NO_ERROR 0 /* 无错误No error */ #define BUF_OVFL 1 /* 缓冲区溢出Buffer overflowed */ #define SBUFSIZ 512 /* Serial buffer size */ #define IBUF_LEN 2048 // 接收缓冲区Incoming buffer #define OBUF_LEN 1024 // 发送缓冲区Outgoing buffer unsigned int PortBaseAddr[6]= {COM1BASE,COM2BASE,COM3BASE,COM4BASE,COM5BASE,COM6BASE}; // 70-8 71-9 72-10 73-11 74-12 75-13 76-14 77-15 int InterruptNo[6]= { 0x0C, 0x0B, 0x0D, 0x72, 0x73, 0x77};//4,3,5,10,11,15 int ComIRQ[6] = { IRQ4, IRQ3, IRQ5, IRQ10, IRQ11, IRQ15}; /////////////////////// class GSerial{ int flag; public: unsigned int m_unPortNo; unsigned int m_unPortBase; GSerial(void); ~GSerial(void); int InitSerialPort(int Port, int Speed, int Parity, int Bits, int StopBit); void CloseSerialPort(void); int SetDataFormat(int Parity, int Bits, int StopBit); int SetSpeed(int Speed); int SetPortBaseAddr(int Port); void CommOn(void); void CommOff(void); int ReadStatus(void); void SendChar(unsigned char unCh); void SendString(int nStrlen, unsigned char *unChBuf); //char ReadChar(void); void interrupt(*OldVects)(...); void SetVects(void interrupt(*New_Int)(...)); void ResetVects(void); };
程序代码:
/*------------------------------------------------------------------* 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]; // 接受数据buffer char outbuf[OBUF_LEN]; // 发送数据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() { } /* 读取串口LSR状态 */ int GSerial::ReadStatus(void) { return(inp(m_unPortBase+5)); } /* 发送一个字符 */ void GSerial::SendChar(unsigned char unCh) { while ((ReadStatus() & 0x40) == 0); outportb(m_unPortBase,unCh); } /* 发送一个字符串 */ void GSerial::SendString(int nStrlen, unsigned char *unChBuf) { int k=0; do { SendChar(*(unChBuf + k)); k++; } while ((k < nStrlen)); } /* 装入新的中断向量:中断服务程序地址 */ void GSerial::SetVects(void interrupt(*New_Int)(...)) { disable(); OldVects = getvect(InterruptNo[m_unPortNo-1]); setvect(InterruptNo[m_unPortNo-1], New_Int); enable(); } /* 恢复中断向量 */ void GSerial::ResetVects(void) { setvect(InterruptNo[m_unPortNo-1], OldVects); } /* 启动串口 */ 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(); } /* 关闭串口 */ 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(); } /* 设置串口号 */ int GSerial::SetPortBaseAddr(int Port) { if((Port<1)||(Port>6)) return(-1); m_unPortNo = Port; m_unPortBase = PortBaseAddr[m_unPortNo-1]; return (0); } /* 设置波特率 */ /* 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); } /* S设置数据格式:奇偶较验,数据位,停止位 */ 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(); /* 恢复中断向量 */ } /* 初始化串口:设置串口号,数据格式 */ 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); } /* 本函数非GSerial类成员函数 */ 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 } /* 本函数也不是GSerial类成员函数,是笔者为了多串口编程而设计的 */ 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; /* 定义GSerial类对象 */ /* 以下代码调用GSerial类成员函数初始化串口、打开串口 */ if (!gs.InitSerialPort(port, speed, parity, bits, stopbits)) { PortBase = PortBaseAddr[port-1]; /* 得到串口基地址,中断服务程序中要用到 */ gs.SetVects(ComIntServ); /* 装入中断服务程序向量 */ (); /* 打开串口 */ } 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]); /* 打印出终端状态,程序按ESC退出 */ 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(); /* 是否有Esc键,如有,则退出循环 */ switch (c) { case ESC: done = TRUE; /* 这里可对其他键进行响应处理 */ break; } if (!done) { gs.SendChar( c ); /* 如果不是Esc键,则从串口将键入的字符发送 */ 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); } }
[ 本帖最后由 li343 于 2009-10-9 13:35 编辑 ]