📄 rs485.cpp
字号:
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include "rs485.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 LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
#define IRQ4MaskBit 0x10
#define IRQ3MaskBit 0x08
#define IRQ5MaskBit 0x20
#define IRQ6MaskBit 0x40
#define IRQ7MaskBit 0x80
#define BUF_SIZ 1500
char InputBuf[BUF_SIZ];
unsigned int IBufGetIdx;
unsigned int IBufPutIdx;
char OutputBuf[BUF_SIZ];
unsigned int OBufGetIdx;
unsigned int OBufPutIdx;
void interrupt ( *oldCOMhandler)(__CPPARGS);
void interrupt COM_ISR(__CPPARGS);
int tport;
int PutInputData( char abyte ); // call by ISR
int GetOutputData( ); // call by ISR
// BaudIdx = 1: 115.2kbps
// BaudIdx = 2: 57.6kbps
// BaudIdx = 3: 38.4kbps
// BaudIdx = 6: 19.2kbps
// BaudIdx = 12: 9600bps
// BaudIdx = ...
int InitUART( int PortNum, int BaudIdx )
{
int i1;
// check parameters
switch( PortNum )
{
case COM1:
tport = 0x3f8;
break;
case COM2:
tport = 0x2f8;
break;
case COM3:
tport = 0x3e8; // 0x300
break;
case COM4:
tport = 0x2e8;
break;
default:
return -1;
}
outportb(tport + LCR, 0x80); // DLAB = 1, set baud reg access
outportb(tport + BRDH, BaudIdx>>8);
outport(tport + BRDL, BaudIdx);
outportb(tport + LCR, 0x03); // 8bit 1stop No_parity
outportb(tport + IER, 0x03); // set IER value
// set MCR value, MCR.D1=RTS=0, MCR.D0=DTR=0 for RS485
outportb(tport + MCR, 0x08);
outportb(tport + IIR, 0); // disable FIFO of 16550, if existed
i1 = (int)inportb(tport + LSR); // clear any line status interrupt
if( i1 == -1 ) return -2;
inportb(tport + RDR); // clear any receive interrupt
inportb(tport + IIR); // clear any transmitter interrupt
inportb(tport + MSR); // clear any modem status interrupt
outportb(tport + IER, 0); // some clones require this!?
outportb(tport + IER, 0x01);
IBufGetIdx = 0;
IBufPutIdx = 0;
OBufGetIdx = 0;
OBufPutIdx = 0;
return 0;
}
void interrupt COM_ISR(__CPPARGS)
{
int i1;
unsigned char status;
enable( );
status = inportb(tport + IIR);
status &= 0x07;
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( );
if( i1 != -1 ) outportb( tport+THR, i1 );
else
{
// disable THR interrupt as no data any more
outportb( tport+IER, inportb(tport+IER) & 0xd);
// wait transmit shift register empty
for( i1=0; i1<10000; i1++ )
{
if( (inportb(tport + LSR)&0x60) == 0x60 ) break;
}
// disable RS485 data send by RTS=0, DTR=0
outportb( tport+MCR, 0x08);
}
break;
case 4: // received data available
PutInputData( 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;
switch( tport )
{
case 0x3f8:
outportb( 0x20, 0x64 ); // specific EOI command
break;
case 0x2f8:
outportb( 0x20, 0x63 ); // specific EOI command
break;
case 0x3e8:
outportb( 0x20, 0x66 ); // specific EOI command
break;
case 0x2e8:
outportb( 0x20, 0x65 ); // specific EOI command
default:
outportb( 0x20, 0x20 ); // normal EOI command
}
}
int GetOutputData( )
{
int i;
if( OBufGetIdx != OBufPutIdx )
{
i = (unsigned int)OutputBuf[OBufGetIdx];
OBufGetIdx = ( OBufGetIdx + 1 ) % BUF_SIZ;
return i;
}
return -1;
}
int PutOutputData( char abyte )
{
unsigned int Idx;
if( OBufGetIdx == 0 ) Idx = BUF_SIZ - 1;
else Idx = OBufGetIdx - 1;
if( OBufPutIdx == Idx ) return -1;
OutputBuf[OBufPutIdx] = abyte;
OBufPutIdx = ( OBufPutIdx + 1 ) % BUF_SIZ;
return 0;
}
void StartSend( )
{
int i1;
unsigned char aa;
aa = inportb(tport+IER);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( );
if( i1 == -1 ) return;
// enable RS485 send data out by setting DTR=1, RTS=1
outportb( tport+MCR, 0x0b);
outportb( tport+THR, i1 );
outportb( tport+IER, aa|0x02 ); // enable THR interrupt
}
}
int PutInputData( char abyte )
{
unsigned int Idx;
if( IBufGetIdx == 0 ) Idx = BUF_SIZ - 1;
else Idx = IBufGetIdx - 1;
if( IBufPutIdx == Idx ) return -1;
InputBuf[IBufPutIdx] = abyte;
IBufPutIdx = ( IBufPutIdx + 1 ) % BUF_SIZ;
return 0;
}
int GetInputData( )
{
int i;
if( IBufGetIdx != IBufPutIdx )
{
i = (unsigned int)InputBuf[IBufGetIdx];
IBufGetIdx = ( IBufGetIdx + 1 ) % BUF_SIZ;
return i;
}
return -1;
}
int InstallISR( int PortNum )
{
unsigned char MaskBit;
switch( PortNum )
{
case COM1:
MaskBit = IRQ4MaskBit;
oldCOMhandler = getvect( 0x0c );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0c, COM_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM2:
MaskBit = IRQ3MaskBit;
oldCOMhandler = getvect( 0x0b );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0b, COM_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM3:
MaskBit = IRQ6MaskBit;
oldCOMhandler = getvect( 0x0e );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0e, COM_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM4:
MaskBit = IRQ5MaskBit;
oldCOMhandler = getvect( 0x0d );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0d, COM_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
default:
return -1;
}
return 0;
}
int UninstallISR( int PortNum )
{
switch( PortNum )
{
case COM1:
setvect( 0x0c, oldCOMhandler );
break;
case COM2:
setvect( 0x0b, oldCOMhandler );
break;
case COM3:
setvect( 0x0e, oldCOMhandler );
break;
case COM4:
setvect( 0x0d, oldCOMhandler );
break;
default:
return -1;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -