📄 rs232x3.cpp
字号:
#include <dos.h>
#include "rs232x3.h"
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
#define THR 0
#define RDR 0
#define BRDL 0
#define BRDH 1
#define IER 1
#define IIR 2
#define FCR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
#define IRQ4MaskBit 0x10
#define IRQ3MaskBit 0x08
#define IRQ6MaskBit 0x40
#define IRQ7MaskBit 0x80
#define BUF_SIZE 1500
unsigned char InputBuf[3][BUF_SIZE];
unsigned int IBufGetIdx[3];
unsigned int IBufPutIdx[3];
unsigned char OutputBuf[3][BUF_SIZE];
unsigned int OBufGetIdx[3];
unsigned int OBufPutIdx[3];
void interrupt ( *oldCOM1handler)(__CPPARGS);
void interrupt ( *oldCOM2handler)(__CPPARGS);
void interrupt ( *oldCOM3handler)(__CPPARGS);
void interrupt COM1_ISR(__CPPARGS);
void interrupt COM2_ISR(__CPPARGS);
void interrupt COM3_ISR(__CPPARGS);
int BasePort[3]={ 0x3f8, 0xff80, 0xff10 };
int PutInputData( int PortNum, char abyte ); // call by ISR
int GetOutputData( int PortNum ); // call by ISR
// BaudIdx = 0: 230.4kbps ( only for COM2 COM3 )
// BaudIdx = 1: 115.2kbps
// BaudIdx = 2: 57.6kbps
// BaudIdx = 3: 38.4kbps
// BaudIdx = 6: 19.2kbps
// BaudIdx = 12: 9600bps
// BaudIdx = ...
int InitUART( int PortNum, unsigned int BaudIdx )
{
int i1;
unsigned int tport;
// check parameters
switch( PortNum )
{
case COM1:
tport = 0x3f8;
if( BaudIdx==0 ) BaudIdx=1;
break;
case COM2:
tport = 0xff80;
break;
case COM3:
tport = 0xff10;
break;
default:
return -1;
}
if( PortNum==COM1 )
{
outportb(tport + LCR, 0x80); // DLAB = 1, set baud reg access
outportb(tport + BRDH, (BaudIdx>>8));
outportb(tport + BRDL, BaudIdx);
outportb(tport + LCR, 0x03); // 8bit 1stop No_parity
outportb(tport + IER, 0); // set IER value
outportb(tport + MCR, 0x0b); // set MCR value
outportb(tport + IIR, 0); // disable FIFO of 16550, if existed
inportb(tport + LSR); // clear any line status interrupt
inportb(tport + RDR); // clear any receive interrupt
inportb(tport + IIR); // clear any transmitter interrupt
inportb(tport + MSR); // clear any modem status interrupt
outportb(tport + FCR, 0); // disable FIFO in 16C550
outportb(tport + IER, 0x01);
}
else
{
// for 96MHz:1.8432MHz baudrate
if( BaudIdx==0 ) BaudIdx *= 26;
else BaudIdx *= 52;
outport(tport + LCR*2, 0x80); // DLAB = 1, set baud reg access
outport(tport + BRDH*2, (BaudIdx>>8)&0x00ff);
outport(tport + BRDL*2, BaudIdx&0x00ff);
outport(tport + LCR*2, 0x03); // 8bit 1stop No_parity
outport(tport + IER*2, 0); // set IER value
outport(tport + MCR*2, 0x0b); // set MCR value
outport(tport + IIR*2, 0); // disable FIFO of 16550, if existed
inport(tport + LSR*2); // clear any line status interrupt
inport(tport + RDR*2); // clear any receive interrupt
inport(tport + IIR*2); // clear any transmitter interrupt
inport(tport + MSR*2); // clear any modem status interrupt
outport(tport + FCR*2, 0); // disable FIFO in 16C550
outport(tport + IER*2, 0x01);
}
IBufGetIdx[PortNum] = 0;
IBufPutIdx[PortNum] = 0;
OBufGetIdx[PortNum] = 0;
OBufPutIdx[PortNum] = 0;
return 0;
}
void interrupt COM1_ISR(__CPPARGS)
{
int i1;
unsigned char status;
unsigned int tport;
enable( );
tport = BasePort[COM1];
status = inportb(tport + IIR) & 7;
while( status != 1 )
{
i1 = inportb(tport + LSR);
switch (status)
{
case 0: // MODEM status change
inportb(tport + MSR);
break;
case 2: // THR empty
lab4:
i1 = GetOutputData( COM1 );
if( i1 != -1 ) outportb( tport+THR, i1 );
else outportb( tport+IER, inportb(tport+IER) & 0xd);
break;
case 4: // received data available
PutInputData( COM1, inportb( tport+RDR ) );
break;
case 6: // Line status change
break;
}
status = inportb(tport + IIR) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (inportb(tport + IER)&2) && (inportb(tport + LSR) & 0x20) )
goto lab4;
outport( 0xff22, 0x0c ); // specific EOI command for IRQ4
}
void interrupt COM2_ISR(__CPPARGS)
{
int i1;
unsigned int tport;
unsigned int status;
enable( );
tport = BasePort[COM2];
status = inport(tport + IIR*2) & 7;
while( status != 1 )
{
i1 = inport(tport + LSR*2);
switch (status)
{
case 0: // MODEM status change
inport(tport + MSR*2);
break;
case 2: // THR empty
lab4:
i1 = GetOutputData( COM2 );
if( i1 != -1 ) outport( tport+THR*2, i1 );
else outport( tport+IER*2, inport(tport+IER*2) & 0xd);
break;
case 4: // received data available
PutInputData( COM2, inport( tport+RDR*2 ) );
break;
case 6: // Line status change
break;
}
status = inport(tport + IIR*2) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (inport(tport + IER*2)&2) && (inport(tport + LSR*2) & 0x20) )
goto lab4;
outport( 0xff22, 0x0014 ); // specific EOI command
}
void interrupt COM3_ISR(__CPPARGS)
{
int i1;
unsigned int status;
unsigned int tport;
enable( );
tport = BasePort[COM3];
status = inport(tport + IIR*2) & 7;
while( status != 1 )
{
i1 = inport(tport + LSR*2);
switch (status)
{
case 0: // MODEM status change
inport(tport + MSR*2);
break;
case 2: // THR empty
lab4:
i1 = GetOutputData( COM3 );
if( i1 != -1 ) outport( tport+THR*2, i1 );
else outport( tport+IER*2, inport(tport+IER*2) & 0xd);
break;
case 4: // received data available
PutInputData( COM3, inport( tport+RDR*2 ) );
break;
case 6: // Line status change
break;
}
status = inport(tport + IIR*2) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (inport(tport + IER*2)&2) && (inport(tport + LSR*2) & 0x20) )
goto lab4;
outport( 0xff22, 0x0011 ); // specific EOI command
}
int GetOutputData( int PortNum )
{
int i, i1;
i1 = PortNum;
if( OBufGetIdx[i1] != OBufPutIdx[i1] )
{
i = (int)OutputBuf[i1][OBufGetIdx[i1]];
OBufGetIdx[i1] = ( OBufGetIdx[i1] + 1 ) % BUF_SIZE;
return i;
}
return -1;
}
int PutOutputData( int PortNum, char abyte )
{
unsigned int Idx;
int i1;
i1 = PortNum;
if( OBufGetIdx[i1] == 0 ) Idx = BUF_SIZE - 1;
else Idx = OBufGetIdx[i1] - 1;
if( OBufPutIdx[i1] == Idx ) return -1;
OutputBuf[i1][OBufPutIdx[i1]] = abyte;
OBufPutIdx[i1] = ( OBufPutIdx[i1] + 1 ) % BUF_SIZE;
return 0;
}
void StartSend( int PortNum )
{
int i1;
unsigned char aa;
unsigned int tport;
tport = BasePort[PortNum];
if( PortNum==COM1 )
{
aa = inportb(tport+IER);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( PortNum );
if( i1 == -1 ) return;
outportb( tport+THR, (char)i1 );
outportb( tport+IER, aa|0x02 ); // enable THR interrupt
}
}
else
{
aa = inport(tport+IER*2);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( PortNum );
if( i1 == -1 ) return;
outport( tport+THR*2, (char)i1 );
outport( tport+IER*2, aa|0x02 ); // enable THR interrupt
}
}
}
int PutInputData( int PortNum, char abyte )
{
unsigned int Idx;
int i1;
i1 = PortNum;
if( IBufGetIdx[i1] == 0 ) Idx = BUF_SIZE - 1;
else Idx = IBufGetIdx[i1] - 1;
if( IBufPutIdx[i1] == Idx ) return -1;
InputBuf[i1][IBufPutIdx[i1]] = abyte;
IBufPutIdx[i1] = ( IBufPutIdx[i1] + 1 ) % BUF_SIZE;
return 0;
}
int GetInputData( int PortNum )
{
int i;
int i1;
i1 = PortNum;
if( IBufGetIdx[i1] != IBufPutIdx[i1] )
{
i = (int)InputBuf[i1][IBufGetIdx[i1]];
IBufGetIdx[i1] = ( IBufGetIdx[i1] + 1 ) % BUF_SIZE;
return i;
}
return -1;
}
int InstallISR( int PortNum )
{
unsigned char MaskBit;
switch( PortNum )
{
case COM1:
MaskBit = IRQ4MaskBit;
oldCOM1handler = getvect( 0x0c );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0c, COM1_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM2:
oldCOM2handler = getvect( 0x14 );
outport( 0xff44, inport(0xff44)|0x0008 );
setvect( 0x14, COM2_ISR );
outport( 0xff44, inport(0xff44)&0xfff7 );
break;
case COM3:
oldCOM3handler = getvect( 0x61 );
outport( 0xff42, inport(0xff42)|0x0008 );
setvect( 0x61, COM3_ISR );
outport( 0xff42, inportb(0xff42)&0xfff7 );
break;
default:
return -1;
}
return 0;
}
int UninstallISR( int PortNum )
{
switch( PortNum )
{
case COM1:
setvect( 0x0c, oldCOM1handler );
break;
case COM2:
outport( 0xff44, inport(0xff44)|0x0008 );
setvect( 0x14, oldCOM2handler );
break;
case COM3:
outport( 0xff42, inport(0xff42)|0x0008 );
setvect( 0x61, oldCOM3handler );
break;
default:
return -1;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -