EPICS asynPortDriver中数组用法示例

本驱动程序是继承自asynPortDriver,分别重写了用于读取32位整型数组和32位浮点型数组的 readInt32Array和readFloat32Array。

1)源代码如下:

arraydriver.h:

#include "epicsEvent.h"
#include "asynPortDriver.h"

#define P_Int32ArrayValueString         "INT32_ARRAY_VALUE"     /* asynInt32Array */
#define P_Float32ArrayValueString       "FLOAT32_ARRAY_VALUE"   /* asynFloat32Array */
#define P_RunThreadString               "Run_Thread"            /* asynInt32Digital */

class ArrayDriver:public asynPortDriver{
public:
        ArrayDriver(const char * portName, size_t intsize, size_t floatsize);
        virtual asynStatus readInt32Array(asynUser *pasynUser, epicsInt32 * value,size_t nElements,size_t *nIn);
        virtual asynStatus readFloat32Array (asynUser *pasynUser, epicsFloat32 *value, size_t nElements, size_t *nIn);
        virtual asynStatus writeUInt32Digital (asynUser *pasynUser, epicsUInt32 value, epicsUInt32 mask);
        void    startThread(void);

protected:
        int P_Int32ArrayValue;
        int P_Float32ArrayValue;
        int P_RunThread;

private:
        size_t          intsize_;
        epicsInt32      * pInt32_;
        size_t          floatsize_;
        float           * pFloat32_;
        epicsEventId    startevent_;
        epicsUInt32     run_;
};

arraydriver.cpp:

#include 
#include 
#include 
#include 

#include "epicsEvent.h"
#include "asynPortDriver.h"
#include "arraydriver.h"
#include "epicsTypes.h"
#include "iocsh.h"
#include "epicsExport.h"

static const char * driverName = "ArrayDriver";

static void startThreadC(void * pvt);

ArrayDriver::ArrayDriver(const char * portName, size_t intsize, size_t floatsize)
        :asynPortDriver(portName,
                    1,
                    asynInt32ArrayMask | asynFloat32ArrayMask | asynUInt32DigitalMask | asynDrvUserMask,
                    asynInt32ArrayMask | asynFloat32ArrayMask | asynUInt32DigitalMask,
                    0,
                    1,
                    0,0), intsize_(intsize), floatsize_(floatsize),run_(0)
{
        srand(time(NULL));

        pInt32_ = (epicsInt32 *)malloc(sizeof(epicsInt32) * intsize_);
        pFloat32_ = (float *)malloc(sizeof(float) * floatsize);

        createParam(P_Int32ArrayValueString,             asynParamInt32Array,                   &P_Int32ArrayValue);
        createParam(P_Float32ArrayValueString,           asynParamFloat32Array,                 &P_Float32ArrayValue);
        createParam(P_RunThreadString,                   asynParamUInt32Digital,                &P_RunThread);

        for (size_t i = 0; i < intsize_; i++){
                pInt32_[i] = i;
        }

        for (size_t i = 0; i < floatsize_; i++){
                pFloat32_[i] = i * 0.2;
        }

        setUIntDigitalParam(P_RunThread,        run_,   0x1, 0x1);

        startevent_ = epicsEventMustCreate(epicsEventEmpty);

        int status = (epicsThreadCreate("startThreadC",  epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium),
                    (EPICSTHREADFUNC)::startThreadC, (void *)this) == NULL);

        if (status ){
                printf("%s: %s  epicsThreadCreate failed\n", "ArraryDriver", "startThreadC");
                return;
        }

}

asynStatus ArrayDriver::readInt32Array(asynUser *pasynUser, epicsInt32 * value,size_t nElements,size_t *nIn)
{
        int function = pasynUser->reason;
        size_t copysize;

        if (function == P_Int32ArrayValue){
                if (intsize_ >= nElements)
                        copysize = nElements;
                else
                        copysize = intsize_;

                *nIn = copysize;

                memcpy(value, pInt32_, sizeof(epicsInt32) * copysize);
        }

        return asynSuccess;
}


asynStatus ArrayDriver::readFloat32Array (asynUser *pasynUser, epicsFloat32 *value, size_t nElements, size_t *nIn)
{
        int function = pasynUser->reason;
        size_t copysize;

        if (function == P_Float32ArrayValue){
                if (floatsize_ >= nElements)
                        copysize = nElements;
                else
                        copysize = floatsize_;

                *nIn = copysize;

                memcpy(value, pFloat32_, sizeof(float) * copysize);
        }
        return asynSuccess;
}

asynStatus ArrayDriver::writeUInt32Digital (asynUser *pasynUser, epicsUInt32 value, epicsUInt32 mask)
{
        int function = pasynUser->reason;
        epicsUInt32 run;

        if (function == P_RunThread){
                run = value & mask;
                setUIntDigitalParam(P_RunThread,        run,   0x1, 0x1);

                if (run){
                        epicsEventSignal(startevent_);
                }

                callParamCallbacks();
                return asynSuccess;
        }
        else{
                return asynPortDriver::writeUInt32Digital(pasynUser, value, mask);
        }

}

//用单独一个线程运行这个方法,为数组产生随机数,用于测试
void ArrayDriver::startThread()
{
        epicsUInt32 run;
        lock();

        while(1){
                unlock();
                epicsEventMustWait(startevent_);
                lock();
                getUIntDigitalParam(P_RunThread, &run, 0x01);
                while (run){
                        for (size_t i = 0; i < intsize_; i++){
                                pInt32_[i] = rand() % 100 + 1;
                        }
                        for (size_t i = 0; i < floatsize_; i++){
                                pFloat32_[i] = (rand() % 100 + 1) * 0.01;
                        }
                        unlock();
                        epicsThreadSleep(1.0);
                        lock();
                        getUIntDigitalParam(P_RunThread, &run, 0x01);
                }
        }
}

static void startThreadC(void * pvt)
{
        ArrayDriver * parrayDriver = (ArrayDriver *)pvt;

        parrayDriver->startThread();
}

extern "C"{
int ArrayDriverConfigure(const char * portName, size_t intsize, size_t floatsize)
{
        new ArrayDriver(portName, intsize,floatsize);
        return asynSuccess;
}

/* EPICS iocsh shell command */
static const iocshArg initArg0 = {"portName", iocshArgString};
static const iocshArg initArg1 = {"intsize", iocshArgInt};
static const iocshArg initArg2 = {"floatsize", iocshArgInt};
static const iocshArg * const initArgs[] = {&initArg0, &initArg1, &initArg2};
static iocshFuncDef initFuncDef = {"ArrayDriverConfigure", 3, initArgs};

static void initCallFunc(const iocshArgBuf * args)
{
    ArrayDriverConfigure(args[0].sval, args[1].ival, args[2].ival);
}

void ArrayDriverRegister(void)
{
    iocshRegister(&initFuncDef, initCallFunc);
}

2) 数据库实例文件arrays.db:

# 用于读取整型数组
record(waveform, "$(P)wfInt32")
{
        field(NELM,"$(NUMS1)")
        field(FTVL, "LONG")
        field(SCAN, "$(SCAN)")
        field(DTYP, "asynInt32ArrayIn")
        field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))INT32_ARRAY_VALUE")
}

# 用于读取浮点数数组
record(waveform, "$(P)wfFloat32")
{
        field(NELM, "$(NUMS2)")
        field(FTVL, "FLOAT")
        field(SCAN, "$(SCAN)")
        field(DTYP, "asynFloat32ArrayIn")
        field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))FLOAT32_ARRAY_VALUE")
}

# 控制随机数线程的运行
record(bo, "$(P)StartThread")
{
   field(PINI, "$(PINI)")
   field(DTYP, "asynUInt32Digital")
   field(OUT,  "@asynMask($(PORT),$(ADDR),0x1, $(TIMEOUT))RUN_THREAD")
   field(ZNAM, "Stop")
   field(ONAM, "Start")
}

3) 启动脚本:

...
# 启动驱动程序
ArrayDriverConfigure("MYPORT", 10, 5)

## 装载记录实例
dbLoadRecords("db/arrays.db","P=TEST:,PORT=MYPORT, ADDR=0, TIMEOUT=1.0, SCAN=I/O Intr, NUMS1=10, NUMS2=5,PINI=NO")
...

4)测试界面:

EPICS asynPortDriver中数组用法示例_第1张图片

5) 进行测试:

启动IOC后,点击按钮,每一秒钟会产生一个随机整数数组和一个随机浮点数组:

EPICS asynPortDriver中数组用法示例_第2张图片

你可能感兴趣的:(EPICS教程,Linux,C,EPICS,C语言)