⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs232x3.cpp

📁 英创386模块的RS232控制协议和函数,还有例程
💻 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 + -