本驱动程序是继承自asynPortDriver,分别重写了用于读取32位整型数组和32位浮点型数组的 readInt32Array和readFloat32Array。
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);
- }
- # 用于读取整型数组
- 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")
- }
- ...
- # 启动驱动程序
- 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")
- ...
启动IOC后,点击按钮,每一秒钟会产生一个随机整数数组和一个随机浮点数组: