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");
}
}
- 最后编辑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的写操作。