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

📄 rs485.cpp

📁 在DOS环境下
💻 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 + -