本驱动程序是继承自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后,点击按钮,每一秒钟会产生一个随机整数数组和一个随机浮点数组: