请求帮助:修改C程序使之在VC++6.0下编译运行
请高手帮忙修改一下这段串口通信程序,使之能够在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 编辑 ]










