串口通信是一个讨论了很久的问题,我曾经用VC6.0,VS2003, VS2005开发过串口程序。同样也写过单片机的串口通信程序。这次用纯C语言写了一个,放上来与大家分享。
该程序实现的原理是利用TC库函数outportb与inportb来读写对串口芯片的寄存器进行读写和配置,由于我一起开发过单片机的串口通信程序,所以这种方法我比较容易理解。我参考了网上很多资料,所以代码中有跟网上类似的地方,其中也做了一些优化和修改。
程序利用中断接收串口数据,利用查询方式来发送数据,可以自发自收。详细源代码如下:
程序在TC2.0 下编译运行通过。希望对大家有所帮助和启发。
#include
<
stdio.h
>
#include < conio.h >
#include < stdlib.h >
#include < dos.h >
#define MAXBUFFERSIZE 1024 /* 数据缓冲区大小 */
unsigned char DataBuffer[MAXBUFFERSIZE]; /**/ /* 数据缓冲区 */
int regBASE; /**/ /* 串口基地址 */
int inBuffer = 0 ; /**/ /* 接收计数 */
int outBuffer = 0 ; /**/ /* 发送计数 */
/**/ /* 以下枚举为串口相关设置选项 */
typedef enum ... {COM1,COM2} COM; /**/ /* 串口号 */
/**/ /* 奇偶校验类型 */
typedef enum ... {NONE=0,ODD=1,EVEN=3,MARK=5,SPACE=7} PARITY;
/**/ /* 数据位 */
typedef enum ... {BIT5,BIT6,BIT7,BIT8} DATABIT;
/**/ /* 停止位 */
typedef enum ... {BIT1=0,BIT15=1,BIT2=1} STOPBIT;
/**/ /* 自定义bool数据类型 */
typedef enum ... {false,true} bool ;
/**/ /* 8250寄存器偏移地址 */
typedef enum ... {RXR=0,TXR=0,IER=1,IIR=2,LCR=3,MCR=4,LSR=5,MSR=6,LSB=0,MSB=1}
regSeriesCOMM;
/**/ /* 串口结构体 */
typedef struct
... {
COM comNumber; /**//* 串口号 */
long comBps; /**//* 波特率 */
PARITY comParity; /**//* 奇偶校验类型 */
DATABIT comDataBit; /**//* 数据位 */
STOPBIT comStopBit; /**//* 停止位 */
} SeriesCOMM;
/**/ /* 设置波特率 */
bool SettingBPS( long bps);
/**/ /* 获取波特率 */
long GettingBPS();
/**/ /* 初始化串口 */
bool InitSeriesCOMM( long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit);
/**/ /* 打开串口 */
bool OpenCOMM( COM com,
long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit);
/**/ /* 关闭串口 */
void CloseCOMM();
/**/ /* 发送数据 */
void SendByte(unsigned char data);
/**/ /* 中断服务程序 */
void interrupt far asyncint();
/**/ /* 中断向量表 */
void interrupt( * asyncoldvect)();
/**/ /* 读取数据 */
unsigned char ReadData( void );
int main()
... {
unsigned char temp; /**//* 临时变量 用于缓存接收数据 */
char buffer[10]; /**//* 临时缓冲区 用于接收控制台输入数据 */
char * pParme; /**//* 控制台输入字符串指针 */
char sendBuffer[1024]; /**//* 发送数据缓冲区 */
SeriesCOMM thisComm; /**//* 串口结构 保存当前操作串口数据 */
/**//********************************************************************/
/**//* 该段程序用于向用户获取串口初始化配置 */
/**//* 根据用户输入的数据来配置串口 */
printf("Enter the Seriec COM Number(COM1:1,COM2):"); /**//* 获取要使用的串口 */
pParme = cgets(buffer);
if( atoi(pParme) == 2)
thisComm.comNumber = COM2;
else
thisComm.comNumber = COM1;
/**//* 获取波特率 */
printf(" Enter the Seriec COM BPS(eg:2400):");
pParme = cgets(buffer);
thisComm.comBps = atol(pParme);
/**//* 获取数据位位数 */
printf(" Please Choice the Data Bits: ");
printf("5 bits: 0 6 bits: 1 7 bits: 2 8 bits: 3 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 0)
thisComm.comDataBit = BIT5;
else if ( atoi(pParme) == 1)
thisComm.comDataBit = BIT6;
else if ( atoi(pParme) == 2)
thisComm.comDataBit = BIT7;
else
thisComm.comDataBit = BIT8;
/**//* 获取奇偶校验模式 */
printf(" Please Choice the Parity Check Mode: ");
printf("NONE: 0 ODD: 1 EVEN: 2 MARK: 3 SPACE: 4 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 1)
thisComm.comParity = ODD;
else if ( atoi(pParme) == 2)
thisComm.comParity = EVEN;
else if ( atoi(pParme) == 3)
thisComm.comParity = MARK;
else if ( atoi(pParme) == 4)
thisComm.comParity = SPACE;
else
thisComm.comParity = NONE;
/**//* 获取停止位位数 */
printf(" Please Choice the Stop Bits: ");
printf("1 bits: 0 1.5 bits: 1 2 bits: 2 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 1)
thisComm.comStopBit = BIT15;
else if ( atoi(pParme) == 2)
thisComm.comStopBit = BIT2;
else
thisComm.comStopBit = BIT1;
/**//* 根据用户配置打开串口 */
if(OpenCOMM(thisComm.comNumber,thisComm.comBps,thisComm.comDataBit,
thisComm.comParity,thisComm.comStopBit))
printf("The Series COMM Is Start... ");
else
printf("The Series COMM Opened False. ");
printf("The Series COMM Ready To Receive Data. ");
/**//* 如果是接收数据,将下面while语句注释取消,将发送语句注释掉
如果是发送数据,将while注释掉,取消发送语句注释 */
/**//* 接收数据 */
while(1)
...{
temp = ReadData();
if (temp != 0xFF) /**//* 如果接收的不是0xff 则打印接收结果 */
printf("%c",temp);
}
/**//*
while(1)
{
SendByte('a');
}
CloseCOMM();
getch(); */
return 0;
}
/**/ /*******************************************************************
函数名 : SettingBPS
参数功能 : 设置串口波特率
参数列表 : long bps : 输入 串口波特率
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : 波特率时钟为数据时钟的1/16,而INS8250频率为1.8432MHZ
所以有如下等式:
预置数 = (主时钟频率/16)/波特率=115200/波特率
********************************************************************/
bool SettingBPS( long bps)
... {
unsigned char regBPSMSB; /**//* 波特率寄存器高8位 */
unsigned char regBPSLSB; /**//* 波特率寄存器低8位 */
unsigned int regBPS; /**//* 波特率寄存器值 */
regBPS = 115200/bps; /**//* 获取波特率寄存器预置数 */
regBPSMSB = regBPS >> 8; /**//* 将预置数分解为高8位与低8位 */
regBPSLSB = regBPS & 0x00FF;
/**//* LCR控制寄存器的最高位D7为0时 地址 regBASE 与 regBASE+1 为接收/发送、
中断控制寄存器,当D7为1时,地址regBASE与regBASE+1 为波特率LSB、MSB
寄存器,所以设置波特率寄存器应先将LCR寄存器最高位置1*/
outportb((regBASE+LCR),0x80); /**//* 置D7为1 */
outportb((regBASE+LSB),regBPSLSB); /**//* 先设波特率寄存器低8位 */
outportb((regBASE+MSB),regBPSMSB); /**//* 设置波特率寄存器高8位 */
/**//* 读取波特率寄存器,如果读取值与设置值相等,表示设置成功
返回 true, 否则返回 false */
if(((inportb(regBASE+MSB)<< 8) | inportb(regBASE+LSB)) == regBPS)
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : GettingBPS
参数功能 : 获取串口波特率
参数列表 : 空
返回值 : long bps : 当前串口设置的波特率
备注 : 波特率 = 115200/波特率寄存器值
********************************************************************/
long GettingBPS()
... {
long bps;
outportb((regBASE+LCR),0x80); /**//* 置D7为1表示操作波特率寄存器 */
bps = 115200 / ((inportb(regBASE+MSB)<< 8) | inportb(regBASE+LSB));
return bps;
}
/**/ /*******************************************************************
函数名 : InitSeriesCOMM
参数功能 : 初始化串口
参数列表 : long bps 输入 波特率
DATABIT databit 输入 数据位位数
PARITY paritycheck 输入 奇偶校验模式
STOPBIT stopbit 输入 停止位位数
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : D7 :与串口初始化无关,D7为1表示操作波特率寄存器
D7为0表示操作RXT/TXT、IEE寄存器
D6 :当D6为1时,允许发送器空闲一个完整的发送周期
D5D4D3 | 含义
--------------------------------------
000/010/100/110 | 无奇偶校验
--------------------------------------
001 | 奇校验
--------------------------------------
011 | 偶校验
--------------------------------------
101 |标志(MARK)奇偶校验
|奇偶位恒为1
--------------------------------------
111 |空白(SPACE)奇偶校验
|奇偶位恒为0
--------------------------------------
D2 :停止位设置,当该位为0时,停止位为1位,该位为1时,
当D1D0=00时,停止位为1.5位,否则停止位为2位
D1D0 | 数据位数
----------------------
00 | 5
----------------------
01 | 6
----------------------
10 | 7
----------------------
11 | 8
------------------------
********************************************************************/
bool InitSeriesCOMM( long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit)
... {
unsigned char parme;
/**//* 组合参数 */
parme = paritycheck<<3 | stopbit<<2 | databit;
/**//* 设置波特率 */
SettingBPS(bps);
outportb((regBASE+LCR),0x00); /**//* 置LCR最高位为0 */
outportb((regBASE+LCR),parme); /**//* 根据参数设置LCR寄存器 */
/**//* 读取控制寄存器的值,如果和设置值相同,说明设置成功
返回 true,否则设置失败,返回false。 */
if(inportb(regBASE+LCR) == parme)
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : OpenCOMM
参数功能 : 打开串口进行串行通信
参数列表 : COM com 输入 串口号
long bps 输入 波特率
DATABIT databit 输入 数据位位数
PARITY paritycheck 输入 奇偶校验模式
STOPBIT stopbit 输入 停止位位数
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : 系统中断表:
INT | (Hex) | IRQ Common Uses
---------------------------------------
08 | 0 | System Timer
---------------------------------------
09 | 1 | Keyboard
---------------------------------------
0A | 2 | Redirected
---------------------------------------
0B | 3 | Serial Comms. COM2/COM4
---------------------------------------
0C | 4 | Serial Comms. COM1/COM3
---------------------------------------
0D | 5 | Reserved/Sound Card
---------------------------------------
0E | 6 | Floppy Disk Controller
---------------------------------------
0F | 7 | Parallel Comms.
---------------------------------------
70 | 8 | Real Time Clock
---------------------------------------
71 | 9 | Reserved
---------------------------------------
72 | 10 | Reserved
---------------------------------------
73 | 11 | Reserved
---------------------------------------
74 | 12 | PS/2 Mouse
---------------------------------------
75 | 13 | Maths Co-Processor
---------------------------------------
76 | 14 | Hard Disk Drive
---------------------------------------
77 | 15 | Reserved
---------------------------------------
********************************************************************/
bool OpenCOMM( COM com,
long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit)
... {
unsigned char temp;
/**//* 根据用户选择的串口设置寄存器基地址
如果选择串口1,基地址为0x03F8
如果选择串口2,基地址为0x02F8 */
if(com)
regBASE = 0x2F8;
else
regBASE = 0x3F8;
asyncoldvect = getvect(0x0C); /**//* 获取中断向量表 */
disable(); /**//* 禁止系统中断 */
outportb((regBASE+LCR),0x00); /**//* 选择设置中断寄存器*/
outportb((regBASE+IER),0x01); /**//* 允许串口接收中断 */
temp = inportb(0x21) & 0xef; /**//* 读取当前中断设置 */
outportb(0x21,temp); /**//* 注册串口中断 */
setvect(0x0C,asyncint); /**//* 设置中断向量表 */
enable(); /**//* 允许系统中断 */
/**//* 调用串口初始化函数初始化串口,如果调用成功,表示
打开端口成功,返回 true,否则打开端口失败,返回false。 */
if(InitSeriesCOMM(bps,databit,paritycheck,stopbit))
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : SendByte
参数功能 : 利用串口发送1字节数据
参数列表 : unsigned char data 输入 发送字节数据
返回值 : void
备注 :
********************************************************************/
void SendByte(unsigned char data)
... {
/**//* 查询LSR寄存器,如果数据准备好,则发送1字节数据 */
while (((inportb(regBASE+LSR)) & 0x40) == 0);
/**//* 将数据写入RTX寄存器发送 */
outportb((regBASE+TXR),data);
}
/**/ /*******************************************************************
函数名 : CloseCOMM
参数功能 : 关闭串口
参数列表 : 空
返回值 : void
备注 :
********************************************************************/
void CloseCOMM()
... {
disable(); /**//* 禁止全部中断 */
outportb((regBASE+LCR),0x00); /**//* 清串口控制寄存器 */
outportb((regBASE+IER),0x00); /**//* 清串口中断寄存器 */
outportb((regBASE+MCR),0x00); /**//* 清串口MODEM寄存器 */
outportb(0x21,inportb(0x21)&0x10); /**//* 禁止串口全局中断 */
enable(); /**//* 开全局中断 */
setvect(0x0C,asyncoldvect); /**//* 重设中断向量表 */
}
/**/ /*******************************************************************
函数名 : asyncint
参数功能 : 串口接收中断服务程序,通过中断接收串口数据
参数列表 : 空
返回值 : void
备注 :
********************************************************************/
void interrupt far asyncint()
... {
/**//* 接收数据 */
DataBuffer[inBuffer++] = inportb(regBASE);
/**//* 如果接收到最大数据量,重设数据指针*/
if (inBuffer >= MAXBUFFERSIZE)
inBuffer = 0;
outportb(0x20,0x20); /**//* 中断完成,返回主程序 */
}
/**/ /*******************************************************************
函数名 : ReadData
参数功能 : 从接收缓冲区读取数据
参数列表 : 空
返回值 : unsigned char temp : 读取数据成功
0xff : 读取数据失败
备注 :
********************************************************************/
unsigned char ReadData( void )
... {
unsigned char temp;
if (outBuffer != inBuffer)
...{
temp = DataBuffer[outBuffer++];
/**//* 如果读取到最最后一个数据,重设读取数据指针*/
if (outBuffer >= MAXBUFFERSIZE)
outBuffer = 0;
return temp;
} /**//* 返回读取数据 */
else
return 0xff; /**//* 读取失败,返回0xff*/
}
#include < conio.h >
#include < stdlib.h >
#include < dos.h >
#define MAXBUFFERSIZE 1024 /* 数据缓冲区大小 */
unsigned char DataBuffer[MAXBUFFERSIZE]; /**/ /* 数据缓冲区 */
int regBASE; /**/ /* 串口基地址 */
int inBuffer = 0 ; /**/ /* 接收计数 */
int outBuffer = 0 ; /**/ /* 发送计数 */
/**/ /* 以下枚举为串口相关设置选项 */
typedef enum ... {COM1,COM2} COM; /**/ /* 串口号 */
/**/ /* 奇偶校验类型 */
typedef enum ... {NONE=0,ODD=1,EVEN=3,MARK=5,SPACE=7} PARITY;
/**/ /* 数据位 */
typedef enum ... {BIT5,BIT6,BIT7,BIT8} DATABIT;
/**/ /* 停止位 */
typedef enum ... {BIT1=0,BIT15=1,BIT2=1} STOPBIT;
/**/ /* 自定义bool数据类型 */
typedef enum ... {false,true} bool ;
/**/ /* 8250寄存器偏移地址 */
typedef enum ... {RXR=0,TXR=0,IER=1,IIR=2,LCR=3,MCR=4,LSR=5,MSR=6,LSB=0,MSB=1}
regSeriesCOMM;
/**/ /* 串口结构体 */
typedef struct
... {
COM comNumber; /**//* 串口号 */
long comBps; /**//* 波特率 */
PARITY comParity; /**//* 奇偶校验类型 */
DATABIT comDataBit; /**//* 数据位 */
STOPBIT comStopBit; /**//* 停止位 */
} SeriesCOMM;
/**/ /* 设置波特率 */
bool SettingBPS( long bps);
/**/ /* 获取波特率 */
long GettingBPS();
/**/ /* 初始化串口 */
bool InitSeriesCOMM( long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit);
/**/ /* 打开串口 */
bool OpenCOMM( COM com,
long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit);
/**/ /* 关闭串口 */
void CloseCOMM();
/**/ /* 发送数据 */
void SendByte(unsigned char data);
/**/ /* 中断服务程序 */
void interrupt far asyncint();
/**/ /* 中断向量表 */
void interrupt( * asyncoldvect)();
/**/ /* 读取数据 */
unsigned char ReadData( void );
int main()
... {
unsigned char temp; /**//* 临时变量 用于缓存接收数据 */
char buffer[10]; /**//* 临时缓冲区 用于接收控制台输入数据 */
char * pParme; /**//* 控制台输入字符串指针 */
char sendBuffer[1024]; /**//* 发送数据缓冲区 */
SeriesCOMM thisComm; /**//* 串口结构 保存当前操作串口数据 */
/**//********************************************************************/
/**//* 该段程序用于向用户获取串口初始化配置 */
/**//* 根据用户输入的数据来配置串口 */
printf("Enter the Seriec COM Number(COM1:1,COM2):"); /**//* 获取要使用的串口 */
pParme = cgets(buffer);
if( atoi(pParme) == 2)
thisComm.comNumber = COM2;
else
thisComm.comNumber = COM1;
/**//* 获取波特率 */
printf(" Enter the Seriec COM BPS(eg:2400):");
pParme = cgets(buffer);
thisComm.comBps = atol(pParme);
/**//* 获取数据位位数 */
printf(" Please Choice the Data Bits: ");
printf("5 bits: 0 6 bits: 1 7 bits: 2 8 bits: 3 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 0)
thisComm.comDataBit = BIT5;
else if ( atoi(pParme) == 1)
thisComm.comDataBit = BIT6;
else if ( atoi(pParme) == 2)
thisComm.comDataBit = BIT7;
else
thisComm.comDataBit = BIT8;
/**//* 获取奇偶校验模式 */
printf(" Please Choice the Parity Check Mode: ");
printf("NONE: 0 ODD: 1 EVEN: 2 MARK: 3 SPACE: 4 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 1)
thisComm.comParity = ODD;
else if ( atoi(pParme) == 2)
thisComm.comParity = EVEN;
else if ( atoi(pParme) == 3)
thisComm.comParity = MARK;
else if ( atoi(pParme) == 4)
thisComm.comParity = SPACE;
else
thisComm.comParity = NONE;
/**//* 获取停止位位数 */
printf(" Please Choice the Stop Bits: ");
printf("1 bits: 0 1.5 bits: 1 2 bits: 2 ");
pParme = cgets(buffer);
if ( atoi(pParme) == 1)
thisComm.comStopBit = BIT15;
else if ( atoi(pParme) == 2)
thisComm.comStopBit = BIT2;
else
thisComm.comStopBit = BIT1;
/**//* 根据用户配置打开串口 */
if(OpenCOMM(thisComm.comNumber,thisComm.comBps,thisComm.comDataBit,
thisComm.comParity,thisComm.comStopBit))
printf("The Series COMM Is Start... ");
else
printf("The Series COMM Opened False. ");
printf("The Series COMM Ready To Receive Data. ");
/**//* 如果是接收数据,将下面while语句注释取消,将发送语句注释掉
如果是发送数据,将while注释掉,取消发送语句注释 */
/**//* 接收数据 */
while(1)
...{
temp = ReadData();
if (temp != 0xFF) /**//* 如果接收的不是0xff 则打印接收结果 */
printf("%c",temp);
}
/**//*
while(1)
{
SendByte('a');
}
CloseCOMM();
getch(); */
return 0;
}
/**/ /*******************************************************************
函数名 : SettingBPS
参数功能 : 设置串口波特率
参数列表 : long bps : 输入 串口波特率
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : 波特率时钟为数据时钟的1/16,而INS8250频率为1.8432MHZ
所以有如下等式:
预置数 = (主时钟频率/16)/波特率=115200/波特率
********************************************************************/
bool SettingBPS( long bps)
... {
unsigned char regBPSMSB; /**//* 波特率寄存器高8位 */
unsigned char regBPSLSB; /**//* 波特率寄存器低8位 */
unsigned int regBPS; /**//* 波特率寄存器值 */
regBPS = 115200/bps; /**//* 获取波特率寄存器预置数 */
regBPSMSB = regBPS >> 8; /**//* 将预置数分解为高8位与低8位 */
regBPSLSB = regBPS & 0x00FF;
/**//* LCR控制寄存器的最高位D7为0时 地址 regBASE 与 regBASE+1 为接收/发送、
中断控制寄存器,当D7为1时,地址regBASE与regBASE+1 为波特率LSB、MSB
寄存器,所以设置波特率寄存器应先将LCR寄存器最高位置1*/
outportb((regBASE+LCR),0x80); /**//* 置D7为1 */
outportb((regBASE+LSB),regBPSLSB); /**//* 先设波特率寄存器低8位 */
outportb((regBASE+MSB),regBPSMSB); /**//* 设置波特率寄存器高8位 */
/**//* 读取波特率寄存器,如果读取值与设置值相等,表示设置成功
返回 true, 否则返回 false */
if(((inportb(regBASE+MSB)<< 8) | inportb(regBASE+LSB)) == regBPS)
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : GettingBPS
参数功能 : 获取串口波特率
参数列表 : 空
返回值 : long bps : 当前串口设置的波特率
备注 : 波特率 = 115200/波特率寄存器值
********************************************************************/
long GettingBPS()
... {
long bps;
outportb((regBASE+LCR),0x80); /**//* 置D7为1表示操作波特率寄存器 */
bps = 115200 / ((inportb(regBASE+MSB)<< 8) | inportb(regBASE+LSB));
return bps;
}
/**/ /*******************************************************************
函数名 : InitSeriesCOMM
参数功能 : 初始化串口
参数列表 : long bps 输入 波特率
DATABIT databit 输入 数据位位数
PARITY paritycheck 输入 奇偶校验模式
STOPBIT stopbit 输入 停止位位数
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : D7 :与串口初始化无关,D7为1表示操作波特率寄存器
D7为0表示操作RXT/TXT、IEE寄存器
D6 :当D6为1时,允许发送器空闲一个完整的发送周期
D5D4D3 | 含义
--------------------------------------
000/010/100/110 | 无奇偶校验
--------------------------------------
001 | 奇校验
--------------------------------------
011 | 偶校验
--------------------------------------
101 |标志(MARK)奇偶校验
|奇偶位恒为1
--------------------------------------
111 |空白(SPACE)奇偶校验
|奇偶位恒为0
--------------------------------------
D2 :停止位设置,当该位为0时,停止位为1位,该位为1时,
当D1D0=00时,停止位为1.5位,否则停止位为2位
D1D0 | 数据位数
----------------------
00 | 5
----------------------
01 | 6
----------------------
10 | 7
----------------------
11 | 8
------------------------
********************************************************************/
bool InitSeriesCOMM( long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit)
... {
unsigned char parme;
/**//* 组合参数 */
parme = paritycheck<<3 | stopbit<<2 | databit;
/**//* 设置波特率 */
SettingBPS(bps);
outportb((regBASE+LCR),0x00); /**//* 置LCR最高位为0 */
outportb((regBASE+LCR),parme); /**//* 根据参数设置LCR寄存器 */
/**//* 读取控制寄存器的值,如果和设置值相同,说明设置成功
返回 true,否则设置失败,返回false。 */
if(inportb(regBASE+LCR) == parme)
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : OpenCOMM
参数功能 : 打开串口进行串行通信
参数列表 : COM com 输入 串口号
long bps 输入 波特率
DATABIT databit 输入 数据位位数
PARITY paritycheck 输入 奇偶校验模式
STOPBIT stopbit 输入 停止位位数
返回值 : 如果设置成功 返回 true
如果设置失败 返回 false
备注 : 系统中断表:
INT | (Hex) | IRQ Common Uses
---------------------------------------
08 | 0 | System Timer
---------------------------------------
09 | 1 | Keyboard
---------------------------------------
0A | 2 | Redirected
---------------------------------------
0B | 3 | Serial Comms. COM2/COM4
---------------------------------------
0C | 4 | Serial Comms. COM1/COM3
---------------------------------------
0D | 5 | Reserved/Sound Card
---------------------------------------
0E | 6 | Floppy Disk Controller
---------------------------------------
0F | 7 | Parallel Comms.
---------------------------------------
70 | 8 | Real Time Clock
---------------------------------------
71 | 9 | Reserved
---------------------------------------
72 | 10 | Reserved
---------------------------------------
73 | 11 | Reserved
---------------------------------------
74 | 12 | PS/2 Mouse
---------------------------------------
75 | 13 | Maths Co-Processor
---------------------------------------
76 | 14 | Hard Disk Drive
---------------------------------------
77 | 15 | Reserved
---------------------------------------
********************************************************************/
bool OpenCOMM( COM com,
long bps,
DATABIT databit,
PARITY paritycheck,
STOPBIT stopbit)
... {
unsigned char temp;
/**//* 根据用户选择的串口设置寄存器基地址
如果选择串口1,基地址为0x03F8
如果选择串口2,基地址为0x02F8 */
if(com)
regBASE = 0x2F8;
else
regBASE = 0x3F8;
asyncoldvect = getvect(0x0C); /**//* 获取中断向量表 */
disable(); /**//* 禁止系统中断 */
outportb((regBASE+LCR),0x00); /**//* 选择设置中断寄存器*/
outportb((regBASE+IER),0x01); /**//* 允许串口接收中断 */
temp = inportb(0x21) & 0xef; /**//* 读取当前中断设置 */
outportb(0x21,temp); /**//* 注册串口中断 */
setvect(0x0C,asyncint); /**//* 设置中断向量表 */
enable(); /**//* 允许系统中断 */
/**//* 调用串口初始化函数初始化串口,如果调用成功,表示
打开端口成功,返回 true,否则打开端口失败,返回false。 */
if(InitSeriesCOMM(bps,databit,paritycheck,stopbit))
return true;
else
return false;
}
/**/ /*******************************************************************
函数名 : SendByte
参数功能 : 利用串口发送1字节数据
参数列表 : unsigned char data 输入 发送字节数据
返回值 : void
备注 :
********************************************************************/
void SendByte(unsigned char data)
... {
/**//* 查询LSR寄存器,如果数据准备好,则发送1字节数据 */
while (((inportb(regBASE+LSR)) & 0x40) == 0);
/**//* 将数据写入RTX寄存器发送 */
outportb((regBASE+TXR),data);
}
/**/ /*******************************************************************
函数名 : CloseCOMM
参数功能 : 关闭串口
参数列表 : 空
返回值 : void
备注 :
********************************************************************/
void CloseCOMM()
... {
disable(); /**//* 禁止全部中断 */
outportb((regBASE+LCR),0x00); /**//* 清串口控制寄存器 */
outportb((regBASE+IER),0x00); /**//* 清串口中断寄存器 */
outportb((regBASE+MCR),0x00); /**//* 清串口MODEM寄存器 */
outportb(0x21,inportb(0x21)&0x10); /**//* 禁止串口全局中断 */
enable(); /**//* 开全局中断 */
setvect(0x0C,asyncoldvect); /**//* 重设中断向量表 */
}
/**/ /*******************************************************************
函数名 : asyncint
参数功能 : 串口接收中断服务程序,通过中断接收串口数据
参数列表 : 空
返回值 : void
备注 :
********************************************************************/
void interrupt far asyncint()
... {
/**//* 接收数据 */
DataBuffer[inBuffer++] = inportb(regBASE);
/**//* 如果接收到最大数据量,重设数据指针*/
if (inBuffer >= MAXBUFFERSIZE)
inBuffer = 0;
outportb(0x20,0x20); /**//* 中断完成,返回主程序 */
}
/**/ /*******************************************************************
函数名 : ReadData
参数功能 : 从接收缓冲区读取数据
参数列表 : 空
返回值 : unsigned char temp : 读取数据成功
0xff : 读取数据失败
备注 :
********************************************************************/
unsigned char ReadData( void )
... {
unsigned char temp;
if (outBuffer != inBuffer)
...{
temp = DataBuffer[outBuffer++];
/**//* 如果读取到最最后一个数据,重设读取数据指针*/
if (outBuffer >= MAXBUFFERSIZE)
outBuffer = 0;
return temp;
} /**//* 返回读取数据 */
else
return 0xff; /**//* 读取失败,返回0xff*/
}