当前位置: 首页 > news >正文

怎么在百度上能搜到自己的网站长春火车站停运了吗

怎么在百度上能搜到自己的网站,长春火车站停运了吗,网络营销分销策略是什么,宁波网站优化建站公司EtherCATBridge示例讲解 文章目录 EtherCATBridge示例讲解结构说明代码说明 项目打开请查看【BaseFunction精讲】。 结构说明 EtherCATBridge.h #xff1a;数据定义 EtherCATBridge.cpp #xff1a;应用层源码 EtherCATBridge_dll.cpp #xff1a;内核层源码 其余文件说明…EtherCATBridge示例讲解 文章目录 EtherCATBridge示例讲解结构说明代码说明 项目打开请查看【BaseFunction精讲】。 结构说明 EtherCATBridge.h 数据定义 EtherCATBridge.cpp 应用层源码 EtherCATBridge_dll.cpp 内核层源码 其余文件说明请查看【BaseFunction精讲】中的结构说明。 ps : 内核层中的数据、结构体需要一字节对齐需要以MT方式构建 代码说明 EtherCATBridge.h 内核层和应用层共用此文件方便通过共享内存进行数据交换 /* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. *///############################################################################################################## // // 文件: EtherCATBridge.h // // 模块: EtherCAT模块, 时钟模块, 网络模块, 实时模块 // // 描述: 用户空间应用程序和内核空间 DLL 之间的共享定义例如 通过直接访问 EtherCAT 进行简单的桥接重映射流程和数据交换 // // 创建人: t.pet 2009-08-26 // //##############################################################################################################/**\| *** 免责声明 *** || || 本代码仅是示例程序您可以随意使用我们不承担任何法律责任 || |\**///############################################################################################################## // // 目的: // // 本示例介绍如何配置和使用 EL6692 型 EtherCAT 网桥。 // // 在此示例中 EL6692 的主站设备和从站设备处于相同的拓扑结构中。 // 为此请将 EL6692 连接到耦合器上并将耦合器的输出插头与 EL6692 的输入插头连接起来。如下图所示 // // -------------- // ------------------- | EK1100|EL6692| // | | | In | | // | PC 运行着Kithara | |-- | | // | |----------|| | | In | // | EtherCAT主站 | |-- | -- | // | | | | | | |--- // ------------------- |-- | -- | | // ---|| | | -- | | // | |-- | | | | | // | | Out | -- | | // | | | Out | | // | | | | | // | -------------- | // | | // ------------------------- // 网络拓扑结构 // // 在成功枚举出从属设备后一级从站 EL6692 被配置为具有两个输出和一个输入二级从站 EL6692 被配置为具有一个输出和两个输入。 // 请注意一级从站从站和二级从站从站的配置输入和输出必须首尾相连。 // // 二级从站从站的两个输出将作为二级从站从站的两个输入。 // 二级从站从站将输出其两个输入端的乘积而这两个输入端将成为一级从站的单个输入端。 // 用户可以更改一级从站两个输出端 二级从站的输入端的输出值这些值将与一级从站的输入端 二级从站输入端1 x 二级从站输入端2 二级从站输出端一起显示。 // //###############################################################################################################ifndef __SMP_ETHERCATBRIDGE_H #define __SMP_ETHERCATBRIDGE_H#include ../_KitharaSmp/_KitharaSmp.h//-------------------------------------------------------------------------------------------------------------- // SharedData 是一个用户定义的参数结构用于在内核 DLL 和用户应用程序之间使用共享内存进行信息交换。 // 您可以自由定义任何与系统位大小无关的参数。 //--------------------------------------------------------------------------------------------------------------struct SharedData {KSHandle hKernel; // 内核的句柄KSHandle hAdapter; // 网络适配器的句柄KSHandle hMaster; // EtherCAT 主站的句柄KSHandle hPrimarySlave; // 一级从站的句柄KSHandle hPrimaryDataSet; // 用于与包含一级从站的拓扑结构进行数据交换的 DataSet 的句柄KSHandle hPrimarySendCallBack; // 由 hPrimaryTimer 调用的回调函数的句柄KSHandle hPrimaryReceiveCallBack; // 当 DataSet 从一级从站返回时将被调用的回调函数的句柄KSHandle hPrimaryTimer; // 用于触发从主站到一级从站的 DataSet 传输的定时器的句柄KSError primarySlaveError; // 一级从站用于从内核空间 DLL 向用户空间应用程序传递错误信息KSHandle hSecondarySlave; // 二级从站的句柄KSHandle hSecondaryDataSet; // 用于与包含二级从站的拓扑结构进行数据交换的 DataSet 的句柄KSHandle hSecondarySendCallBack; // 由 hSecondaryTimer 调用的回调函数的句柄KSHandle hSecondaryReceiveCallBack; // 当 DataSet 从二级从站返回时将被调用的回调函数的句柄KSHandle hSecondaryTimer; // 用于触发从主站到二级从站的 DataSet 传输的定时器的句柄KSError secondarySlaveError; // 二级从站用于从内核空间 DLL 向用户空间应用程序传递错误信息KSHandle hPrimaryDataSentEvent; // 用于通知应用程序 DataSet 已发送到一级从站的事件ushort primaryOutput1; // 将被复制到一级从站的过程数据中ushort primaryOutput2; // 将被复制到一级从站的过程数据中uint primaryInput; // 将从一级从站的过程数据中复制过来 }; #endif // __SMP_ETHERCATBRIDGE_H EtherCATBridge.cpp 应用层源码 /* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. *///############################################################################################################## // // 文件: EtherCATBridge.cpp // // 模块: EtherCAT模块, 时钟模块, 网络模块, 实时模块 // // 描述: 用户空间应用程序和内核空间 DLL 之间的共享定义例如 通过直接访问 EtherCAT 进行简单的桥接重映射流程和数据交换 // // 创建人: t.pet 2009-08-26 // //##############################################################################################################/**\| *** 免责声明 *** || || 本代码仅是示例程序您可以随意使用我们不承担任何法律责任 || |\**///############################################################################################################## // // 目的: // // 本示例介绍如何配置和使用 EL6692 型 EtherCAT 网桥。 // // 在此示例中 EL6692 的主站设备和从站设备处于相同的拓扑结构中。 // 为此请将 EL6692 连接到耦合器上并将耦合器的输出插头与 EL6692 的输入插头连接起来。如下图所示 // // -------------- // ------------------- | EK1100|EL6692| // | | | In | | // | PC 运行着Kithara | |-- | | // | |----------|| | | In | // | EtherCAT主站 | |-- | -- | // | | | | | | |--- // ------------------- |-- | -- | | // ---|| | | -- | | // | |-- | | | | | // | | Out | -- | | // | | | Out | | // | | | | | // | -------------- | // | | // ------------------------- // 网络拓扑结构 // // 在成功枚举出从属设备后一级从站 EL6692 被配置为具有两个输出和一个输入二级从站 EL6692 被配置为具有一个输出和两个输入。 // 请注意一级从站从站和二级从站从站的配置输入和输出必须首尾相连。 // // 二级从站从站的两个输出将作为二级从站从站的两个输入。 // 二级从站从站将输出其两个输入端的乘积而这两个输入端将成为一级从站的单个输入端。 // 用户可以更改一级从站两个输出端 二级从站的输入端的输出值这些值将与一级从站的输入端 二级从站输入端1 x 二级从站输入端2 二级从站输出端一起显示。 // //##############################################################################################################//-------------------------------------------------------------------------------------------------------------- // 为了在主程序用户层和内核 DLL 之间共享数据结构的定义我们使用了一个通用的头文件。 //--------------------------------------------------------------------------------------------------------------#include EtherCATBridge.h//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // 别忘了输入你的序列号6位客户编号这是打开驱动程序所必需的。 // // 如果你使用Demo版本也可以使用“DEMO”代替。 // 如果你使用Beta版本也可以使用“BETA”代替。 // //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!// 如上说所定义的客户号 const char _pCustomerNumber[] DEMO;// 主程序入口 void runSample() {outputTxt(***** Kithara example program EtherCATBridge *****);KSError ksError;// 错误码定义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 ? // 根据系统位数加载内核DllEtherCATBridge_64.dll : EtherCATBridge_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;}// 查询并展示所有受支持的网络适配器char pDeviceName[256]; // 用于保存设备名称outputTxt( );outputTxt(Following network adapters found:);for (int i 0; ; i) { // KS_enumDevices()可以用于查询分配给Kithara驱动程序的所有网络适配器的名称。ksError KS_enumDevices(NET, // NET 代表搜索网络设备i, // 从0开始的枚举索引号pDeviceName, // 返回设备名称KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {if (KSERROR_CODE(ksError) ! KSERROR_DEVICE_NOT_FOUND)outputErr(ksError, KS_enumDevices, Unable to query network device name!);if (KSERROR_CODE(ksError) KSERROR_DEVICE_NOT_FOUND !i) {outputTxt(No network adapters found);outputTxt( );KS_closeDriver();return;}break;}// 输出索引号对应的设备名称outputDec(i, , : , false);outputTxt(pDeviceName);}outputTxt( );// 输入想要打开的适配器索引号outputTxt(Attention!);outputTxt(By selecting a device its Windows driver gets removed and replaced by the );outputTxt(appropriate Kithara driver. This will render the network device for the duration);outputTxt(of this sample invisible to Windows.);outputTxt(Be sure that all other Applications using that device are closed right now!);// 输入并保存索引号并根据索引和再次获取设备名称int deviceIndex inputDec(Device number: , 0);ksError KS_enumDevices(NET, // NET 代表搜索网络设备deviceIndex, // 选择的设备索引号pDeviceName, // 返回设备名称KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {outputErr(ksError, KS_enumDevices, Unable to query selected network device name!);KS_closeDriver();return;}outputTxt(Selected device: , false);outputTxt(pDeviceName);outputTxt( );// 根据设备名称打开以太网适配器。ksError KS_openNetworkAdapter(pApp-hAdapter, // 获取适配器句柄pDeviceName, // 输入适配器的硬件IDNULL, // 设配器配置选项KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {outputErr(ksError, KS_openNetworkAdapter, Failed to open network adapter!);KS_closeDriver();return;}// 创建主站// 输入ESI文件文件夹路径ESI文件可以在大多数设备官网中获取。 char* pXmlPath inputTxt(Please enter config path to XML files: , C:\\Program Files\\Kithara\\RealTime Suite Demo\\xml); ksError KS_createEcatMaster(pApp-hMaster, // 返回主站句柄pApp-hAdapter, // 适配器句柄pXmlPath, // ESI文件夹路径, // 拓扑文件KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {outputErr(ksError, KS_createEcatMaster, Failed to create EtherCAT master!);KS_closeDriver();return;}//------------------------------------------------------------------------------------------------------------// 显式调用初始化函数。// 调用内核的【_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;}//------------------------------------------------------------------------------------------------------------// 主程序循环。//------------------------------------------------------------------------------------------------------------outputTxt( );outputTxt(Press 1 to change value1, 2 for value2, x for exit.);outputTxt( );bool exitSample false;while (!exitSample) {ushort lastPrimaryOutput1 0;ushort lastPrimaryOutput2 0;uint lastPrimaryInput 1;do {if (lastPrimaryOutput1 ! pApp-primaryOutput1 ||lastPrimaryOutput2 ! pApp-primaryOutput2 ||lastPrimaryInput ! pApp-primaryInput) {outputDec(pApp-primaryOutput1, value1 , | , false);outputDec(pApp-primaryOutput2, value2 , | , false);outputDec(pApp-primaryInput, value1 * value2 , \r, false);lastPrimaryOutput1 pApp-primaryOutput1;lastPrimaryOutput2 pApp-primaryOutput2;lastPrimaryInput pApp-primaryInput;}} while ((pApp-primarySlaveError KS_OK) (pApp-secondarySlaveError KS_OK) !myKbhit());if (pApp-primarySlaveError ! KS_OK)ksError pApp-primarySlaveError;else if (pApp-secondarySlaveError ! KS_OK)ksError pApp-secondarySlaveError;if (ksError ! KS_OK) {outputErr(ksError, , An error occurred during data exchange!);break;}outputTxt(\r \r, false);switch(myGetch()) {case x:case X:exitSample true;break;case 1:pApp-primaryOutput1 inputHex(Enter a new hexadecimal value for value1: );break;case 2:pApp-primaryOutput2 inputHex(Enter a new hexadecimal value for value2: );break;}//----------------------------------------------------------------------------------------------------------// 等待我们的数据被发送。//----------------------------------------------------------------------------------------------------------ksError KS_waitForEvent(pApp-hPrimaryDataSentEvent, // 事件句柄KSF_NO_FLAGS, // 无标记10 * ms); // 超时以100纳秒为单位。0 无穷大if (ksError ! KS_OK) {outputErr(ksError, KS_waitForEvent, Failed to wait for the data-sent-event!);break;}}outputTxt( );//------------------------------------------------------------------------------------------------------------// 清理内核层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 EtherCATBridge.); } EtherCATBridge_dll.cpp /* Copyright (c) 2009-2024 by Kithara Software GmbH. All rights reserved. *///############################################################################################################## // // 文件: EtherCATBridge_dll.cpp // // 模块: EtherCAT模块, 时钟模块, 网络模块, 实时模块 // // 描述: 用户空间应用程序和内核空间 DLL 之间的共享定义例如 通过直接访问 EtherCAT 进行简单的桥接重映射流程和数据交换 // // 创建人: t.pet 2009-08-26 // //##############################################################################################################/**\| *** 免责声明 *** || || 本代码仅是示例程序您可以随意使用我们不承担任何法律责任 || |\**///############################################################################################################## // // 目的: // // 本示例介绍如何配置和使用 EL6692 型 EtherCAT 网桥。 // // 在此示例中 EL6692 的主站设备和从站设备处于相同的拓扑结构中。 // 为此请将 EL6692 连接到耦合器上并将耦合器的输出插头与 EL6692 的输入插头连接起来。如下图所示 // // -------------- // ------------------- | EK1100|EL6692| // | | | In | | // | PC 运行着Kithara | |-- | | // | |----------|| | | In | // | EtherCAT主站 | |-- | -- | // | | | | | | |--- // ------------------- |-- | -- | | // ---|| | | -- | | // | |-- | | | | | // | | Out | -- | | // | | | Out | | // | | | | | // | -------------- | // | | // ------------------------- // 网络拓扑结构 // // 在成功枚举出从属设备后一级从站 EL6692 被配置为具有两个输出和一个输入二级从站 EL6692 被配置为具有一个输出和两个输入。 // 请注意一级从站从站和二级从站从站的配置输入和输出必须首尾相连。 // // 二级从站从站的两个输出将作为二级从站从站的两个输入。 // 二级从站从站将输出其两个输入端的乘积而这两个输入端将成为一级从站的单个输入端。 // 用户可以更改一级从站两个输出端 二级从站的输入端的输出值这些值将与一级从站的输入端 二级从站输入端1 x 二级从站输入端2 二级从站输出端一起显示。 // //##############################################################################################################//-------------------------------------------------------------------------------------------------------------- // 为了在主程序用户层和内核 DLL 之间共享数据结构的定义我们使用了一个通用的头文件。 //--------------------------------------------------------------------------------------------------------------#include EtherCATBridge.h// 共享内存用于在内核层 DLL 和用户层的应用程序之间共享数据。 SharedData* _pSys NULL;//-------------------------------------------------------------------------------------------------------------- // 用于映射一级从站设备过程数据的变量。 //--------------------------------------------------------------------------------------------------------------ushort *_primaryOutput1; ushort *_primaryOutput2; uint *_primaryInput;//-------------------------------------------------------------------------------------------------------------- // 用于映射二级从站过程数据的变量。 //--------------------------------------------------------------------------------------------------------------uint *_secondaryOutput; ushort *_secondaryInput1; ushort *_secondaryInput2;//-------------------------------------------------------------------------------------------------------------- // 前置声明定时器回调、数据集回调声明在文件末尾定义的回调函数。 //--------------------------------------------------------------------------------------------------------------KSError __stdcall primarySendCallBack(void* /*pArgs*/, void* /*pContext*/); KSError __stdcall primaryReceiveCallBack(void* /*pArgs*/, void* /*pContext*/); KSError __stdcall secondarySendCallBack(void* /*pArgs*/, void* /*pContext*/); KSError __stdcall secondaryReceiveCallBack(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;//------------------------------------------------------------------------------------------------------------// 在这里我们等待主站连接到拓扑。// 代替轮询主站状态您也可以注册一个回调来处理此事件。// 详情请参阅手册中的 KS_installEcatHandler()。//------------------------------------------------------------------------------------------------------------KSEcatMasterState masterState;masterState.structSize sizeof(KSEcatMasterState); // 不要忘记初始化 structSizefor (int i 0; i 50; i) {ksError KS_queryEcatMasterState(_pSys-hMaster, // 主站句柄masterState, // 返回KSEcatMasterState 结构体KSF_NO_FLAGS); // 无标志if (ksError ! KS_OK)return ksError;if (masterState.connected)break;KS_microDelay(100 * ms);}if (masterState.connected 0)return KSERROR_CATEGORY_ETHERCAT;//------------------------------------------------------------------------------------------------------------// 通过指定供应商和产品 ID 创建主从站。// 只有在所附拓扑中找到从属设备函数才会成功执行。//------------------------------------------------------------------------------------------------------------ksError KS_createEcatSlave(_pSys-hMaster, // 主站句柄_pSys-hPrimarySlave, // 返回从站句柄0, // ID (0 任意)0, // 从站位置 (0 任意)0x00000002, // 厂商 ID (2 Beckhoff)0x1a243052, // 产品 ID (0x1a243052 EL6692)0, // 版本 (0 任意)KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 通过指定供应商和产品 ID 创建二级从站设备。// 一级从机在此阶段已经连接因此此调用将不再处理它。//------------------------------------------------------------------------------------------------------------ksError KS_createEcatSlave(_pSys-hMaster, // 主站句柄_pSys-hSecondarySlave, // 返回从站句柄0, // ID (0 任意)0, // 从站位置 (0 任意)0x00000002, // 厂商 ID (2 Beckhoff)0x1a243052, // 产品 ID (0x1a243052 EL6692)0, // 版本 (0 任意)KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 为了配置从站我们需要让它们进入 PREOP 状态。通过使用主站句柄调用 KS_changeEcatState()// 拓扑中创建的所有从站也都会进入 PREOP 状态。//------------------------------------------------------------------------------------------------------------ksError KS_changeEcatState(_pSys-hMaster, // 主站句柄KS_ECAT_STATE_PREOP, // 切换状态类型KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 通过调用 KS_setEcatPdoMapping()我们可以配置从站的输入和输出。// 对于一级从机我们希望有两个输出和一个输入。// 第一步是重置输出和输入的 PDO。//------------------------------------------------------------------------------------------------------------ksError KS_setEcatPdoMapping(_pSys-hPrimarySlave, // 从站句柄0x1600, // 输出PDO的索引-1, // 要映射的条目-1表示重置此PDO0, // 子索引未使用0, // 位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hPrimarySlave, // 从站句柄0x1A00, // 输入PDO的索引-1, // 要映射的条目-1表示重置此PDO0, // 子索引未使用0, // 位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 现在为两个输出和一个输入配置给一级从站。// KS_setEcatPdoMapping() 以增量方式工作每次调用都会向指定的 PDO 添加一个变量。// 输出配置为 16 位宽输入配置为 32 位宽。//------------------------------------------------------------------------------------------------------------ksError KS_setEcatPdoMapping(_pSys-hPrimarySlave, // 从站句柄0x1600, // 输出PDO的索引0x7000, // 要映射的条目1, // 子索引16, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hPrimarySlave, // 从站句柄0x1600, // 输出PDO的索引0x7000, // 要映射的条目2, // 子索引16, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hPrimarySlave, // 从站句柄0x1A00, // 输入PDO的索引0x6000, // 要映射的条目1, // 子索引32, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 现在通过重置 PDO将二级从站设备配置为一个输出端和两个输入端。//------------------------------------------------------------------------------------------------------------ksError KS_setEcatPdoMapping(_pSys-hSecondarySlave, // 从站句柄次级从站0x1600, // 输出PDO的索引-1, // 要映射的条目-1表示重置此PDO0, // 子索引未使用0, // 位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hSecondarySlave, // 从站句柄次级从站0x1A00, // 输入PDO的索引-1, // 要映射的条目-1表示重置此PDO0, // 子索引未使用0, // 位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 现在将二级从站配置为一个输出和两个输入。// 输出配置为 32 位宽输入配置为 16 位宽。//------------------------------------------------------------------------------------------------------------ksError KS_setEcatPdoMapping(_pSys-hSecondarySlave, // 从站句柄二级从站0x1600, // 输出PDO的索引0x7000, // 要映射的条目1, // 子索引32, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hSecondarySlave, // 从站句柄二级从站0x1A00, // 输入PDO的索引0x6000, // 要映射的条目1, // 子索引16, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_setEcatPdoMapping(_pSys-hSecondarySlave, // 从站句柄二级从站0x1A00, // 输入PDO的索引0x6000, // 要映射的条目2, // 子索引16, // 位长度KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 为了显示一级从站和二级从站是独立的我们创建了两个数据集每个从站一个。//------------------------------------------------------------------------------------------------------------ksError KS_createEcatDataSet(_pSys-hMaster, // 主站句柄_pSys-hPrimaryDataSet, // 用于写入新数据集句柄的地址NULL, // 数据集数据的应用层指针未使用NULL, // 数据集数据的内核层指针未使用KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;ksError KS_createEcatDataSet(_pSys-hMaster, // 主站句柄_pSys-hSecondaryDataSet, // 用于写入新数据集句柄的地址NULL, // 数据集数据的应用层指针未使用NULL, // 数据集数据的内核层指针未使用KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 创建数据集后我们为每个数据集分配一个从数据集以便能够访问它们的流程数据。//------------------------------------------------------------------------------------------------------------ksError KS_assignEcatDataSet(_pSys-hPrimaryDataSet, // 数据集句柄_pSys-hPrimarySlave, // 从站句柄KS_ECAT_SYNC_ALL, // 同步对象0, // 数据集中的特殊位置KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;ksError KS_assignEcatDataSet(_pSys-hSecondaryDataSet, // 数据集句柄_pSys-hSecondarySlave, // 从站句柄KS_ECAT_SYNC_ALL, // 同步对象0, // 数据集中的特殊位置KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 映射一级从机的过程数据。//------------------------------------------------------------------------------------------------------------ksError KS_getEcatDataObjAddress(_pSys-hPrimaryDataSet, // 数据集句柄_pSys-hPrimarySlave, // 从站句柄0x1600, 0, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_primaryOutput1, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_getEcatDataObjAddress(_pSys-hPrimaryDataSet, // 数据集句柄_pSys-hPrimarySlave, // 从站句柄0x1600, 1, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_primaryOutput2, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_getEcatDataObjAddress(_pSys-hPrimaryDataSet, // 数据集句柄_pSys-hPrimarySlave, // 从站句柄0x1A00, 0, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_primaryInput, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 初始化一级从站在共享内存中的过程数据。//------------------------------------------------------------------------------------------------------------_pSys-primarySlaveError KS_OK;_pSys-secondarySlaveError KS_OK;*_primaryOutput1 0;_pSys-primaryOutput1 0;*_primaryOutput2 0;_pSys-primaryOutput2 0;//------------------------------------------------------------------------------------------------------------// 映射二级从站的过程数据。//------------------------------------------------------------------------------------------------------------ksError KS_getEcatDataObjAddress(_pSys-hSecondaryDataSet, // 数据集句柄_pSys-hSecondarySlave, // 从站句柄0x1A00, 0, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_secondaryInput1, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_getEcatDataObjAddress(_pSys-hSecondaryDataSet, // 数据集句柄_pSys-hSecondarySlave, // 从站句柄0x1A00, 1, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_secondaryInput2, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_getEcatDataObjAddress(_pSys-hSecondaryDataSet, // 数据集句柄_pSys-hSecondarySlave, // 从站句柄0x1600, 0, // 目标对象的索引和子索引NULL, // 数据应用层指针的地址未使用(void**)_secondaryOutput, // 数据内核层指针的地址NULL, NULL, // 位偏移和位长度未使用KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 实际上开始通信的第一步是将主站状态切换至SAFEOP。//------------------------------------------------------------------------------------------------------------ksError KS_changeEcatState(_pSys-hMaster, // 主站句柄KS_ECAT_STATE_SAFEOP, // 切换状态类型KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 我们将使用一个事件来通知应用程序一级从站数据集的传输情况。//------------------------------------------------------------------------------------------------------------ksError KS_createEvent(_pSys-hPrimaryDataSentEvent, // 返回一个事件句柄NULL, // 事件名称可忽略KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------ // 在本示例中我们需要使用四个回调函数。 // 第一个回调函数将由 hPrimaryTimer 触发用于发送包含一级从站过程数据的 hPrimaryDataSet 到其拓扑。 //------------------------------------------------------------------------------------------------------------ksError KS_createCallBack(_pSys-hPrimarySendCallBack, // 用于写入新回调句柄的地址primarySendCallBack, // 回调函数NULL, // 回调函数的参数未使用KSF_DIRECT_EXEC, // 标志此处为内核级别0); // 优先级在内核级别未使用 if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------ // 第二个回调函数将在接收包含一级从站过程数据的 hPrimaryDataSet 从拓扑返回时触发。 //------------------------------------------------------------------------------------------------------------ksError KS_createCallBack(_pSys-hPrimaryReceiveCallBack, // 用于写入新回调句柄的地址primaryReceiveCallBack, // 回调函数NULL, // 回调函数的参数未使用KSF_DIRECT_EXEC, // 标志此处为内核级别0); // 优先级在内核级别未使用 if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------ // 第三个回调函数将由 hSecondaryTimer 触发用于发送包含二级从站过程数据的 hSecondaryDataSet 到其拓扑。 //------------------------------------------------------------------------------------------------------------ksError KS_createCallBack(_pSys-hSecondarySendCallBack, // 用于写入新回调句柄的地址secondarySendCallBack, // 回调函数NULL, // 回调函数的参数未使用KSF_DIRECT_EXEC, // 标志此处为内核级别0); // 优先级在内核级别未使用 if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------ // 第四个回调函数将在接收包含二级从站过程数据的 hSecondaryDataSet 从拓扑返回时触发。 //------------------------------------------------------------------------------------------------------------ksError KS_createCallBack(_pSys-hSecondaryReceiveCallBack, // 用于写入新回调句柄的地址secondaryReceiveCallBack, // 回调函数NULL, // 回调函数的参数未使用KSF_DIRECT_EXEC, // 标志此处为内核级别0); // 优先级在内核级别未使用 if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------ // 将回调函数附加到它们的信号上。 //------------------------------------------------------------------------------------------------------------ksError KS_createTimer(_pSys-hPrimaryTimer, // 用于写入新定时器句柄的地址1 * ms, // 定时器周期单位为 100 纳秒_pSys-hPrimarySendCallBack, // 回调句柄KSF_REALTIME_EXEC); // 标志此处为高精度实时定时器 if (ksError ! KS_OK)return ksError;ksError KS_createTimer(_pSys-hSecondaryTimer, // 用于写入新定时器句柄的地址1 * ms, // 定时器周期单位为 100 纳秒_pSys-hSecondarySendCallBack, // 回调句柄KSF_REALTIME_EXEC); // 标志此处为高精度实时定时器 if (ksError ! KS_OK)return ksError;ksError KS_installEcatHandler(_pSys-hPrimaryDataSet, // 数据集句柄KS_DATASET_SIGNAL, // 事件代码_pSys-hPrimaryReceiveCallBack, // 回调句柄KSF_NO_FLAGS); // 标志未使用 if (ksError ! KS_OK)return ksError;ksError KS_installEcatHandler(_pSys-hSecondaryDataSet, // 数据集句柄KS_DATASET_SIGNAL, // 事件代码_pSys-hSecondaryReceiveCallBack, // 回调句柄KSF_NO_FLAGS); // 标志未使用 if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 一切都设置好了。现在将总线状态切入OP。//------------------------------------------------------------------------------------------------------------ksError KS_changeEcatState(_pSys-hMaster, // 主站句柄KS_ECAT_STATE_OP, // 状态KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;return KS_OK; }//-------------------------------------------------------------------------------------------------------------- // 这是一个清理函数用于关闭 EtherCAT 主站、EtherCAT 从站和网络设备、 删除数据集、定时器和回调并卸载处理程序。 //--------------------------------------------------------------------------------------------------------------extern C KSError __declspec(dllexport) __stdcall _exitFunction(void* /*pArgs*/, void* /*pContext*/) {if (_pSys NULL) // 共享内存未映射return KSERROR_FUNCTION_NOT_AVAILABLE; // _initFunction 未调用KSError ksError;// 关闭ksError KS_changeEcatState(_pSys-hDataSet, // 数据集句柄KS_ECAT_STATE_SAFEOP, // 状态KSF_NO_FLAGS); // 无标志if (ksError ! KS_OK)return ksError;// 停止定时器。ksError KS_stopTimer(_pSys-hPrimaryTimer); // 定时器句柄if (ksError ! KS_OK)return ksError;ksError KS_stopTimer(_pSys-hSecondaryTimer); // 定时器句柄if (ksError ! KS_OK)return ksError;// 切换 SAFEOPksError KS_changeEcatState(_pSys-hDataSet, // DataSet 句柄KS_ECAT_STATE_INIT, // 状态KSF_NO_FLAGS); // 无标志if (ksError ! KS_OK)return ksError;// 移除定时器ksError KS_removeTimer(_pSys-hPrimaryTimer); // 定时器句柄if (ksError ! KS_OK)return ksError;ksError KS_removeTimer(_pSys-hSecondaryTimer); // 定时器句柄if (ksError ! KS_OK)return ksError;// 卸载数据集处理器ksError KS_installEcatHandler(_pSys-hPrimaryDataSet, // 数据集句柄KS_DATASET_SIGNAL, // 事件代码KS_INVALID_HANDLE, // 无效句柄用于卸载KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;ksError KS_installEcatHandler(_pSys-hSecondaryDataSet, // 数据集句柄KS_DATASET_SIGNAL, // 事件代码KS_INVALID_HANDLE, // 无效句柄用于卸载KSF_NO_FLAGS); // 标志未使用if (ksError ! KS_OK)return ksError;// 移除回调ksError KS_removeCallBack(_pSys-hPrimarySendCallBack); // 回调句柄if (ksError ! KS_OK)return ksError;ksError KS_removeCallBack(_pSys-hPrimaryReceiveCallBack); // 回调句柄if (ksError ! KS_OK)return ksError;ksError KS_removeCallBack(_pSys-hSecondarySendCallBack); // 回调句柄if (ksError ! KS_OK)return ksError;ksError KS_removeCallBack(_pSys-hSecondaryReceiveCallBack); // 回调句柄if (ksError ! KS_OK)return ksError;// 删除数据集ksError KS_deleteEcatDataSet(_pSys-hPrimaryDataSet); // 数据集句柄if (ksError ! KS_OK)return ksError;ksError KS_deleteEcatDataSet(_pSys-hSecondaryDataSet); // 数据集句柄if (ksError ! KS_OK)return ksError;// 删除EtherCAT从站ksError KS_deleteEcatSlave(_pSys-hPrimarySlave); // 从站句柄if (ksError ! KS_OK)return ksError;ksError KS_deleteEcatSlave(_pSys-hSecondarySlave); // 从站句柄if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 关闭EtherCAT主站//------------------------------------------------------------------------------------------------------------ksError KS_closeEcatMaster(_pSys-hMaster); // 主站句柄if (ksError ! KS_OK)return ksError;//------------------------------------------------------------------------------------------------------------// 关闭网络适配器//------------------------------------------------------------------------------------------------------------ksError KS_closeNetwork(_pSys-hAdapter, // 适配器句柄KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)return ksError;return KS_OK; }//-------------------------------------------------------------------------------------------------------------- // 该回调触发主从机数据集的数据交换。 // 它将一级从站设备的两个输出值从共享内存复制到进程数据中并在每次被定时器触发时将 DataSet 发送到拓扑中。 // 之后它会通过设置事件通知应用程序发送成功。 //--------------------------------------------------------------------------------------------------------------KSError __stdcall primarySendCallBack(void* /*pArgs*/, void* /*pContext*/) {KSError ksError;if (_pSys-primarySlaveError ! KS_OK)return _pSys-primarySlaveError;//------------------------------------------------------------------------------------------------------------// 在发送 DataSet 之前将所需的输出值从共享内存复制出来。//------------------------------------------------------------------------------------------------------------*_primaryOutput1 _pSys-primaryOutput1;*_primaryOutput2 _pSys-primaryOutput2;ksError KS_postEcatDataSet(_pSys-hPrimaryDataSet, // 数据集句柄KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {_pSys-primarySlaveError ksError;return ksError;}ksError KS_setEvent(_pSys-hPrimaryDataSentEvent); // 事件句柄if (ksError ! KS_OK)_pSys-primarySlaveError ksError;return ksError; }//-------------------------------------------------------------------------------------------------------------- // 每次收到一级从站数据集时都会调用该回调。 // 它将把输入值复制到共享内存中以便从应用程序中访问。 //--------------------------------------------------------------------------------------------------------------KSError __stdcall primaryReceiveCallBack(void* /*pArgs*/, void* /*pContext*/) {KSError ksError;if (_pSys-primarySlaveError ! KS_OK)return _pSys-primarySlaveError;ksError KS_readEcatDataSet(_pSys-hPrimaryDataSet, // 数据集句柄KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {_pSys-primarySlaveError ksError;return ksError;}//------------------------------------------------------------------------------------------------------------// 将输入的接收值存储在共享内存中。//------------------------------------------------------------------------------------------------------------_pSys-primaryInput *_primaryInput;return KS_OK; }//-------------------------------------------------------------------------------------------------------------- // 该回调将触发二级从站设备 DataSet 的数据交换。 // 它将把数据集发布到包含二级从站设备的拓扑中。 //--------------------------------------------------------------------------------------------------------------KSError __stdcall secondarySendCallBack(void* /*pArgs*/, void* /*pContext*/) {KSError ksError;if (_pSys-secondarySlaveError ! KS_OK)return _pSys-secondarySlaveError;ksError KS_postEcatDataSet(_pSys-hSecondaryDataSet, // 数据集句柄KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK)_pSys-secondarySlaveError ksError;return ksError; }//-------------------------------------------------------------------------------------------------------------- // 每次收到二级从站 DataSet 时都会调用该回调。 // 在这里我们通过将输出设置为输入 1 * 输入 2 来完成二级从站设备的工作。 // 当 secondarySlave.input1 primarySlave.output1 和 secondarySlave.input2 primarySlave.output2 时 //--------------------------------------------------------------------------------------------------------------KSError __stdcall secondaryReceiveCallBack(void* /*pArgs*/, void* /*pContext*/) {KSError ksError;if (_pSys-secondarySlaveError ! KS_OK)return _pSys-secondarySlaveError;ksError KS_readEcatDataSet(_pSys-hSecondaryDataSet, // 数据集句柄KSF_NO_FLAGS); // 无标记if (ksError ! KS_OK) {_pSys-secondarySlaveError ksError;return ksError;}//------------------------------------------------------------------------------------------------------------// 根据输入计算输出。// 想要的输出值将在下一次迭代 secondarySendCallBack 时设置。//------------------------------------------------------------------------------------------------------------*_secondaryOutput (*_secondaryInput1) * (*_secondaryInput2);return KS_OK; }//-------------------------------------------------------------------------------------------------------------- // 需要实现 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; }
http://www.dnsts.com.cn/news/219704.html

相关文章:

  • 新的网站的建设步骤如何自己制作游戏软件
  • 网站布局规范网站搭建费用计入什么科目
  • 六安网站关键词排名优化地址手机网站菜单设计模板
  • 域名做非法网站便民的网站app怎么做
  • 中国林业建设协会网站网络推广公司 深圳
  • 泸州建设网站网页优化怎么做
  • 哪些行业没有做网站软件开发网站开发
  • 杭州网站免费制作莆田专业网站建设公司
  • 怎么改网站域名wordpress统计代码
  • 网站备案更改吗北京网络营销公司哪家好
  • 访问阿里云主机网站网络服务提供者知道或者应当知道网络用户利用
  • 404 not found网站Sql 发wordpress
  • 韩国的 电子商务网站seo在线培训机构排名
  • 阿里云代理网站怎么做济南网站假设推广
  • 杭州市建设工程交易中心seo索引擎优化
  • 中国建设银行官方招聘网站wordpress文章倒计时
  • 简单asp网站杭州网站建设开发外包公司
  • 网站正在建设中 模板常熟网站建设
  • 珠宝玉器监测网站建设方案专业seo优化费用
  • 东莞技术好的网站建设wordpress是响应式吗
  • 温岭做网站公司dw网页制作教程合集
  • 不懂代码怎么做网站建立企业网站地址
  • 网站设计中级南阳全员核酸检测
  • 有什么检索标准的网站如何购买域名
  • 那些做刷客的网站网站备案名称规定
  • 微云影视自助建站系统免费查企业哪个软件最好
  • 上海网站备案核验单状态查询企业公司建设网站
  • 廊坊电商网站建设东莞东城网站建设公司
  • 做网站到哪里接单网站开发国际化
  • 网站编写教程四川省网站建设