Qt5中使用EPICS通道访问读写EPICS PV

1、用Qt Creator创建一个Qt Widget项目ChannelAccess,并且在其生成的ChannelAccess.pro中添加以下行:

bash 复制代码
#
# Project created by QtCreator 2023-06-27T02:06:24
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ChannelAccess
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    pvchannels.cpp

HEADERS  += mainwindow.h \
    pvchannels.h

FORMS    += mainwindow.ui

# 以下是添加了EPICS base通道访问库的头文件的路径以及库文件的位置
INCLUDEPATH += /usr/local/EPICS/base/include
INCLUDEPATH += /usr/local/EPICS/base/include/os/Linux
INCLUDEPATH += /usr/local/EPICS/base/include/compiler/gcc
LIBS += /usr/local/EPICS/base/lib/linux-x86_64/libca.so.4.13.5
LIBS += /usr/local/EPICS/base/lib/linux-x86_64/libCom.so.3.17.6

2、mainwindow.ui的设计如下:

3、添加一个名为pvchannels的类,其在Headers和Sources下分别生成了一个名为pvchannels.h和pvchannels.cpp文件:

编辑以上两个文件:

1)pvchannels.h:

cpp 复制代码
#ifndef PVCHANNELS_H
#define PVCHANNELS_H
#include "cadef.h"
#include <QString>
#include <QDebug>

class pvchannels
{
public:
    pvchannels(const char * pvname);
    ~pvchannels();

    void pv_init();

    void Display();
    double getValue();
    void updateValue();
    void writeValue(double value);

private:
    QString     pvname_;
    chid        mychid_;
    double      data_;
    unsigned    elementcount_;
    double *    pdoubles_;
};

#endif // PVCHANNELS_H

2)pvchannels.cpp:

cpp 复制代码
#include "pvchannels.h"

pvchannels::pvchannels(const char *pvname)
{
    this->pvname_ = pvname;
    this->pdoubles_ = NULL;
}

pvchannels::~pvchannels()
{
    if (this->pdoubles_ != NULL){
        free(this->pdoubles_);
    }
    this->pdoubles_ = NULL;

    ca_clear_channel(this->mychid_);
//    ca_context_destroy();
}

void pvchannels::pv_init()
{
    SEVCHK(ca_context_create(ca_disable_preemptive_callback),"ca_context_create");
    SEVCHK(ca_create_channel(this->pvname_.toLatin1().data(), NULL, NULL, 10 , &this->mychid_), "ca_create_channel failure");
    SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
    SEVCHK(ca_get(DBR_DOUBLE, this->mychid_, (void *)&data_), "ca_get failure");
    SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");

    this->elementcount_ = ca_element_count(mychid_);

    if (this->elementcount_ > 1){
        this->pdoubles_ = (double *) malloc(sizeof(double) * this->elementcount_);

        SEVCHK(ca_array_get(DBR_DOUBLE, this->elementcount_, this->mychid_, (void *)pdoubles_), "ca_array_get failed");
        SEVCHK(ca_pend_io(5.0), "ca_pend_io failed");
    }
}

void pvchannels::Display()
{
    qDebug() << "Data:" << this->data_;
    qDebug() << "Count:" << this->elementcount_;
}

void pvchannels::updateValue()
{
    if (this->elementcount_ > 1){
        SEVCHK(ca_array_get(DBR_DOUBLE, this->elementcount_, this->mychid_, (void *)pdoubles_), "ca_array_get failed");
    }
    else{
         SEVCHK(ca_get(DBR_DOUBLE, this->mychid_, (void *)&data_), "ca_get failure");
    }
    SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
}

void pvchannels::writeValue(double value)
{
    this->data_ = value;
    SEVCHK(ca_put(DBR_DOUBLE, this->mychid_, (void *)&data_), "ca_put failure");
    SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
}

double pvchannels::getValue()
{
    return data_;
}

3) 编辑mainwindow..h头文件:

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <vector>
#include <QMainWindow>
#include <QLineEdit>
#include <QLabel>
#include "pvchannels.h"

using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private slots:
    void on_BtnGetPVs_clicked();

    void on_MonitorButton_clicked();

    void on_BtnUpdatePVs_clicked();

    void on_BtnWritePVs_clicked();

    void on_BtnDisconnectPVs_clicked();

private:
    Ui::MainWindow *ui;
    vector<QLineEdit *> vec;
    vector<QLabel *>veclabel;
    vector<pvchannels *> vecpvs;
    vector<QLineEdit *> vecwrite;
    pvchannels * pv_monitor;
    bool isConnected;
};

#endif // MAINWINDOW_H

3) 编辑mainwindow..cpp头文件:

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <vector>
#include "pvchannels.h"
#include <QMessageBox>
#include <QDoubleValidator>
#include <QDebug>
//#include <QtChart>

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->leWritePV1->setValidator(new QDoubleValidator());
    ui->leWritePV2->setValidator(new QDoubleValidator());
    ui->leWritePV3->setValidator(new QDoubleValidator());
    ui->leWritePV4->setValidator(new QDoubleValidator());
    vecwrite.push_back(ui->leWritePV1);
    vecwrite.push_back(ui->leWritePV2);
    vecwrite.push_back(ui->leWritePV3);
    vecwrite.push_back(ui->leWritePV4);
    vec.push_back(ui->lineEdit_PV1);
    vec.push_back(ui->lineEdit_PV2);
    vec.push_back(ui->lineEdit_PV3);
    vec.push_back(ui->lineEdit_PV4);
    veclabel.push_back(ui->label_v1);
    veclabel.push_back(ui->label_v2);
    veclabel.push_back(ui->label_v3);
    veclabel.push_back(ui->label_v4);

    pv_monitor = NULL;
    isConnected = false;

}

MainWindow::~MainWindow()
{
    if (pv_monitor != NULL){
        delete pv_monitor;
        pv_monitor = NULL;
    }

    vector<pvchannels *>::iterator itpvs = vecpvs.begin();

    for (; itpvs != vecpvs.end(); ++itpvs){
        pvchannels * ppv = * itpvs;
        delete ppv;
    }
    delete ui;
}



void MainWindow::on_BtnGetPVs_clicked()
{
    vector<QLineEdit *>::iterator it;
    vector<QLabel *>::iterator itlabel;
    vector<QLineEdit *>::iterator itwrite;

    vecpvs.clear();
    if (isConnected ==  false){
        isConnected = true;

        for (it = vec.begin(), itlabel = veclabel.begin(), itwrite = vecwrite.begin();  \
             it != vec.end()&& itlabel != veclabel.end() && itwrite != vecwrite.end(); \
             ++it, ++itlabel, ++itwrite){
            QLineEdit * pedit = * it;

            QString pvname = pedit->text();

            qDebug() << "pvname: " << pvname;
            pvchannels * ppv = new pvchannels(pvname.toUtf8().data());
            ppv->pv_init();

            (*itlabel)->setText(QString::number(ppv->getValue()));
            (*itwrite)->setText(QString::number(ppv->getValue()));
            vecpvs.push_back(ppv);
        }

        ui->BtnUpdatePVs->setEnabled(true);
        ui->BtnWritePVs->setEnabled(true);
        ui->BtnGetPVs->setEnabled(false);
        ui->BtnDisconnectPVs->setEnabled(true);
   }


}

void MainWindow::on_MonitorButton_clicked()
{
    QString pvname = ui->lineEditMonitor->text();
    if (pv_monitor == NULL){
        pv_monitor = new pvchannels(pvname.toLatin1().data());
        pv_monitor->pv_init();
    }
    else{
        pv_monitor->updateValue();
    }

    QMessageBox::information(this, "PV Monitor", QString::number(pv_monitor->getValue()));
}

void MainWindow::on_BtnUpdatePVs_clicked()
{
    vector<pvchannels *>::iterator it;
    vector<QLabel *>::iterator itlabel;
    vector<QLineEdit *>::iterator itwrite;


    for (it = vecpvs.begin(), itlabel = veclabel.begin() , itwrite = vecwrite.begin();  \
         it != vecpvs.end() && itlabel != veclabel.end() && itwrite != vecwrite.end(); \
         ++it, ++itlabel, ++itwrite){
        pvchannels * ppv = *(it);
        ppv->updateValue();
        (* itlabel)->setText(QString::number(ppv->getValue()));
        (* itwrite)->setText(QString::number(ppv->getValue()));
    }
}

void MainWindow::on_BtnWritePVs_clicked()
{
    vector<pvchannels *>::iterator itpvs;
    vector<QLineEdit *>::iterator  it;

    for (it = vecwrite.begin(), itpvs = vecpvs.begin(); it != vecwrite.end() && itpvs != vecpvs.end(); ++it, ++itpvs){
        QString str = (*it)->text();
        double value = str.toDouble();
//        qDebug() << value;
        (* itpvs)->writeValue(value);

    }

    this->on_BtnUpdatePVs_clicked();
}

void MainWindow::on_BtnDisconnectPVs_clicked()
{
    if (isConnected == true){
        isConnected = false;

        ui->BtnDisconnectPVs->setEnabled(false);
        ui->BtnGetPVs->setEnabled(true);
        ui->BtnUpdatePVs->setEnabled(false);
        ui->BtnWritePVs->setEnabled(false);

        vector<pvchannels *>::iterator itpvs = vecpvs.begin();

        for (; itpvs != vecpvs.end(); ++itpvs){
            pvchannels * ppv = * itpvs;
            delete ppv;
        }

        QMessageBox::information(this , "Disconnect PV", "Diconntect PVs");
    }
}
  1. 最后编辑main.cpp源文件:
cpp 复制代码
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QLoggingCategory>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
     QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
    MainWindow w;
    w.show();


    return a.exec();
}

6)选择菜单项Build->Build Project "ChannelAccess",编译项目。等编译结束,选择Run,运行这个项目。

在PV列中输入想要连接的EPICS PV,点击Connnect PVs,就可以连接指定的PV,并且回读PV的当前值。

如果想要读取当前的PV值,点击Update PVs,如果想要更改PV,则在右侧Write Value列中写入想要更新的值,然后点击WritePVs,完成PV的写操作。

相关推荐
杭电码农-NEO2 分钟前
【lua语言基础(四)】IO模型以及补充知识
开发语言·junit·lua
是十一月末9 分钟前
Python语法之正则表达式详解以及re模块中的常用函数
开发语言·python·正则表达式
一只大侠10 分钟前
计算S=1!+2!+3!+…+N!的值:JAVA
java·开发语言
一只大侠13 分钟前
输入一串字符,以“?”结束。统计其中字母个数,数字个数,其它符号个数。:JAVA
java·开发语言·算法
Oneforlove_twoforjob13 分钟前
【Java基础面试题011】什么是Java中的自动装箱和拆箱?
java·开发语言
橘子真甜~20 分钟前
Linux操作系统3-文件与IO操作1(从C语言IO操作到系统调用)
linux·运维·服务器·c语言·io·文件操作·文件fd
优雅的落幕30 分钟前
多线程---线程安全(synchronized)
java·开发语言·jvm
A charmer31 分钟前
Linux 权限管理:用户分类、权限解读与常见问题剖析
linux·运维·服务器
小黄编程快乐屋32 分钟前
前端小练习——大雪纷飞(JS没有上限!!!)
开发语言·前端·javascript
羊村懒哥35 分钟前
linux-安全-iptables防火墙基础笔记
linux·网络·安全