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的写操作。

相关推荐
小钻风336617 小时前
Spring Boot 文件上传详解:深入理解 MultipartFile 的使用与原理
java·开发语言
张小姐的猫18 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
qq_4523962318 小时前
第二篇:《Go 开发环境搭建:SDK、IDE、Module 与 Hello World》
开发语言·ide·golang
栩栩云生19 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
天青色等烟雨..19 小时前
全流程ArcGISPro空间分析、三维建模、可视化及Python融合应用技术
开发语言·python
丰锋ff19 小时前
1.2 Qt常用基础类型
开发语言·qt
冰暮流星20 小时前
javascript之String方法介绍
开发语言·javascript·ecmascript
imc.1120 小时前
linux基础IO
linux·运维·服务器
nianniannnn20 小时前
Qt QMessageBox知识点
开发语言·数据库·qt
故乡de云20 小时前
AWS 添加付款方式失败排查清单:卡片、银行风控与账号状态逐项定位
开发语言·php