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

📄 driver.c

📁 研华工控卡PCL836的一些例程序
💻 C
📖 第 1 页 / 共 3 页
字号:
//--------------------------------------------------------------------------d
//
//     PCL-836 Driver
//
//--------------------------------------------------------------------------
#include <dos.h>
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include <stdlib.h>
#include "..\driver.h"

// Global variables
USHORT usBaseAddr[10] = {0,0,0,0,0,0,0,0,0,0};  // save base address location
USHORT usPreState[10][2];     // digital output previous state
USHORT usFirstCount[10][6];   // first read counter value for event counter
ULONG  ulOverflow[10][6];     // overflow flag for event counter
USHORT usPreCount[10][6];     // previous count state for event counter
USHORT usFoutCtrReg[10];      // frequency output control register
USHORT usModeCtrReg[10][6];   // control clock input mode control register

// Function prototypes
ULONG DoSection(USHORT ,USHORT, USHORT ,USHORT);
ULONG DiSection(USHORT, USHORT, USHORT *);
ULONG GetDoStatus(USHORT, USHORT, USHORT *);

//-------------------------------------------------------------------
// Function    : DeviceOpen
// PURPOSE     : Retrieves the parameters pertaining to the device
//               operation from Global Variable , and store it for
//               quick reference. This function must be called
//               before any other functions
// Parameters  : DeviceNumber (IN), BaseAddr(OUT)
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
//------------------------------------------------------------------
ULONG DeviceOpen(USHORT DeviceNumber, USHORT BaseAddr)
{
    USHORT usIndex;
    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (BaseAddr == NULL)
        return ((ULONG) InvalidBaseAddr);

    // Is BaseAddr in use ?
    if (usBaseAddr[DeviceNumber] != NULL)
        return ((ULONG) DeviceIsBusy); // If you have this error, you
                                       // can call DeviceClose to reset it.

    // everything is OK then initiate some Global variables by DeviceNumber
    usPreState[DeviceNumber][0] = 0;   // for digital output port 0
    usPreState[DeviceNumber][1] = 0;   // for digital output port 1

    for (usIndex=0 ; usIndex < MaxCounterNumber ; usIndex++)
    {
        // use by event counter
        usFirstCount[DeviceNumber][usIndex] = 0;
        ulOverflow[DeviceNumber][usIndex]   = 0;
        usPreCount[DeviceNumber][usIndex]   = 0;
        usFoutCtrReg[DeviceNumber]          = 0;
        usModeCtrReg[DeviceNumber][usIndex] = 0;
    }

    // set Global variable by DeviceNumber
    usBaseAddr[DeviceNumber] = BaseAddr;

    // return success
    return ((ULONG) NULL);
}

//------------------------------------------------------------------
// Function    : DeviceClose
// PURPOSE     : Resets Device by DeviceNumber.
// Parameters  : DeviceNumber (IN)
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
// CounterReset
//------------------------------------------------------------------
ULONG DeviceClose(USHORT DeviceNumber)
{
    USHORT usIndex;
    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (usBaseAddr[DeviceNumber] == NULL)
        return ((ULONG) LostBaseAddr);

    // Reset counters by DeviceNumber
    for (usIndex=0 ; usIndex < MaxCounterNumber ; usIndex++)
        CounterReset(DeviceNumber, usIndex);

    // Reset Golbal variable
    usBaseAddr[DeviceNumber] = 0;

    return ((ULONG) NULL);
}

//------------------------------------------------------------------
// Function    : CounterConfig
// PURPOSE     : This function config the counter mode of specified counter
//               (default is positive edge without filter)
// Parameters  : DeviceNumber(IN), counter(IN), CounterEdge(IN)
//               MaxInFreq(IN)
//               312K is high limitation of MaxInFreq.
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
//------------------------------------------------------------------
extern ULONG CounterConfig(USHORT DeviceNumber, USHORT counter,
                           USHORT CounterEdge, FLOAT MaxInFreq)
{
    USHORT usCount;
    USHORT usCtrByte, usLowByte, usHighByte;
    ULONG  retCode;
    FLOAT  fFout;

    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (usBaseAddr[DeviceNumber] == NULL)
        return ((ULONG) LostBaseAddr);

    // check input param correct ?
    if (counter > MaxCounterNumber)
        return((ULONG) InvalidCounterChannel);

    // check MaxInFreq is out of range ?
    if (MaxInFreq > (FLOAT)312000.0)
        return((ULONG) InvalidFreqRange);

    usModeCtrReg[DeviceNumber][counter] = 0x00;

    if (CounterEdge == 1)   // this mode is negative edge
        usModeCtrReg[DeviceNumber][counter] = 0x04;

    if (MaxInFreq != (FLOAT)0.0)
    {
       // set control with digital filter
       usModeCtrReg[DeviceNumber][counter] |= 0x01;

       // set filter wide
       fFout = MaxInFreq*8*2;

       retCode = FreqOutStart(DeviceNumber, counter, fFout);
       if (retCode != 0L)
          return(retCode);
    }

    return ((ULONG) 0);
}

//------------------------------------------------------------------
// Function    : CounterPulseStart
// PURPOSE     : Configures the specified counter for pulse
//               output and starts the counter.
// Parameters  : DeviceNumber(IN), counter(IN),
//               period(IN)  in ms
//               UpCycle(IN) in ms
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
//------------------------------------------------------------------
ULONG CounterPulseStart(USHORT DeviceNumber,USHORT counter,
    FLOAT period, FLOAT UpCycle)
{
    USHORT usBase;
    DWORD  divisor;
    USHORT usCtrByte, usLowByte, usHighByte;
    FLOAT  fUserHz;
    FLOAT fFout;
    USHORT usCount0, usCount3;
    ULONG retCode;

    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (usBaseAddr[DeviceNumber] == NULL)
        return ((ULONG) LostBaseAddr);

    // check input param correct ?
    if (counter > MaxPWMNumber)
        return((ULONG) InvalidCounterChannel);

    // check Period is out of range ?
    if ((period  > (FLOAT)10000)   || (UpCycle > (FLOAT)10000) ||
        (period == 0)              || (UpCycle == 0)            ||
        (UpCycle >= period))
        return((ULONG) InvalidInputParam);

    // get base address
    usBase = usBaseAddr[DeviceNumber];

    /* configure counter for external clocking */
    outportb(usBase+counter+18, 0x03);

    // configures counter 0 and counter 3 (for PWM channel 0)
    // configures counter 1 and counter 4 (for PWM channel 1)
    // configures counter 2 and counter 5 (for PWM channel 2)

    fUserHz = (FLOAT)((FLOAT)1.0/period)*1000;

    if (fUserHz > (FLOAT)2500000.0)  // check out of 2.5Mhz
        return((ULONG) InvalidFreqRange);

    // FOUT select
    if (fUserHz >= (FLOAT)F100HZ)
        fFout = (FLOAT)5000000.0;
    else if (fUserHz >= (FLOAT)F10HZ)
        fFout = (FLOAT)500000.0;
    else if (fUserHz >= (FLOAT)F1HZ)
        fFout = (FLOAT)50000.0;
    else if (fUserHz >= (FLOAT)F0_1HZ)
        fFout = (FLOAT)5000.0;

    usCount3 = (USHORT)(fFout/fUserHz);

   // FOUT enable
   retCode = FreqOutStart(DeviceNumber, counter, fFout);
   if (retCode != 0L)
        return(retCode);

   // set counter 3 (or 4, 5)
   usCtrByte = (counter%3) << 6;
   usCtrByte |= 0x34;
   usLowByte = (USHORT)(usCount3 & 0x000000FF);
   usHighByte = (USHORT)((usCount3 &  0x0000FF00) >> 8);

   outportb(usBase+counter+21, 0x02);        /* set internal clock */
   outportb(usBase+15, usCtrByte);
   outportb(usBase+counter+12, usLowByte);       /* write low byte */
   outportb(usBase+counter+12, usHighByte);      /* write high byte */

   // set counter 0 (or 1, 2)
   usCount0 = usCount3*((FLOAT)(period-UpCycle)/period);

   usCtrByte = (counter%3) << 6;
   usCtrByte |= 0x3a;
   usLowByte = (USHORT)(usCount0 & 0x000000FF);
   usHighByte = (USHORT)((usCount0 &  0x0000FF00) >> 8);

   outportb(usBase+counter+18, 0x03);        /* set internal clock */
   outportb(usBase+11, usCtrByte);
   outportb(usBase+counter+8, usLowByte);       /* write low byte */
   outportb(usBase+counter+8, usHighByte);      /* write high byte */


    return 0L;
}

//------------------------------------------------------------------
// Function    : FreqOutStart
// PURPOSE     : Configures the specified counter for frequency output
//               and starts the counter. (internal base clock is 10MHZ)
// Parameters  : DeviceNumber(IN), counter(IN), fout(IN)
//               fout range is from 153HZ to 5MHZ
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
//------------------------------------------------------------------
ULONG FreqOutStart(USHORT DeviceNumber, USHORT counter, FLOAT fout)
{
    USHORT usBase, usCount;
    USHORT usCtrByte, usLowByte, usHighByte;
    FLOAT  fBalance;

    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (usBaseAddr[DeviceNumber] == NULL)
        return ((ULONG) LostBaseAddr);

    // check input param correct ?
    if (counter > MaxCounterNumber)
        return((ULONG) InvalidCounterChannel);

    // get base address
    usBase = usBaseAddr[DeviceNumber];

    // check input fout is out of range ?
    if (( fout > (float)5000000.0) ||  ( fout < (float)153.0))
        return((ULONG) InvalidFreqRange);

    fBalance = (float)10000000.0f / fout;
    usCount = (USHORT) fBalance;

    if (((FLOAT)fBalance*10 - (FLOAT)usCount*10) > 4)
        usCount ++;

    usLowByte = (USHORT)(usCount & 0x000000FF);
    usHighByte = (USHORT)((usCount &  0x0000FF00) >> 8);

    usCtrByte = (counter%3) << 6;
    usCtrByte |= 0x36;

    if (counter < 3)
    {
       outportb(usBase+3, usCtrByte);     // Mode 3
       outportb(usBase+counter, usLowByte);       /* write low byte */
       outportb(usBase+counter, usHighByte);      /* write high byte */
    }
    else
    {
       outportb(usBase+7, usCtrByte);     // Mode 3
       outportb(usBase+(counter%3)+4, usLowByte);  /* write low byte */
       outportb(usBase+(counter%3)+4, usHighByte); /* write high byte */
    }

    // enable frequency output control reg.
    usCtrByte = 0x01;
    usCtrByte = usCtrByte << counter;
    usFoutCtrReg[DeviceNumber] |= usCtrByte;

    outportb(usBase+24, usFoutCtrReg[DeviceNumber]);

    return 0L;
}

//------------------------------------------------------------------
// Function    : FreqOutStop
// PURPOSE     : This function stop the Frequency out of specified counter
// Parameters  : DeviceNumber(IN), counter(IN)
// Return      : NULL (success)
//				 ErrorCode (failure)
// Call/Called procedure cross reference :
// Call        Called		     Explanation
//------------------------------------------------------------------
ULONG FreqOutReset(USHORT DeviceNumber, USHORT counter)
{
    USHORT usBase, usCtrByte;

    // Is DeviceNumber out of range ?
    if (DeviceNumber > MaxBoardNumber)
        return ((ULONG) InvalidDeviceNumber);

    // Is BaseAddr valid ?
    if (usBaseAddr[DeviceNumber] == NULL)

⌨️ 快捷键说明

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