[工业互联-21]:常见EtherCAT主站方案:Kithara实时套件

news2024/11/15 16:55:21

第1章 Kithara实时套件概述

1.1 概述

Kithara Software是一家德国的软件公司,专注于实时技术嵌入式解决方案

他们为Windows操作系统提供了Kithara RealTime Suite,这是一套实时扩展模块,使Windows能够实现硬实时任务和控制。

Kithara RealTime Suite提供了一系列的实时功能,包括实时调度器、硬实时驱动程序和实时通信机制。它可以将Windows操作系统转变为一个强大的实时平台适用于许多应用领域,如机器人控制、生产自动化、测试和测量等。

除了实时功能,Kithara RealTime Suite还提供了其他特性,如实时数据采集实时图形化用户界面、实时网络通信和实时控制器接口等。

Kithara RealTime Suite的使用需要对实时系统操作开发和配置有一定的技术要求。因此,如果您对Kithara软件产品感兴趣,建议您参考官方网站或与Kithara软件团队联系,以获取更详细的信息和支持。

1.2 主要功能

 Kithara RealTime Suite是一套针对Windows操作系统的实时解决方案,它提供了实时性能和嵌入式开发所需的功能。以下是Kithara RealTime Suite的一些主要方案和功能:

  1. 实时控制:Kithara RealTime Suite可以将Windows操作系统转变为一个强大的实时控制平台。它提供一个实时调度器,使开发人员能够编写和执行硬实时任务,实现精确的控制。

  2. 实时通信:Kithara RealTime Suite支持实时通信机制,包括共享内存、实时IPC(进程间通信)、实时网络通信等,使不同任务之间可以高效地进行通信和数据交换。

  3. 实时数据采集和处理:Kithara RealTime Suite提供了实时数据采集的功能,使开发人员能够高速读取和处理传感器数据、信号等实时数据,并实时响应。

  4. 实时图形化用户界面:Kithara RealTime Suite支持实时图形化用户界面(GUI),使开发人员可以创建动态和交互式的实时用户界面,用于监控和操作实时控制系统。

  5. 实时网络通信:Kithara RealTime Suite提供了实时网络通信库,可以实现实时UDP和实时TCP通信,使实时控制系统可以与其他设备和系统进行实时数据交换和通信。

以上只是Kithara RealTime Suite提供的一些主要方案和功能,该解决方案还具有其他特性和工具,可根据具体应用的需求进行定制和配置。

1.3 Kithara实时套件软件架构

        Kithara RealTime Suite是一个组合套件,提供了一系列功能和工具,用于在Windows操作系统上实时开发和控制应用程序。以下是Kithara RealTime Suite的软件架构的主要组件和层级:

  1. 实时内核(Real-time Kernel):实时内核是Kithara RealTime Suite的核心组件,它提供了基础的实时调度和任务处理功能。实时内核处理任务的优先级和调度,保证任务按照预定的时间和顺序执行,并提供了实时事件和中断处理机制。

  2. 实时驱动程序(Real-time Drivers):Kithara RealTime Suite包含了一些实时驱动程序,用于与硬件设备进行实时通信和控制。这些驱动程序可以与各种硬件接口和设备通信,如数据采集卡、传感器、执行器等。

  3. 实时通信库(Real-time Communication Libraries):Kithara RealTime Suite提供了一些实时通信库,用于实现实时数据交换和通信。这些库支持共享内存、实时IPC(进程间通信)、实时网络通信等机制,以便实时任务之间或与外部设备进行实时数据传输。

  4. 实时文件系统(Real-time File System):Kithara RealTime Suite提供了实时文件系统,可用于实时应用程序中的数据存储和访问。它可以确保实时读写操作的可靠性和实时性能。

  5. 实时图形化用户界面(Real-time GUI):Kithara RealTime Suite支持实时图形化用户界面的开发,开发人员可以使用这些工具创建动态和交互式的实时监控界面,用于实时控制系统的可视化和操作。

  6. 实时开发工具(Real-time Development Tools):Kithara RealTime Suite提供了一些实时开发工具,用于辅助实时应用程序的开发和调试。这些工具包括实时调度器分析器、实时事件追踪器和调试器等。

        通过以上组件和层级,Kithara RealTime Suite提供了一个完整的软件架构,使开发人员能够在Windows操作系统上进行实时应用程序的开发、控制和监控。请注意,具体的架构和组件可根据实际应用需求进行定制和配置。

第2章 Kithara实时套件详解

2.1 实时操作系统如何与Windows操作系统一起工作

2.2 软实时与硬实时的区别

软实时(Soft Real-Time)和硬实时(Hard Real-Time)是实时系统中常用的两个概念,用于描述任务是否能够在预定的时间内得到满足。

软实时:指的是系统能够在大部分情况下满足任务的实时性要求,但在偶尔的情况下可能会有一些延迟或错过任务的截止时间。软实时系统的主要特点是性能的可预测性较差,对于时间要求并不是非常严格。在软实时系统中,错过任务的截止时间可能会导致性能下降或一些不可预测的情况发生,但不会对系统的稳定性产生严重影响。

硬实时:指的是系统必须能够在严格的时间约束下满足任务的实时性要求,任务的截止时间是绝对不能错过的。硬实时系统要求系统能够以确定性地、一致地和可预测性地响应任务,并确保任务的截止时间不会被延迟。在硬实时系统中,一旦任务的截止时间被错过,可能会导致系统失败、严重事故或其他严重后果。

简而言之,软实时系统在大部分情况下能满足实时性要求,但偶尔可能会有延迟,而硬实时系统则要求在严格的时间约束下绝不能错过任务的截止时间。

需要注意的是,软实时和硬实时并没有严格的界限,而是存在一个连续的实时性要求的范围。在实时系统设计中,需要根据具体应用的需求和性能要求来确定是选择软实时还是硬实时方案。

 

2.3 为什么使用Windows操作实时操作系统

 

 2.4 Windows实时拓展Kithara

 

2.5 如何将kithara库添加到QT中使用

如何将kithara库添加到QT中使用_kithara 实时套件_kobesdu的博客-CSDN博客

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替换成其他名字即可

————————————————

2.6 Kithara RTS进程与Qt应用程序间通信(共享内存)

Kithara RTS进程与Qt应用程序间通信(共享内存)_ks_opendriver_阿基米东的博客-CSDN博客

由于基于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

————————————————

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

菜比:你还不会接口测试?

很多人会谈论接口测试。到底什么是接口测试&#xff1f;如何进行接口测试&#xff1f;这篇文章会帮到你。 一、前端和后端 在谈论接口测试之前&#xff0c;让我们先明确前端和后端这两个概念。 前端是我们在网页或移动应用程序中看到的页面&#xff0c;它由 HTML 和 CSS 编写…

QT - 20230710

练习&#xff1a;实现一个简易闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDateTime> #include <QDebug> #include <QTextToSpeech>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJECTpubl…

Kafka入门, Kafka-Kraft 模式 部署(二十六)

Kafka-Kraft 模式 左图为kafka现有架构&#xff0c;元数据在zookeeper中&#xff0c;运行时动态选举controller,由controller进行kafka集群管理&#xff0c;右图为kraft模式架构&#xff08;实验性&#xff09;&#xff0c;不再依赖zookeeper集群&#xff0c;而是用三台control…

MyBatis将查询的两个字段分别作为Map的key和value

问题背景 首先查出 危险源id 和 危险源报警的个数 alarm 遍历危险源&#xff0c;将报警数填充进去 所以&#xff0c;我需要根据id得到alarm 最方便的就是Map 经过sql查询 -- 危险源下的对象的报警个数select id, ifnull(alarm_count,0) alarm from spang_monitor_danger_…

LongLLaMA:LLaMA的升级版,处理超长上下文的利器!

原文来源&#xff1a;芝士AI吃鱼 有效整合新知识&#xff1a;大模型面临的挑战 大家使用过大型模型产品的时候可能会遇到一个共同的问题&#xff1a;在进行多轮对话时&#xff0c;模型可能会忘记之前的对话内容&#xff0c;导致回答不连贯。这实际上是由于大型模型在处理大量新…

ARM day10 (IIC协议接收温湿传感器数据)

iic.h #ifndef __IIC_H__ #define __IIC_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" /* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4* I2C1_SCL ---> PF14* I2C1_SDA ---> PF15** */#define SET_SDA_OUT do{…

c++实现贝塞尔曲线,生成缓动和回弹动画

贝塞尔曲线于1962年由法国工程师皮埃尔贝塞尔(Pierre Bzier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。 一般参数公式 贝兹曲线可如下推断。给定点P0、P1、…、Pn,其贝兹曲线即: 几何学的方向上理解贝塞尔曲线: 一阶贝塞尔曲线 二阶贝塞尔曲线 三阶贝塞尔曲…

记录使用注入的方式为Unity编辑器实现扩展能力

使用场景 当前项目编辑器中不方便存放或者提交扩展代码相同的扩展功能需要在多个项目(编辑器)中使用项目开发中&#xff0c;偶尔临时需要使用一个功能&#xff0c;想随时使用随时卸载 设计思路 使用进程注入&#xff0c;将一个c/c dll注入到当前运行的unity编辑器中使用c/c …

分布式搜索 (二)

一、DSL 查询文档 1. DSL Query 的分类 Elasticsearch 提供了基于 JSON 的 DSL (Domain Specific Language) 来定义查询 常见的查询类型包括&#xff1a; ① 查询所有&#xff1a;查询出所有数据&#xff0c;一般测 试用 例如&#xff1a;match_all ② 全文检索 (full text) …

C++数据结构笔记(8)循环链表实现

1.循环链表与单链表的区别在于尾部结点存在指向头结点的指针 2.无论尾部结点指向第一个结点&#xff08;头结点&#xff09;还是第二个结点&#xff08;第一个有效结点&#xff09;&#xff0c;都可以被称为循环链表 3.判断循环结束的两种方式&#xff1a;遍历次数等于size;或…

《深度探索c++对象模型》笔记

非原创&#xff0c;在学习 1 关于对象&#xff08;Object Lessons&#xff09; 这里最开始从C语言的结构体引出C中的”抽象数据类型&#xff08;ADT&#xff09;“。 而加上封装之后&#xff0c;布局成本没有增加&#xff0c;三个data member直接内含在每一个class object之中…

深入选择屏幕

2.3.4.4 屏幕输入报表筛选条件等 &--------------------------------------------------------------------- *& selection-screen /option/parameter:屏幕输入报表赛选条件 *& TABLES . *selection-screen begin of block test select-options: selection-screen…

PHY芯片快速深度理解

摘要&#xff1a; 什么是phy 为什么要熟悉RJ45网口 网络七层协议 两个模块进行通信 什么是MDIO协议 MDIO的作用 MDIO没那么重要 MDIO读写时序 为什么说读取的phy最多32个 什么是phy 物理层芯片称为PHY、数据链路层芯片称为MAC。 可以看到PHY的数据是RJ45网络接口&am…

linux常见指令下

接下来我们就聊聊linux的后面十条指令。 一:echo 作用是往显示器输出内容&#xff0c;和printf类型&#xff0c;但是该指令最核心的是与之相关的一些概念 概念1.输出重定向&#xff1a; echo不仅可以向显示打印内容&#xff0c;还可以向文件输出内容&#xff0c;本应该输出到…

在服务器上启动springboot项目

环境搭建&#xff1a;要在服务器上运行SpringBoot Web项目&#xff0c;需要先在服务器上安装JDK&#xff08;CentOS系统安装JDK参考&#xff1a;http://t.csdn.cn/0zYml&#xff09; 第一步&#xff1a;创建项目 创建一个简单的springboot项目&#xff0c;并通过测试&#xf…

Java Web Servlet (2)23.7.8

1.7 urlPattern配置 Servlet类编写好后&#xff0c;要想被访问到&#xff0c;就需要配置其访问路径&#xff08;urlPattern&#xff09; 一个Servlet,可以配置多个urlPattern package com.itheima.web;import javax.servlet.ServletRequest; import javax.servlet.ServletRes…

嵌入式基础知识-流水线

提到流水线&#xff0c;最先想到的可能是流水线车间中的产品制造过程。 工业上的流水线&#xff0c;又称装配线&#xff0c;指每一个生产单位只专注处理某一个片段的工作&#xff0c;以提高工作效率及产量。 在计算机领域中&#xff0c;也有流水线的概念&#xff0c;其核心原理…

互联网医院系统定制|互联网医院在线诊疗平台

互联网医院系统对医院有以下几个方面的帮助&#xff1a;   提升医疗服务效率&#xff1a;互联网医院系统可以为医院提供在线挂号、在线问诊、远程会诊等功能&#xff0c;减少患者排队等待时间&#xff0c;提高医疗服务效率。   扩大服务范围&#xff1a;互联网医院系统可以…

【数据结构二叉树OJ系列】6、平衡二叉树

目录 题述&#xff1a; 思路&#xff1a; 正确代码如下&#xff1a; 时间复杂度分析&#xff1a; 现让你把代码优化时间复杂度为O&#xff08;N&#xff09; 思路&#xff1a; 题述&#xff1a; 给定一个二叉树&#xff0c;判断他是否是高度平衡的二叉树。 本题中&#xf…

HttpRunner自动化之接口关联和常用断言

接口关联 第一个test接口获取token,并提取出存储到变量中&#xff0c;在第二个test接口中直接调用该变量&#xff0c;如下图 # 接口关联 - config:name: 微信接口base_url: https://api.weixin.qq.com - test:name: 获取tokenrequest:url: /cgi-bin/tokenmethod: GETparams:g…