设备通讯2--C/C++语言开发2
从BT-BASIC直接调用用户函数会因BT-BASIC与ATL频繁交互增加复杂度,推荐优先从ATL中调用。开发UCI服务器需安装兼容的C/C++开发工具,且编译时必须链接uciapi.lib库文件。UCI服务器程序的main函数格式标准化,核心流程为「创建服务器→注册函数→处理调用→关闭服务器」。rcall语句调用的函数名是注册的别名,而非C/C++程序中的原始函数名。
设备通讯2–C/C++语言开发2
文章目录
基于C/C++的UCI仪器服务器开发
注意:开发UCI服务器前,必须在系统上安装C/C++软件开发工具包。
C/C++开发环境并非Medalist在线测试系统控制器的标配组件。安捷伦已完成兼容性测试的工具包括:
- Microsoft Visual Studio(官网地址:msdn.microsoft.com/vstudio)
- LCC-Win32(官网地址:www.cs.virginia.edu/~lcc-win32/)
其他C/C++开发工具包也可能正常工作,但尚未在Medalist在线测试系统上完成验证。
通用C接口(UCI)是一款仪器服务器,配套提供相应软件工具,支持从BT-BASICtestplan与模拟测试中,调用C/C++编写的用户自定义函数。UCI包含一套供C/C++服务器程序调用的API(应用程序接口)函数库,所有API函数均以uci为前缀,便于识别与使用。
本节将介绍如何使用C/C++编写的用户自定义函数,控制连接在测试系统上的外部仪器,涵盖以下内容:
- UCI服务器文件的创建流程
- 可执行UCI服务器程序示例
- 可执行UCI服务器程序的编译与生成
关于C/C++软件的详细用法及安装说明,请参考配套的软件官方文档。
UCI服务器文件的创建流程
使用C/C++函数控制外部仪器的板卡测试程序,必须访问UCI服务器与对应的用户自定义函数集。UCI服务器与其附带的用户自定义函数,共同构成一个完整的C/C++程序。
该程序的存储路径有两种选择:
- 存储在公共目录中,供多个板卡测试程序共享访问;
- 若该服务器程序为某一板卡测试专属,可直接存储在该板卡测试的目录下。
服务器文件的文件名可自定义,为便于识别,我们推荐将其命名为workfile.uci。UCI服务器程序启动后,将在后台持续运行,响应板卡测试程序发起的仪器调用请求。
步骤1:创建基于UCI函数库的程序
a. 编写一个独立的C/C++程序,通过调用UCI函数库,实现仪器服务器的核心功能;
b. 将用户自定义的仪器控制/测量函数整合到该程序中。
步骤2:生成可执行服务器文件
a. 编译程序
> 注意:编译器必须链接至$AgilentICT_ROOT/standard/uciapi.lib库文件,以解析UCI动态链接库($AgilentICT_ROOT/bin/uciapi.dll)中的API调用。请确保编译过程的链接器(linker)配置中,包含uciapi.lib文件的路径。
b. 保存可执行文件
将编译生成的UCI服务器可执行文件,保存为对应板卡测试目录下的workfile.uci。
若该服务器需被多个板卡测试程序访问,可将其保存到更易被所有测试程序访问的公共目录中。
步骤3:修改testplan
a. 修改testplan代码,确保在testplan启动时启动UCI服务器,在testplan结束时终止UCI服务器;
b. 修改模拟测试程序,必要时同时修改testplan,在板卡测试的对应环节调用用户自定义函数。
可执行程序示例
以下示例文件位于目录$AgilentICT_ROOT/standard/servers下:
ucisample1:可执行BT-BASIC程序,演示如何调用C/C++用户自定义函数进行数据处理;ucisample1.c:包含ucisample1调用的用户自定义函数的C/C++程序。
这些示例也将在可执行UCI服务器程序示例中完整列出。
可执行UCI服务器程序示例
示例8 是一个完整的C/C++编写的UCI服务器程序,展示了典型UCI服务器的程序结构,以及其在板卡测试中的应用方式,同时也可作为你编写自定义服务器程序的模板。
该程序实现了两个简单的函数:UserFunc1与UserFunc2。在C/C++程序之前,附带了可在testplan中调用该服务器的BT-BASIC与ATL语句。
相关程序与语句文件可在以下路径找到:$AgilentICT_ROOT/standard/servers/ucisample1
注意:C/C++程序中的函数名,不一定与BT-BASICtestplan和模拟测试中
rcall语句使用的函数名一致。rcall语句使用的是通过uciRegisterFunction调用注册时,为函数指定的别名。例如,程序中的UserFunc1函数被注册为Func1,在rcall语句中需使用Func1来调用该函数。
示例8 可执行UCI服务器程序
! ===== BT-BASICtestplan中的代码 =====
...
rinit "U_Server";
program btgetenv$("AgilentICT_ROOT") & "/boards/my_board/workfile.uci", servicetype "UCI"
...
rcall Func1(Value_1, Value_2, Sum)
...
rcall Func2(Number, Word$)
...
rexit "U_Server"
/************ C/C++ 程序 ***************/
#include "<value in $AgilentICT_ROOT>/standard/uciapi.h"
#include <stdio.h>
/* ------------------------------------------------------------------------*/
/*
该用户自定义函数功能:读取参数1和参数2中的64位实数值,求和后将结果存入参数3返回
*/
void UserFunc1(UCIPARMHANDLE ph)
{
double num1, num2, sum;
if (UCI_SUCCESS != uciGetReal64(ph, 1, &num1)) {
uciRaiseError(ph, "Couldn't read parameter 1 in UserFunc1");
return;
}
if (UCI_SUCCESS != uciGetReal64(ph, 2, &num2)) {
uciRaiseError(ph, "Couldn't read parameter 2 in UserFunc1");
return;
}
sum = num1 + num2;
if (UCI_SUCCESS != uciSetReal64(ph, 3, sum)) {
uciRaiseError(ph, "Couldn't write parameter 3 in UserFunc1");
return;
}
}
/* ------------------------------------------------------------------------*/
/*
该用户自定义函数功能:将参数1中的64位实数值转换为字符串,存入参数2返回
*/
void UserFunc2(UCIPARMHANDLE ph)
{
double num1;
char buf[100];
if (UCI_SUCCESS != uciGetReal64(ph, 1, &num1)) {
uciRaiseError(ph, "Couldn't read parameter 1 in UserFunc2");
return;
}
if (sprintf(buf, "%g", num1) < 0) {
uciRaiseError(ph, "Error converting number to string in UserFunc2");
return;
}
if (UCI_SUCCESS != uciSetCString(ph, 2, buf)) {
uciRaiseError(ph, "Couldn't write parameter 2 in UserFunc2");
return;
}
}
/* ------------------------------------------------------------------------*/
/*
UCI服务器程序的main函数格式高度标准化,核心流程如下:
1. 创建服务器实例
2. 注册用户自定义函数
3. 处理外部的函数调用请求
4. 关闭服务器实例
5. 退出程序
*/
int main(int argc, char * argv[])
{
int errorVal = 0;
UCISERVERHANDLE sh = 0;
/* 初始化服务器实例 */
if (UCI_SUCCESS != uciCreateServer(&sh, argc, argv)) {
fprintf(stderr, "Error: Couldn't create UCI server.\n");
errorVal = 1;
goto errorexit;
}
/* 注册可用的用户自定义函数 */
if (
UCI_SUCCESS != uciRegisterFunction(sh, "Func1", UserFunc1) ||
UCI_SUCCESS != uciRegisterFunction(sh, "Func2", UserFunc2)
) {
fprintf(stderr, "Error registering functions.\n");
errorVal = 1;
goto errorexit;
}
/* 启动服务器,等待并处理外部的函数调用请求 */
if (UCI_SUCCESS != uciHandleFuncCalls(sh)) {
fprintf(stderr, "Error processing calls.\n");
errorVal = 1;
goto errorexit;
}
errorexit:
/* 关闭服务器实例,释放资源 */
if (sh != 0)
uciShutdownServer(sh);
return errorVal;
}
总结
- 从BT-BASIC直接调用用户函数会因BT-BASIC与ATL频繁交互增加复杂度,推荐优先从ATL中调用。
- 开发UCI服务器需安装兼容的C/C++开发工具,且编译时必须链接
uciapi.lib库文件。 - UCI服务器程序的
main函数格式标准化,核心流程为「创建服务器→注册函数→处理调用→关闭服务器」。 rcall语句调用的函数名是uciRegisterFunction注册的别名,而非C/C++程序中的原始函数名。
更多推荐

所有评论(0)