udoslnk.c

来自「DALLAS 1 Wire 总线 SDK 支持多种高级语言」· C语言 代码 · 共 699 行 · 第 1/2 页

C
699
字号
//
// Returns TRUE for success and FALSE for failure
//
int WriteCOM(int portnum, int outlen, uchar *outbuf)
{
   short cnt=0;

   // remember this as the last port
   LastPrt = portnum;

   // loop to write out each byte an wait until sent
   while (cnt < outlen)
   {

      // check if output buffer empty
      if (inportb(PortState[portnum].com.nam.lsr) & 0x20)
      {
         // make sure interrupts are enabled
         _enable();

         // send out a character
         outportb(PortState[portnum].com.nam.a.tbr,outbuf[cnt++]);
      }
   }

   return outlen;
}


//------------------------------------------------------------------
//  Description:
//     This routines sets up the DCB and performs a SetCommState().
//     SetupCOM assumes OpenComm has previously been called.
//     Returns 0 if unsuccessful and 1 if successful.
//
//  Prt      - number 0 to MAX_PORTNUM-1.  This number is provided to
//                 indicate the symbolic port number.
//  baudrate - the baudrate that should be used in setting up the port.
//
//  return TRUE if the port was setup correctly
//
SMALLINT SetupCOM(int portnum, ulong baudrate)
{
   ushort reload;

   // set dlab to load reload of 8250 in LCR
   outportb(PortState[portnum].com.nam.lcr, 0x80);

   // calculat the reload
   switch (baudrate)
   {
      case 9600:   reload = 12;
         break;
      case 19200:  reload = 6;
         break;
      case 57600:  reload = 2;
         break;
      case 115200: reload = 1;
         break;
      default: reload = 12;
         break;
   };

   // load msb of Reload
   outportb(PortState[portnum].com.nam.b.msb, reload / 256);

   // load lsb of Reload
   outportb(PortState[portnum].com.nam.a.lsb, reload & 0xFF);

   // parity off, stop=1, word=8 in LCR
   outportb(PortState[portnum].com.nam.lcr, 3);
   //?????outportb(PortState[Prt].com.nam.lcr, 0x07); // 2 stop bits for test

   // enable 16550 hokie1

   outportb(PortState[portnum].com.nam.iir,0xC7);

   // disable 16550 fifos
   // commented out because you can do the hardware enable
   // or this option chooses software fifo.
//   outportb(PortState[portnum].com.nam.iir,0x00);

   return TRUE;
}


//-------------------------------------------------------------------
//  Description:
//     flush the rx and tx buffers
//
//  portnum    - number 0 to MAX_PORTNUM-1.  This number is provided to
//                 indicate the symbolic port number.
//
void FlushCOM(int portnum)
{
   // loop to flush the send buffers
   while ((inportb(PortState[portnum].com.nam.lsr) & 0x60) != 0x60)
      ;

   // read any bytes in input buffer
   while (inportb(PortState[LastPrt].com.nam.lsr) & 0x01)
      inportb(PortState[LastPrt].com.nam.a.rbr);

   // clear the interrupt
   inportb(PortState[LastPrt].com.nam.iir);

   // non-specific return from interrupt
   outportb(0x20,0x20);

   _disable();         // disable interrupts

   // reset the buffer counters
   PortState[portnum].inbuf_n   = 0;
   PortState[portnum].inbuf_get = 0;
   PortState[portnum].inbuf_put = 0;

   _enable();         // re-enble interrupts
}


//--------------------------------------------------------------------------
//  ISR for com port receive.
//
void __interrupt __far  com_serial_int4(ushort _es, ushort _ds, ushort _di, ushort _si,
                                   ushort _bp, ushort _sp, ushort _bx, ushort _dx,
                                   ushort _cx, ushort _ax, ushort _ip, ushort _cs,
                                   ushort _flags)
{
   _disable();                    // disable interrupts

   // get uart status
   if (inportb(PortState[LastPrt].com.nam.lsr) & 0x01)
   {
      // get the character
      PortState[LastPrt].inbuf[PortState[LastPrt].inbuf_put++] = inportb(PortState[LastPrt].com.nam.a.rbr);
      // wrap buffer
      PortState[LastPrt].inbuf_put &= INBUF_MASK;
      // count the new character
      PortState[LastPrt].inbuf_n++;
   }

   // clear the interrupt
   inportb(PortState[LastPrt].com.nam.iir);

   // non-specific return from interrupt
   outportb(0x20,0x20);

   _enable();                     // re-enable interrupts
}

//--------------------------------------------------------------------------
//  ISR for com port receive.
//
void __interrupt __far  com_serial_int3(ushort _es, ushort _ds, ushort _di, ushort _si,
                                   ushort _bp, ushort _sp, ushort _bx, ushort _dx,
                                   ushort _cx, ushort _ax, ushort _ip, ushort _cs,
                                   ushort _flags)
{
   _disable();                    // disable interrupts

   // get uart status
   if (inportb(PortState[LastPrt].com.nam.lsr) & 0x01)
   {
      // get the character
      PortState[LastPrt].inbuf[PortState[LastPrt].inbuf_put++] = inportb(PortState[LastPrt].com.nam.a.rbr);
      // wrap buffer
      PortState[LastPrt].inbuf_put &= INBUF_MASK;
      // count the new character
      PortState[LastPrt].inbuf_n++;
   }

   // clear the interrupt
   inportb(PortState[LastPrt].com.nam.iir);

   // non-specific return from interrupt
   outportb(0x20,0x20);

   _enable();                     // re-enable interrupts
}

//-------------------------------------------------------------------
//  Description:
//     Send a break on the com port for "len" msec
//
//  portnum    - number 0 to MAX_PORTNUM-1.  This number is provided to
//                 indicate the symbolic port number.
//
void BreakCOM(int portnum)
{
   // start the break
   outportb(PortState[portnum].com.nam.lcr, 0x43);

   Sleep(2);

   // clear the break
   outportb(PortState[portnum].com.nam.lcr, 0x03);
}

//--------------------------------------------------------------------------
// Set the baud rate on the com port.
//
// 'portnum'   - number 0 to MAX_PORTNUM-1.  This number was provided to
//               OpenCOM to indicate the port number.
// 'new_baud'  - new baud rate defined as
//                PARMSET_9600     0x00
//                PARMSET_19200    0x02
//                PARMSET_57600    0x04
//                PARMSET_115200   0x06
//
void SetBaudCOM(int portnum, uchar new_baud)
{
   ushort reload;

   // set dlab to load reload of 8250 in LCR
   outportb(PortState[portnum].com.nam.lcr, 0x80);

   // calculate the reload
   // does not support PARMSET_57600
   // and PARMSET_115200
   switch(new_baud)
   {
      case PARMSET_9600:   reload = 12;
         break;
      case PARMSET_19200:  reload = 6;
         break;
      case PARMSET_57600:  reload = 2;
         break;
      case PARMSET_115200: reload = 1;
         break;
      default: reload = 12;
         break;
   };

   // load msb of Reload
   outportb(PortState[portnum].com.nam.b.msb, reload / 256);

   // load lsb of Reload
   outportb(PortState[portnum].com.nam.a.lsb, reload & 0xFF);

   // parity off, stop=1, word=8 in LCR
   outportb(PortState[portnum].com.nam.lcr, 3);
}

//--------------------------------------------------------------------------
//  Description:
//     Drop and then raise power (DTR,RTS) on the com port
//
//  len > 0 - drop power for len ms
//      = 0 - reset power drop
//      < 0 - drop power for an infinite time
//
void PowerCOM(int portnum, short len)
{
   // drop power?
   if (len != 0)
      // DTR/RTS off
      outportb(PortState[portnum].com.nam.mcr,0);

   if (len > 0)
      // sleep
      Sleep(len);

   // is this not an infinite power drop?
   if (len >= 0)
      // DTR/RTS on
      outportb(PortState[portnum].com.nam.mcr,0x0B);
}


//--------------------------------------------------------------------------
// Mark time stamp for later comparison
//
void MarkTime(void)
{
   // get the rought timestamp
   BigTimeStamp = msGettick();

   // get an accurate timestamp
   outportb(0x43,0);                // freeze value in timer
   TimeStamp = inportb(0x40) & 0xFF;        // read value in timer
   TimeStamp += (inportb(0x40) << 8) & 0xFF00;
}


//--------------------------------------------------------------------------
// Check if timelimit number of ms have elapse from the call to MarkTime
//
// timelimit  - the time limit for the elapsed time
//
// Return TRUE if the time has elapse else FALSE.
//
SMALLINT ElapsedTime(long timelimit)
{
   ulong C,N;

   // check if using rought or accurate timestamp
   if (timelimit > 5)
   {
      // check if time elapsed
      return ((BigTimeStamp + timelimit) < (ulong) msGettick());
   }
   else
   {
      outportb(0x43,0);                      // freese value in timer
      N = inportb(0x40) & 0xFF;              // read value in timer
      N += (inportb(0x40) << 8) & 0xFF00;

      if (TimeStamp < N)
         C = 65536 - (N - TimeStamp);
      else
         C = TimeStamp - N;

      // check if time elapsed
      return ((timelimit * MilliSec) < C);
   }
}


//--------------------------------------------------------------------------
// Delays for the given amout of time
//
// len  - the number of milliseconds to sleep
//
void msDelay(int len)
{
   Sleep(len);
}

//--------------------------------------------------------------------------
//  Wait duration in ms
//
void Sleep(long len)
{
   // get a time stamp
   MarkTime();
   // wait for len ms
   while (!ElapsedTime(len));
}

//--------------------------------------------------------------------------
// Get the current millisecond tick count.  Does not have to represent
// an actual time, it just needs to be an incrementing timer.
//
long msGettick(void)
{
   ulong *sysclk = (ulong *) 0x0040006c;

   return *sysclk * 55;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?