【CanFDBasics】- KRTS C++示例精讲(5)

CanFDBasics示例讲解



项目打开请查看【BaseFunction精讲】。

结构说明

在这里插入图片描述

  • CanFDBasics:应用层程序,主要用于人机交互、数据显示、内核层数据交互等;

    1. CanFDBasics.h : 数据定义
    2. CanFDBasics.cpp:用户应用层源码
  • CanFDBasics_64: 内核层程序(实时层程序),主要用于实时数据处理;

    1. CanFDBasics.h : 数据定义
    2. CanFDBasics_dll.cpp : 内核层源码
  • 其余文件说明请查看【BaseFunction精讲】中的结构说明。
    ps : 内核层中的数据、结构体需要一字节对齐,需要以MT方式构建
    在这里插入图片描述

代码说明

CanFDBasics.h : 应用层与内核层共用一个头文件

/* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         CanFDBasics.h
//
// 模块: 带有 CAN-FD 扩展的 CAN 模块
//
// 描述:   用户应用程序和内核 DLL 之间的共享定义,例如:从用户层面在 CAN-FD 端口上进行通信
//
// 创建者:      t.pet 2009-04-18
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目地:
//
// 本示例展示了如何对 CAN-FD 通信应用程序进行编程。
// 通信需要两个连接的 CAN-FD 端口,可以是同一个 CAN-FD 设备上的端口,也可以是不同设备上的端口。
//
// 首先,程序会打开驱动程序,并在 PCI CAN-FD 设备上打开一个用于发送报文的端口,第二个用于接收报文的端口。
// 我们安装一个内核级接收回调,将接收到的 CANFD 报文复制到共享内存中。
// 应用程序将打印接收到的 CAN 消息。
// 最后,我们释放所有已用资源并关闭驱动程序。
//
// 由于 CAN-FD 优先于 CAN,因此该示例也可以发送和接收 CAN 消息。
//
//##############################################################################################################

#ifndef __SMP_CANFDBASICS_H
#define __SMP_CANFDBASICS_H

#include "../_KitharaSmp/_KitharaSmp.h"


//--------------------------------------------------------------------------------------------------------------
// SharedData 是一个用户定义的参数结构,用于在内核 DLL 和用户应用程序之间使用共享内存进行信息交换。
// 您可以自由定义任何与系统位大小无关的参数。
//--------------------------------------------------------------------------------------------------------------

struct SharedData {
  KSHandle hKernel;                                     // 内核句柄
  KSHandle hReceiveCallBack;                            // 回调句柄,由传入的回调触发的回调获取CAN-FD消息
  KSHandle hCanRecv;                                    // 接收CAN-FD接口的句柄
  KSHandle hCanXmit;                                    // 发送CAN-FD接口的句柄
  char pDeviceNameRecv[256];                            // 接收的 CAN-FD 设备名称
  int recvPort;                                         // 接收CAN-FD接口的端口
  char pDeviceNameXmit[256];                            // 发送CAN-FD 设备名称
  int xmitPort;                                         // 发送CAN-FD接口的端口

  KSCanFdMsg sendMsg;                                   // 将 CAN-FD 报文从用户应用程序传输到内核 dll 的缓冲区
  KSCanFdMsg receiveMsg;                                // 将接收到的 CAN-FD 报文从内核 dll 传输到用户应用程序的缓冲区
};

#endif // __SMP_CANFDBASICS_H

CanFDBasics.cpp

/* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         CanFDBasics.cpp
//
// 模块: 带有 CAN-FD 扩展的 CAN 模块
//
// 描述:   用户应用程序和内核 DLL 之间的共享定义,例如:从用户层面在 CAN-FD 端口上进行通信
//
// 创建者:      t.pet 2009-04-18
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目地:
//
// 本示例展示了如何对 CAN-FD 通信应用程序进行编程。
// 通信需要两个连接的 CAN-FD 端口,可以是同一个 CAN-FD 设备上的端口,也可以是不同设备上的端口。
//
// 首先,程序会打开驱动程序,并在 PCI CAN-FD 设备上打开一个用于发送报文的端口,第二个用于接收报文的端口。
// 我们安装一个内核级接收回调,将接收到的 CANFD 报文复制到共享内存中。
// 应用程序将打印接收到的 CAN 消息。
// 最后,我们释放所有已用资源并关闭驱动程序。
//
// 由于 CAN-FD 优先于 CAN,因此该示例也可以发送和接收 CAN 消息。
//
//##############################################################################################################

#include "CanFDBasics.h"


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// 别忘了输入你的序列号(6位客户编号),这是打开驱动程序所必需的。
// 
// 如果你使用Demo版本,也可以使用“DEMO”代替。
// 如果你使用Beta版本,也可以使用“BETA”代替。
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// 如上说所,定义的客户号 
const char _pCustomerNumber[] = "DEMO";

//--------------------------------------------------------------------------------------------------------------
// 声明将 CAN-FD 报文内容输出到控制台的辅助函数。
// 该函数的定义在本文件末尾。
//--------------------------------------------------------------------------------------------------------------

void printCanFdMsg(KSCanFdMsg msg);


// 主程序入口
void runSample() {
  outputTxt("***** Kithara example program 'CanFDBasics' *****");

  // 错误码定义,KSError 是 Kithara API 所有函数的返回类型,通过 【KSError】 可以查询接口的返回错误信息。
  KSError ksError;

  //------------------------------------------------------------------------------------------------------------
  // 打开驱动程序的第一步,所有KRTS程序必须进行的操作。
  // 只要该函数调用成功后,我们可以使用其他函数。如果打开失败,则无法调用其他函数。
  // 此函数接受您的客户编号作为参数,其中包含 Kithara(如果适用可以为“DEMO”或“BETA”)。
  //------------------------------------------------------------------------------------------------------------
  
  ksError = KS_openDriver(
              _pCustomerNumber);                        // 客户序列号
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_openDriver", "Unable to open the driver!");
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 创建共享内存
  // 为实时层中的DLL和此用户层应用程序之间的通信。
  //------------------------------------------------------------------------------------------------------------

  KSHandle hSharedMemory;
  ksError = KS_createSharedMemEx(
              &hSharedMemory,                           // 返回创建的共享内存句柄
              "",                                       // 共享内存的名称
              sizeof(SharedData),                       // 共享内存的大小
              KSF_NO_FLAGS);                            // 无标记,此选项可以进行一些特殊设定
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createSharedMemEx", "Unable to create shared memory!");
    KS_closeDriver();
    return;
  }

  // 要访问共享内存,应用程序需要使用刚创建的共享内存的句柄来获取指向分配的共享内存的指针。
  SharedData* pApp = NULL;								// 自定义的共享内存结构体
  ksError = KS_getSharedMemEx(
              hSharedMemory,                            // 共享内存的句柄
              (void**)&pApp,                            // 指向共享内存的结构的指针
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_getSharedMemEx", "Unable to map shared memory!");
    KS_closeDriver();
    return;
  }

  // 确定操作系统的位数大小以决定是加载32位还是64位内核DLL。
  KSSystemInformation systemInfo;                       // 获取系统信息的结构体
  systemInfo.structSize = sizeof(KSSystemInformation);  // 不要忘记设备结构体大小
  ksError = KS_getSystemInformation(
              &systemInfo,                              // 结构体指针用于获取结构体数据
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_getSystemInformation", "Unable to get system information to distinguish bitsize!");
    KS_closeDriver();
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 想要在内核级别上使用DLL中的函数,必须加载dll,在调用里面的函数!
  // 注意!加载程序必须找到DLL,因此它应该放在搜索路径的目录中!
  // 因为我们想要在共享内存中传递加载的内核的句柄,所以我们不使用加载内核时的初始化函数,
  // 而是在填充内核句柄和初始化内核所需的所有信息之后,显式调用初始化函数。
  //------------------------------------------------------------------------------------------------------------
  
  ksError = KS_loadKernel(
              &pApp->hKernel,                           // 返回内核操作句柄
              systemInfo.isSys64Bit ?                   // 根据系统位数加载内核Dll
                "CanFDBasics_64.dll" :                 
                "CanFDBasics_32.dll",           
              NULL,                                     // 需要支持的函数名称(未使用)
              NULL,                                     // 函数参数 (未使用)
              KSF_KERNEL_EXEC);                         // 内核空间中加载(实时层运行)
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_loadKernel", "Unable to load DLL! Is the DLL in the search path?");
    KS_closeDriver();
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 首先,查询并显示所有CAN-FD设备的名称。
  //------------------------------------------------------------------------------------------------------------

  char pDeviceName[256];

  outputTxt(" ");
  outputTxt("Following CAN-FD devices found:");

  for (int i = 0;; ++i) {


    //----------------------------------------------------------------------------------------------------------
    // KS_enumDevices() 可以用于查询分配给 Kithara 的所有 CAN-FD 设备名称。
    //----------------------------------------------------------------------------------------------------------

    ksError = KS_enumDevices(
                "CAN",                                  // 'CAN'表示搜索 CAN 和 CAN-FD 设备
                i,                                      // 枚举索引,从零开始
                pDeviceName,                            // 返回设备名称
                KSF_NO_FLAGS);                          // 无标记
    if (ksError != KS_OK) {
      if (KSERROR_CODE(ksError) != KSERROR_DEVICE_NOT_FOUND)
        outputErr(ksError, "KS_enumDevices", "Unable to query CAN-FD device name!");
      if (KSERROR_CODE(ksError) == KSERROR_DEVICE_NOT_FOUND && !i) {
        outputTxt("No CAN-FD devices found.");
        outputTxt(" ");
        KS_closeDriver();
        return;
      }
      break;
    }
    outputDec(i, "", ": ", false);
    outputTxt(pDeviceName);
  }
  outputTxt(" ");


  //------------------------------------------------------------------------------------------------------------
  // 输入用于发送的设备的索引。
  //------------------------------------------------------------------------------------------------------------

  int deviceIndex = inputDec("Device number for xmit: ", 0);

  ksError = KS_enumDevices(
              "CAN",                                    // 'CAN'表示搜索 CAN 和 CAN-FD 设备
              deviceIndex,                              // CAN-FD 设备索引
              pApp->pDeviceNameXmit,                    // 设备名称
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_enumDevices", "Unable to query selected CAN-FD device name!");
    KS_closeDriver();
    return;
  }

  outputTxt("Selected device: ", false);
  outputTxt(pApp->pDeviceNameXmit);
  outputTxt(" ");

  pApp->xmitPort = inputDec("Port number for xmit: ", 0);
  outputTxt(" ");


  //------------------------------------------------------------------------------------------------------------
  //  输入用于接收的设备的索引。
  //------------------------------------------------------------------------------------------------------------

  deviceIndex = inputDec("Device number for recv: ", 0);

  ksError = KS_enumDevices(
              "CAN",                                    // 'CAN'表示搜索 CAN 和 CAN-FD 设备
              deviceIndex,                              // CAN-FD 设备索引
              pApp->pDeviceNameRecv,                    // 设备名称
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_enumDevices", "Unable to query CAN-FD device name!");
    KS_closeDriver();
    return;
  }

  outputTxt("Selected device: ", false);
  outputTxt(pApp->pDeviceNameRecv);
  outputTxt(" ");

  pApp->recvPort = inputDec("Port number for recv: ", 1);
  outputTxt(" ");

  pApp->sendMsg.structSize = sizeof(KSCanFdMsg);        // 不要忘记初始化 structSize!
  pApp->receiveMsg.structSize = sizeof(KSCanFdMsg);     // 不要忘记初始化 structSize!

  //------------------------------------------------------------------------------------------------------------
  // 显式调用初始化函数。
  // 调用内核的【_initFunction】函数,并传递共享内存的句柄,这样内核就可以从句柄中检索到共享内存的指针,
  // 并根据共享内存中存储的信息进行所有必要的资源分配。
  // 更为详细的内核初始化操作可以查看内核层【_initFunction】函数
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_execKernelFunctionEx(
              pApp->hKernel,                            // 内核句柄
              "_initFunction",                          // 函数名称
              hSharedMemory,                            // 共享内存的句柄
              KS_INVALID_HANDLE,                        // 上下文
              KSF_NO_FLAGS);                            // 未使用
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_execKernelFunctionEx", "Unable to initialize the kernel DLL!");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // 询问用户关于应传输的CAN-FD消息的详细信息。
  //------------------------------------------------------------------------------------------------------------

  pApp->sendMsg.msgType = 0;
  if (inputDec("Send CAN [0] or CAN-FD [1] message ?", 1) == 1)
    pApp->sendMsg.msgType = KS_CAN_MSGTYPE_FD | KS_CAN_MSGTYPE_BRS;
  if (inputDec("Send standard [0] or extended [1] message ?", 1) == 1)
    pApp->sendMsg.msgType |= KS_CAN_MSGTYPE_EXTENDED;

  uint defaultMsgLength = (pApp->sendMsg.msgType & KS_CAN_MSGTYPE_FD) == KS_CAN_MSGTYPE_FD ? 64 : 8;
  pApp->sendMsg.dataLength = inputDec("data length: ", defaultMsgLength);
  pApp->sendMsg.identifier = inputHex("Identifier: ", "123");

  for (int i = 0; i < pApp->sendMsg.dataLength; ++i)
    pApp->sendMsg.msgData[i] = i;

  outputTxt(" ");
  outputTxt("Message that will be sent:");
  printCanFdMsg(pApp->sendMsg);
  outputTxt(" ");
  outputTxt("Content of buffer for received message before receiving:");
  printCanFdMsg(pApp->receiveMsg);

  ksError = KS_xmitCanFdMsg(
              pApp->hCanXmit,                           // 发送CAN-FD端口句柄
              &pApp->sendMsg,                           // KSCanFdMsg结构的地址
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_xmitCanFdMsg", "Can not send this message!");
    KS_closeDriver();
    return;
  }
  else {
    outputTxt("Message sent.");
    outputTxt(" ");
  }


  //------------------------------------------------------------------------------------------------------------
  // 不要等待超过1秒的。
  //------------------------------------------------------------------------------------------------------------

  waitTime(1 * s);


  outputTxt("Content of buffer for received message:");
  printCanFdMsg(pApp->receiveMsg);


  //------------------------------------------------------------------------------------------------------------
  // 清理内核DLL中分配的资源。
  //------------------------------------------------------------------------------------------------------------
  ksError = KS_execKernelFunctionEx(
              pApp->hKernel,                            // 内核句柄
              "_exitFunction",                          // 内核层退出函数
              KS_INVALID_HANDLE,                        // 传参
              KS_INVALID_HANDLE,                        // 上下文
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_execKernelFunctionEx", "Error while deallocating resources on kernel level!");
    KS_closeDriver();
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 使用共享句柄卸载内核DLL。
  // 尽管KS_closeDriver()释放了所有分配的资源(如共享内存和加载的内核),
  // 明确释放您分配的资源是很好的习惯。
  //------------------------------------------------------------------------------------------------------------
  
  // 释放内核
  ksError = KS_freeKernel(
              pApp->hKernel);                           // 内核句柄
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeKernel", "Unable to unload the kernel!");


  //------------------------------------------------------------------------------------------------------------
  // 使用共享内存手柄释放共享内存。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_freeSharedMemEx(
              hSharedMemory,                            // 共享内存句柄
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeSharedMemEx", "Unable to remove shared memory!");


  //------------------------------------------------------------------------------------------------------------
  // 关闭驱动程序以释放分配的资源。
  //------------------------------------------------------------------------------------------------------------

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

  waitTime(500 * ms);
  outputTxt(" ");
  outputTxt("End of program 'CanFDBasics'.");
}


//--------------------------------------------------------------------------------------------------------------
// 辅助函数,将 CAN-FD 消息的内容输出到控制台。
//--------------------------------------------------------------------------------------------------------------

void printCanFdMsg(KSCanFdMsg msg) {
  outputTxt("Message type: ", false);

  if (msg.msgType & KS_CAN_MSGTYPE_FD) {
    outputTxt("CAN-FD");
    outputTxt("Bitrate switch: ", false);
    outputTxt(msg.msgType & KS_CAN_MSGTYPE_BRS ? "Yes" : "No");
  }
  else {
    outputTxt("Classic CAN");
    outputTxt("Remote Transmission Request (RTR): ", false);
    outputTxt(msg.msgType & KS_CAN_MSGTYPE_RTR ? "Yes" : "No");
  }

  outputTxt("ID type: ", false);
  if (!(msg.msgType & KS_CAN_MSGTYPE_EXTENDED))
    outputTxt("STANDARD");
  else
    outputTxt("EXTENDED");

  outputDec(msg.dataLength, "Length: ", " bytes");
  outputHex04(msg.identifier, "ID: 0x");
  if (!(msg.msgType & KS_CAN_MSGTYPE_RTR)) {
    outputTxt("Data: ", false);
    for (int i = 0; i < msg.dataLength; ++i)
      outputHex02(msg.msgData[i], "0x", " ", false);
  }
  outputTxt(" ");
  outputDec(msg.timestamp, "Timestamp: ", " us");       // 时间戳仅设置在接收到的消息
  outputTxt(" ");
}

CanFDBasics_dll.cpp

/* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         CanFDBasics_dll.cpp
//

// 模块: 带有 CAN-FD 扩展的 CAN 模块
//
// 描述:   用户应用程序和内核 DLL 之间的共享定义,例如:从用户层面在 CAN-FD 端口上进行通信
//
// 创建者:      t.pet 2009-04-18
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目地:
//
// 本示例展示了如何对 CAN-FD 通信应用程序进行编程。
// 通信需要两个连接的 CAN-FD 端口,可以是同一个 CAN-FD 设备上的端口,也可以是不同设备上的端口。
//
// 首先,程序会打开驱动程序,并在 PCI CAN-FD 设备上打开一个用于发送报文的端口,第二个用于接收报文的端口。
// 我们安装一个内核级接收回调,将接收到的 CANFD 报文复制到共享内存中。
// 应用程序将打印接收到的 CAN 消息。
// 最后,我们释放所有已用资源并关闭驱动程序。
//
// 由于 CAN-FD 优先于 CAN,因此该示例也可以发送和接收 CAN 消息。
//
//##############################################################################################################


//--------------------------------------------------------------------------------------------------------------
// 为了在主程序(用户层)和内核 DLL 之间共享数据结构的定义,我们使用了一个通用的头文件。
//--------------------------------------------------------------------------------------------------------------

#include "CanFDBasics.h"


// 共享内存用于在内核层 DLL 和用户层的应用程序之间共享数据。
SharedData* _pSys = NULL;

// 声明在本文件末尾定义的回调函数。
KSError __stdcall receiveCallBack(void* /*pArgs*/, void* /*pContext*/);


//--------------------------------------------------------------------------------------------------------------
// 这是初始化函数。
// 它在加载内核后被调用,并将共享内存的句柄作为参数传递。
//
// 注意!请记住,所有函数都应声明为 'extern "C"'!
// 否则它们的名字可能无法被加载器找到。
// 必须通过 '__declspec(dllexport)' 导出它们。
//--------------------------------------------------------------------------------------------------------------

extern "C" KSError __declspec(dllexport) __stdcall _initFunction(void* pArgs, void* /*pContext*/) {
  KSError ksError;


  // 共享内存的指针通过 KS_execKernelFunctionEx() 作为 'pArgs' 参数传递。
  _pSys = (SharedData*)pArgs;


  // 创建回调,用于接收数据
  ksError = KS_createCallBack(
              &_pSys->hReceiveCallBack,                 // 获取回调句柄
              receiveCallBack,                          // 回调函数
              NULL,                                     // 参考参数到回调(未使用)
              KSF_DIRECT_EXEC,                          // 在内核中执行
              0);                                       // 优先级(内核级别未使用)
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 现在,两个CAN-FD端口将使用相同的通信设置打开。
  //------------------------------------------------------------------------------------------------------------

  KSCanFdConfig config = { 0 };
  config.structSize      = sizeof(KSCanFdConfig);       // 不要忘记初始化 structSize!
  config.nominalBaudRate = KS_CAN_BAUD_500K;
  config.fastBaudRate    = KS_CAN_FD_BAUD_2M;

  // 打开CAN-FD设备
  ksError = KS_openCanFd(
              &_pSys->hCanXmit,                         // 返回 CAN-FD 写入端口句柄
              _pSys->pDeviceNameXmit,                   // CAN-FD设备的设备名称
              _pSys->xmitPort,                          // 端口(计数从 0 开始)
              &config,                                  // KSCanFdConfig结构的地址(波特率信息)
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_openCanFd(
              &_pSys->hCanRecv,                         // 返回 CAN-FD 读取端口句柄
              _pSys->pDeviceNameRecv,                   // CAN-FD设备的设备名称
              _pSys->recvPort,                          // 端口(计数从 0 开始)
              &config,                                  // KSCanFdConfig结构的地址(波特率信息)
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 安装回调以处理接收到的消息。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_installCanFdHandler(
              _pSys->hCanRecv,                          // CAN-FD端口处理程序
              KS_CAN_FD_RECV,                           // 事件类型:接收数据
              _pSys->hReceiveCallBack,                  // 接受回调
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;

  return KS_OK;
}


//--------------------------------------------------------------------------------------------------------------
// 这是清理函数,它会移除CAN-FD-handler,关闭两个CAN设备并移除回调。
//--------------------------------------------------------------------------------------------------------------

extern "C" KSError __declspec(dllexport) __stdcall _exitFunction(void* /*pArgs*/, void* /*pContext*/) {
  if (_pSys == NULL)                                     // 共享内存未映射!
    return KSERROR_FUNCTION_NOT_AVAILABLE;               // _initFunction未被调用?

  KSError ksError;


  //------------------------------------------------------------------------------------------------------------
  // 卸载接收处理程序。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_installCanFdHandler(
              _pSys->hCanRecv,                          // CAN-FD端口处理程序
              KS_CAN_FD_RECV,                           // 事件类型
              KS_INVALID_HANDLE,                        // 重置为无效回调句柄
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 关闭接收的 CAN-FD 端口。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_closeCanFd(
              _pSys->hCanRecv,                          // CAN-FD端口处理程序
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 关闭发送的 CAN-FD 端口。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_closeCanFd(
              _pSys->hCanXmit,                          // CAN-FD端口处理程序
              KSF_NO_FLAGS);                            // Flags (unused)
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 移除回调
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_removeCallBack(
              _pSys->hReceiveCallBack);                 // 回调句柄
  if (ksError != KS_OK)
    return ksError;

  return KS_OK;
}


//------------------------------------------------------------------------------------------------------------
// 这是回调函数,为接收打开的CAN-FD端口上处理传入的CAN-FD消息。
//------------------------------------------------------------------------------------------------------------

KSError __stdcall receiveCallBack(void* /*pArgs*/, void* /*pContext*/) {
  KSError ksError;

  for (;;) {
    ksError = KS_recvCanFdMsg(
                _pSys->hCanRecv,                        // CAN-FD设备的手柄
                &_pSys->receiveMsg,                     // 要写入KSCanFdMsg的地址
                KSF_NO_FLAGS);                          // 无标记
    if (ksError != KS_OK)
      break;
  }
  return ksError;
}


//--------------------------------------------------------------------------------------------------------------
// 需要实现 DllMain 函数,该函数在 DLL 加载时不会被执行。
//
// 对于初始化,请定义一个特殊的 init 函数,并在调用 KS_loadKernel()时将其名称作为参数传递给它,
// 或者在加载内核的句柄以后在加载的 DLL 调用函数(如本例所示)时使用,
// 请不要在加载内核时执行的 init 函数,而是在加载内核后自己明确地调用它,并根据需要传递参数,如本例所示。
//--------------------------------------------------------------------------------------------------------------

#define WIN32_LEAN_AND_MEAN
#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved) {
  return TRUE;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值