Kithara RTS在QT中的使用

一、将Kithara库添加到QT

1、将Kithara安装目录D:\ProgramFiles\Kithara\RealTime Suite Demo 10\dev下的以上三个文件复制到新建的工程目录下

2 将以上的.h .cpp文件添加到工程中 此时 编译会报错 所以执行一下 qmake

3 在mainwindow.h里添加文件包含 #include<KrtsDemo.h>

4 此时编译会报错E:\QtProject\KitharaProj\kitharastudy\KRTStest\KRTStest\KrtsDemo.h:135: error:conflicting declaration ‘typedef long long unsigned int ulong’

typedef unsigned __int64 ulong;

因此要把 ulong这个类型的定义替换掉

文件krtsdemo.h line 135 把ulong的typedefine替换成其他名字即可

二、Kithara RTS进程与Qt应用程序间通信(共享内存)
本文主要描述如下通过KRTS的共享内存使KRTS的实时进程与Qt应用程序进行通信。首先简单介绍什么是Kithara RTS。

由于基于PC的控制系统在工业自动化生产领域得到了广泛的应用,而运行在PC的主流操作系统Windows本身并不是一个实时操作系统,这限制了PC在某些需要高实时性能控制系统的应用。针对该问题,通常的解决方法是为Windows增加一个可编程的实时子系统,而实现这种功能的软件被称为Windows实时拓展软件。而德国Kithara软件公司正是业界知名的Windows实时拓展软件专家,自1996年开始致力于Windows实时拓展软件的研发,其推出的模块化Windows实时拓展软件Kithara Realtime Suite(KRTS)不仅可以为安装Windows的PC提供优秀的实时性能,而且具有众多功能模块以辅助项目和产品的研发。目前国内外很多大公司都采用其产品,如BOSCH(博世)、SIEMENS(西门子)、ALSTOM(阿尔斯通)等公司。

简单来说,Kithara RTS是德国Kithara软件公司的一个产品,本质是一个Windows实时拓展程序,可以把Windows变成一个实时操作系统。此外Kithara RTS自身具有很多功能模块,如EtherCAT、CANopen、Profibus模块等,可以将Halcon、OpenCV直接载入到Kithara RTS的实时内核中执行。因此,Kithara RTS可以把PC变成现场控制系统,应用于运动控制系统中,如数控系统、机器人、自动化控制系统等。

我们知道,共享内存是程序之间进行数据交互的最基本的方式,而由于Windows和Kithara RTS本身为两个独立的系统,为了能够使两个不同系统之上的程序进行通信,那么就必须开辟一块内存区域用于数据共享。

由于每个应用都有独立的地址空间,所以一个进程一般不会访问其他程序的内存。另外,自己的程序一般不能访问内核内存,因为内核层的内存是受保护的。因此为了在不同应用层程序之间、应用层程序与内核层程序之间的实现快速数据交换,需要申请一块独立的物理内存,Kithara RTS中用于操作共享内存的功能在Base模块。

应用层程序和内核层程序可访问的内存地址空间是不同的,这两部分内存区域是独立的。因此,Kithara中关于共享内存的函数会同时指定两个不同的地址参数。

以下是Kithara RTS中提供的操作共享内存的APIs:

Shared memory

KS_createSharedMem (creates shared memory for data exchange)
KS_freeSharedMem (frees shared memory)
KS_getSharedMem (gives the current address of shared memory)
KS_readMem (reads from kernel memory)
KS_writeMem (writes to kernel memory)
KS_createSharedMemEx (creates shared memory for data exchange)
KS_freeSharedMemEx (frees shared memory)
KS_getSharedMemEx (gives the address of shared memory determined by current context)
KS_querySharedMemInfo (is not implemented yet)

下面以一个简单的示例说明如何使用Kithara RTS中的共享内存,以及Qt应用程序如何通过共享内存与Kithara实时任务通信。

Kithara工程相关配置略过,可以直接在Kithara安装目录中的smp目录下的示例工程中修改,这样就可以省去配置工作。下面是具体实现的源文件,我将它命名为periodicTimerTaskShm.cpp。

#include "..\_KitharaSmp\_KitharaSmp.h"

const char* pCustomerNumber = "DEMO";

//------ CallBackData ------
struct CallBackData {
  int counter;
};

const int us = 10;

//----------------------------------------------------------------
// Ctrl + C handler
//----------------------------------------------------------------
bool stopFlag = false;
BOOL WINAPI _keyboardHandler(DWORD key)
{
        if(key == CTRL_C_EVENT){
                // 当Ctrl+C的时候发生的事情
				outputTxt("< Ctrl + C > event happened.");
				stopFlag = true;
                return true;
        }
		return false;
} 

//------ _callBackA ------
static Error __stdcall _callBackA(void* pArgs, void* pContext) {
  CallBackData* pData = (CallBackData*)pArgs;
  pData->counter++
  return KS_OK;
}

//--------------------------------------------------------
// This is the main program
//--------------------------------------------------------
void runSample() {
  Error ksError;
  SetConsoleCtrlHandler(_keyboardHandler, TRUE); // 添加事件回调函数

  ksError = KS_openDriver(pCustomerNumber);                    
  if (ksError) {
    outputErr(ksError, "KS_openDriver", "Maybe incorrect customer number?");
    return;
  }

  //------------------------------------------------------
  // Allocation of Sharedmem
  //------------------------------------------------------
  CallBackData* pAppPtr;
  CallBackData* pSysPtr;
  ksError = KS_createSharedMem(
              (void**)&pAppPtr,    // App Pointer
              (void**)&pSysPtr,    // Sys Pointer
              "periodicTimerTaskShm2Qt",    // Name
              sizeof(CallBackData),          // Size
              KSF_ALTERNATIVE | KSF_CONTINUOUS);                                     // Flags - KSF_ALTERNATIVE | KSF_CONTINUOUS
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createSharedMem", "Failed to allocate shared memory");
    KS_closeDriver();
    return;
  }
  
// 也可以通过以下方法创建
/*
  KSHandle hShmEx;
  ksError = KS_createSharedMemEx(&hShmEx, "GSK_TaskTimerCycle2QtSHM", sizeof(CallBackData), KSF_ALTERNATIVE | KSF_CONTINUOUS);// Flags - KSF_ALTERNATIVE | KSF_CONTINUOUS
  if(ksError != KS_OK) {
	outputErr(ksError, "KS_createSharedMemEx", "Failed to allocate shared memory");
	KS_closeDriver();
	return ;
  }

  CallBackData *pShmExPtr;
  ksError = KS_getSharedMemEx(hShmEx, (void **)&pShmExPtr, 0);
  if(ksError != KS_OK) {
	outputErr(ksError, "KS_getSharedMemEx", "Failed to get shared memory");
	KS_closeDriver();
	return ;
  }
*/
  pAppPtr->counter_ = 0;

  //------------------------------------------------------
  // Now we create the callbacks. The callback contains the KSF_DIRECT_EXEC:  - execution on kernel level
  //------------------------------------------------------
  KSHandle hCallbackA;
  ksError = KS_createCallBack(
              &hCallbackA,    // Address of callback handle
              _callBackA,    // Callback function
              pSysPtr,    // Reference parameter to the callback - pSysPtr
              KSF_DIRECT_EXEC,    // Flags
              0);    // Priority (only on user level)
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createCallBack", "Failed to create callback");
    KS_closeDriver();
    return;
  }

  ksError = KS_createTask(
              &pAppPtr->hTaskA_,  // Address of task handle
              hCallbackA,         // Callback handle
              250,                // Priority
              KSF_DONT_START);    // Dont start the task, a time will do that
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createTask", "Failed to create task");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------
  // Create a timers with different periods. The signalisation objects are tasks in this case.
  //
  // Due to the creation of the timer A directly with a callback handle, the priority has the value 127.
  // Timer B has the priority value 130, which is given when creating the task.
  //
  // Accepted flags are:
  // KSF_REALTIME_EXEC:  - the real-time kernel is to be used
  // KSF_DONT_START:     - don't start the timer (can be started later)
  // KSF_ONE_SHOT:       - signal timer only one time
  //------------------------------------------------------
  KSHandle hTimerA;
  ksError = KS_createTimer(
              &hTimerA,    // Address of timer handle
              1000 * us,   // Timer period in 100-ns-units
			  pAppPtr->hTaskA_,   // Task handle
              KSF_REALTIME_EXEC);   // Flags, here real-time execution
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createTimer", "Unable to create the timer!");
    KS_closeDriver();
    return;
  }

  // Do something
  while(!stopFlag)
  {
	  if (myKbhit()) {
      int key = myGetch();
      if (key == 'q' || key == 'Q')
        break;
    }
  }
  
  outputDec(pAppPtr->counter, "counter: ");
  //outputDec(pShmExPtr ->counter, "counter: ");
  
  waitTime(25 * ms);

  //------------------------------------------------------
  // Stop the timer
  //------------------------------------------------------
  ksError = KS_stopTimer(
              hTimerA);    // Timer handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_stopTimer", "Unable to stop the timer!");

  //------------------------------------------------------
  // Remove the timer
  //------------------------------------------------------
  ksError = KS_removeTimer(
              hTimerA);   // Timer handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_removeTimer", "Unable to remove timer");

  //------------------------------------------------------
  // Remove the callbacks
  //------------------------------------------------------
  ksError = KS_removeCallBack(
              hCallbackA);    // Callback handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_removeCallBack", "Unable to remove the callback!");

  //------------------------------------------------------
  // Remove the shared memory
  //------------------------------------------------------
  ksError = KS_freeSharedMem(
              pAppPtr);    // Application pointer
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeSharedMem", "Unable to remove shared memory!");
  /*
  ksError = KS_freeSharedMemEx(hShmEx, 0);
  if (ksError != KS_OK) {
	outputErr(ksError, "KS_freeSharedMemEx", "Unable to remove shared memory!");
  }
  */

  //------------------------------------------------------
  // At last we have to close the driver to free any allocated resources.
  //------------------------------------------------------

  ksError = KS_closeDriver();
  if (ksError != KS_OK)
    outputErr(ksError, "KS_closeDriver", "Unable to close the driver!");
}

以下是Qt应用程序相关代码:

sharedMemoryTest.pro文件

需要添加两个库:KrtsDemo_x64.lib 和 KrtsDemo_vci.lib

#-------------------------------------------------
#
# Project created by QtCreator 2016-03-09T13:46:03
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = sharedMemoryTest
TEMPLATE = app

LIBS += -L E:/workspace/Kithara/dev -lKrtsDemo_x64 -lKrtsDemo_vci

SOURCES += main.cpp\
        mainwidget.cpp \
    KitharaShm.c

HEADERS  += mainwidget.h \
    KitharaShm.h
    

main.cpp文件

#include "mainwidget.h"
#include <QApplication>

#define SHAREDMEMORY_GLOBALS
#include "KitharaShm.h"

// The name of kithara shared memory is: GSK_TaskTimerCycle2QtSHM

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    G_SharedMemoryInit();
    MainWidget w;
    w.show();
    return a.exec();
}

mainwidget.h文件

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QTimer>

class MainWidget : public QWidget
{
    Q_OBJECT

public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();

private slots:
    void appTimerOut();

private:
    void createUI(void);
    void layoutUI(void);

    QLineEdit *lineEdit1;
    QTimer *appTimer;
};

#endif // MAINWIDGET_H

mainwidget.cpp文件

#include "mainwidget.h"
#include <QFormLayout>
#include "KitharaShm.h"
#include <QDebug>

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    setFixedSize(300, 200);
    setWindowTitle(tr("SharedMemory2Kithara Test"));

    createUI();
    layoutUI();

    appTimer = new QTimer(this);
    connect(appTimer, SIGNAL(timeout()), this, SLOT(appTimerOut()));
    appTimer->start(100);
}

MainWidget::~MainWidget()
{
    G_SharedMemoryCleanup();
}

void MainWidget::createUI()
{
    lineEdit1 = new QLineEdit;
    lineEdit1->setReadOnly(true);
}

void MainWidget::layoutUI()
{
    QFormLayout *mainLayout = new QFormLayout;
    mainLayout->setContentsMargins(15, 30, 15, 30);
    mainLayout->setSpacing(15);

    mainLayout->addRow(tr("counter:"), lineEdit1);

    this->setLayout(mainLayout);
}

void MainWidget::appTimerOut()
{
    if(pShmExPtr == NULL)
    {
        qDebug("pShmExPtr is NULL.");
        return ;
    }
    lineEdit1->setText(QString::number(pShmExPtr->counter));
}

KitharaShm.h文件

#ifndef KITHARASHM_H
#define KITHARASHM_H

#define KS_OK                                           0x00000000
#define KSF_ALTERNATIVE                                 0x00200000
#define KSF_CONTINUOUS                                  0x00010000

//------ Synonyms ------
typedef int                                     Error;
typedef void * 			KSHandle;

#if defined(__cplusplus)
extern "C"
{
#endif

//------ Common functions ------
Error __stdcall KS_openDriver(
                const char* customerNumber);
Error __stdcall KS_closeDriver(
                void);

//------ Shared memory ------
Error __stdcall KS_createSharedMem(
                void** ppAppPtr, void** ppSysPtr, const char* name, int size, int flags);
Error __stdcall KS_freeSharedMem(
                void* pAppPtr);
Error __stdcall KS_getSharedMem(
                void** ppPtr, const char* name);
Error __stdcall KS_readMem(
                void* pBuffer, void* pAppPtr, int size, int offset);
Error __stdcall KS_writeMem(
                const void* pBuffer, void* pAppPtr, int size, int offset);
Error __stdcall KS_createSharedMemEx(
                KSHandle* phHandle, const char* name, int size, int flags);
Error __stdcall KS_freeSharedMemEx(
                KSHandle hHandle, int flags);
Error __stdcall KS_getSharedMemEx(
                KSHandle hHandle, void** pPtr, int flags);


/*
 * 共享内存
 */
#ifdef SHAREDMEMORY_GLOBALS
#define SHAREDMEMORY_EXT
#else
#define SHAREDMEMORY_EXT extern
#endif

//------ CallBackData ------
typedef struct CallBackData {
  int counter;
}CallBackData;

SHAREDMEMORY_EXT KSHandle hShmEx;
SHAREDMEMORY_EXT CallBackData *pShmExPtr;

int G_SharedMemoryInit();
void G_SharedMemoryCleanup();

#if defined(__cplusplus)
}
#endif

#endif // KITHARASHM_H

KitharaShm.c 文件

注意:Qt 应用程序也必须先调用 KS_openDriver() 才能使用共享内存。

#define SHAREDMEMORY_GLOBALS
#include "KitharaShm.h"

int G_SharedMemoryInit()
{
    Error ksError = -1;
    const char* pCustomerNumber = "DEMO";

    ksError = KS_openDriver(pCustomerNumber); // Customer number
      if (ksError) {
 		//
        return;
      }

    ksError = KS_createSharedMemEx(&hShmEx, "periodicTimerTaskShm2Qt", sizeof(CallBackData), KSF_ALTERNATIVE | KSF_CONTINUOUS);
    if(ksError != KS_OK) {
        //
        KS_closeDriver();
        return ;
    }

    ksError = KS_getSharedMemEx(hShmEx, (void **)&pShmExPtr, 0);
    if(ksError != KS_OK) {
        //outputErr(ksError, "KS_getSharedMemEx", "Failed to get shared memory");
        //KS_closeDriver();
        //return ;
    }

    if(pShmExPtr == NULL)
    {
        G_SharedMemoryCleanup();
	    //
        return 1;
    }
    return 0;
}

void G_SharedMemoryCleanup()
{
    Error ksError = -1;
    ksError = KS_freeSharedMemEx(hShmEx, 0);
    if (ksError != KS_OK) {
        //
    }

    ksError = KS_closeDriver();
      if (ksError != KS_OK) {
        //
      }
}
#endif

参考文献:
Kithera添加到QT中
Kithara RTS进程与Qt应用程序间通信

Kithara Codesys是一种实时操作系统(RTOS)和编程环境,用于开发嵌入式控制应用程序。该软件是由德国Kithara Software开发的,旨在提供高性能和稳定性,以满足工业自动化和机器控制领域的需求。 Codesys是一种广泛使用的工业自动化开发环境,它提供了一个集成的开发工具和库,用于创建和管理PLC(可编程逻辑控制器)应用程序。而Kithara Codesys则是在Codesys基础上,结合了Kithara实时操作系统的特性和功能。 Kithara Codesys在实时性能方面表现出色,能够处理实时应用程序的严格时间要求。它提供了具有优先级调度的多任务支持,可以同时管理多个并发任务,并确保各个任务按照预定的时间间隔和优先级进行执行。这种实时性能是在Kithara实时操作系统的基础上实现的,它提供了低延迟的断处理和实时任务调度,确保应用程序对外部输入的及时响应。 Kithara Codesys还具有灵活的硬件支持,支持多种不同的硬件平台和接口。它可以与各种专用硬件设备和传感器进行连接,并通过标准的PLC编程语言进行控制和通信。这使得开发人员可以根据自己的需求选择合适的硬件平台,以实现最佳的控制和自动化方案。 总的来说,Kithara Codesys是一种强大的嵌入式控制开发环境,结合了Codesys的功能和Kithara实时操作系统的实时性能。它在工业自动化领域有广泛的应用,能够满足各种复杂的控制需求,并提供稳定可靠的运行环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值