底层会用到visa定义的一些函数和库,visa.h;visatype.h;…;visa32.lib
这里用射频开关做了一个测试
test.h
#include "visa.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_CNT 200
#define MAX_SCPI_LENGTH 255 // 最大的SCPI命令
#define DEFAULT_TIMEOUT 5000 // 超时:5000ms
using namespace std;
typedef struct {
char in_port[4];
std::string out_port[16]; //这里对应16个输出口的 PORT input out_port\n
std::unordered_map <char, std::string> port_connect;
std::string dis_out_port; //这里只保存1个未被占用的端口 PORT input out_port\n
}PortInfo;
static ViStatus status = 0; //ViStatus接口返回值类型, VI_SUCCESS表示执行成功
static ViSession defaultRM = 0,vi; //句柄,其中vi为操作设备的句柄。
static ViUInt32 retCnt = 0;
static char bytesWrite[VI_FIND_BUFLEN] = {'\0'}; //vi写缓冲区
static char bytesRead[VI_FIND_BUFLEN] = {'\0'}; //vi读缓冲区
///初始化,设置波特率等
static void SessInit(ViSession &defaultRM);
///查找枚举USB设备,将找到的端口号和端口号对应的资源描述符组成map,方便后面操作
static void FindPort(ViSession &defaultRM, unordered_map<ViUInt16,string> &portmap);
根据用户选择的COM口userinputport来连接相应设备,连接上的设备操作句柄为vi
static void ConnectPort(ViSession &defaultRM, unordered_map<ViUInt16,string> &portmap, ViUInt16 userinputport,PortInfo &pinfo);
向设备发送IDN查询命令
static void FindIDN();
/ 向设备发送SN查询命令
static void FindSN();
// 写入SN
static void SetSN(const char* sn);
查询开关切换次数switch?\n
static void FindSwitchNum();
/***************************PORT操作相关*****************************/
/ PORT?\n 查询当前四路端口的输出口。
static void FindAllPort();
//第一次连接成功后初始化端口--->使端口默认连接上01 02 03 04 号口,并点亮对应图标。
static void InitPortInfo(PortInfo &pinfo);
//PORT input out_port\n
//比如现在要执行PORT A 01\n 需要先判断BCD端口没有连接01端口,
//假设B端口连了01端口则需给B重连一个未分配的端口
//typedef struct {
// char in_port[4];
// std::string out_port[16]; //这里对应16个输出口的 PORT input out_port\n
// std::unordered_map port_connect;
// std::string dis_out_port; //这里只保存1个未被占用的端口 PORT input out_port\n
//}PortInfo;
//这个函数用于按键触发执行 类似接通单个串口的命令,执行前增加判断逻辑
//根据不同按键触构造不同指令 eg: PORT B 01\n
static void DoPortin2out(PortInfo &pinfo);
static void DoPortin2out(PortInfo &pinfo){
// 假设初始化后(A,01)(B,02)(C,03)(d,04);现在执行 PORT B 01\n , 但是01被A占用
char do_inport('B');
string do_outport("16");
char cmd[32]={0};
//先判01 是否被占用,遍历 unordered_map
auto e = pinfo.port_connect.begin();
for(;e!=pinfo.port_connect.end();e++){
if(strcmp(e->second.c_str(),do_outport.c_str()) == 0){ //如果e对应的端口被占用
//重新构造指令进行输入
sprintf(cmd,"PORT %c %s\n",e->first,pinfo.dis_out_port.c_str());
status = viQueryf(vi, (ViConstString)cmd, "%t", bytesRead); //执行PORT A 16\n
if(status==VI_SUCCESS){
swap(pinfo.dis_out_port,pinfo.port_connect[do_inport]); //执行成功则,将原来的B-->02和未被使用的端口16交换
std::cout << "cmd1:" << cmd << bytesRead;
memset(cmd,0,sizeof(cmd));
sprintf(cmd, "PORT %c %s\n",do_inport,do_outport.c_str());//构造命令执行
status = viQueryf(vi, (ViConstString)cmd, "%t", bytesRead);//执行PORT B 01\n
if(status==VI_SUCCESS){
pinfo.port_connect[do_inport]=do_outport;//更新端口映射关系
std::cout << "cmd2:" << cmd << bytesRead;
}
return; //执行PORT B 01\n不成功
}
return; //执行PORT A 16\n不成功直接退出
}
}
//如果不存在01端口被占用情况,则直接执行即可
memset(cmd,0,sizeof(cmd));
sprintf(cmd, "PORT %c %s\n",do_inport,do_outport.c_str());//构造命令执行
status = viQueryf(vi, (ViConstString)cmd, "%t", bytesRead);
}
static void SessInit(ViSession &defaultRM){
// 设置波特率为115200
viSetAttribute(defaultRM, VI_ATTR_ASRL_BAUD, 115200);
//使用viFlush()函数清空会话缓冲区。这可以确保在配置后,所有待处理的数据都被清除
viFlush(defaultRM, VI_READ_BUF);
// 设置数据位为8位
viSetAttribute(defaultRM, VI_ATTR_ASRL_DATA_BITS, 8);
// 设置停止位为1位
viSetAttribute(defaultRM, VI_ATTR_ASRL_STOP_BITS, VI_ASRL_STOP_ONE);
// 设置无校验
viSetAttribute(defaultRM, VI_ATTR_ASRL_PARITY, VI_ASRL_PAR_NONE);
}
static void FindPort(ViSession &defaultRM, unordered_map<ViUInt16,string> &portmap){
// 枚举VISA资源
//numInst为查到的资源数量,instrResource为查到的资源描述,findList为指针,用于返回资源查找列表
ViFindList findList;
ViUInt32 numInst;
char instrResource[VI_FIND_BUFLEN];
ViUInt16 comPort[VI_FIND_BUFLEN]={0};
ViUInt16 resultCount;
status = viFindRsrc(defaultRM, "ASRL?*INSTR", &findList, &numInst, instrResource);
if (status != VI_SUCCESS) {
std::cout << "枚举已连接设备失败" << std::endl;
}
// 依次读取已连接设备的COM口号
while (numInst-- > 0 ) {
status = viParseRsrc(defaultRM, instrResource, &resultCount, comPort);
if (status == VI_SUCCESS) {
portmap.insert(make_pair(comPort[0],string(instrResource)));
}
else {
std::cout << "读取COM口号失败" << std::endl;
}
status = viFindNext(findList, instrResource);//找下一个设备
if (status != VI_SUCCESS) {
//std::cout << "找不到下一个设备" << std::endl;
break;
}
}
}
static void ConnectPort(ViSession &defaultRM, unordered_map<ViUInt16,string> &portmap,ViUInt16 userinputport,PortInfo &pinfo){
for (auto it = portmap.begin(); it != portmap.end(); ++it) {
//std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
if(it->first == userinputport){
status = viOpen (defaultRM, it->second.c_str(), VI_NULL, VI_NULL, &vi);
// 检查返回值
if (status == VI_SUCCESS) {
// 设备成功打开
printf("设备连接成功!\n");
SessInit(vi); //连接成功则初始化一下vi的设置
InitPortInfo(pinfo);//第一次连接成功后初始化端口--->使端口默认连接上01 02 03 04 号口,并点亮对应图标。
} else {
// 发生错误
printf("设备连接失败,错误码:%d\n", status);
}
}
}
}
static void FindIDN(){// 向设备发送IDN查询命令
status = viQueryf(vi, (ViConstString)"*IDN?\n", "%t", bytesRead);
if (status != VI_SUCCESS) {
std::cout << "查询IDN信息失败" << std::endl;
}
// 在缓冲区中查看接收的IDN信息
std::cout << "设备IDN信息:" << bytesRead;
}
static void FindSN(){// 向设备发送SN查询命令
memset(bytesRead,0,sizeof(bytesRead));
status = viQueryf(vi, (ViConstString)"SN?\n", "%t", bytesRead);
if (status != VI_SUCCESS) {
std::cout << "查询SN信息失败" << std::endl;
}
// 在缓冲区中查看接收的SN信息
std::cout << "设备SN信息:" << bytesRead;
}
static void SetSN(const char* sn){
ViUInt32 writeCount;
memset(bytesRead,0,sizeof(bytesRead));
status = viPrintf(vi, "WRITE_SN:%s\n", sn);
//status = viWrite(vi, (ViBuf)sn, strlen(sn), &writeCount);
if (status != VI_SUCCESS){
std::cout << "写入SN失败" << std::endl;
}
std::cout << "成功写入SN:" << sn << std::endl;
}
static void FindSwitchNum(){
memset(bytesRead,0,sizeof(bytesRead));
status = viQueryf(vi, (ViConstString)"SWITCHCNT?\n", "%t", bytesRead);
if (status != VI_SUCCESS) {
std::cout << "查询切换次数信息失败" << std::endl;
}
std::cout << "切换次数:" << bytesRead;
}
static void FindAllPort(){
memset(bytesRead,0,sizeof(bytesRead));
status = viQueryf(vi, (ViConstString)"PORT?\n", "%t", bytesRead);
std::cout << "端口:" << bytesRead;
}
static void InitPortInfo(PortInfo &pinfo)
{
手动初始化成员变量
char ch1[4]={'A','B','C','D'};
for(int i=0;i<4;++i)
{
pinfo.in_port[i]=ch1[i];
}
string ch2[16]={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16"};
for(int i=0;i<16;++i)
{
pinfo.out_port[i]=ch2[i];
}
pinfo.port_connect.insert(make_pair('A',"01"));
pinfo.port_connect.insert(make_pair('B',"02"));
pinfo.port_connect.insert(make_pair('C',"03"));
pinfo.port_connect.insert(make_pair('D',"04"));
pinfo.dis_out_port="16";
/*********将('A',"01"),('B',"02"),('C',"03"),('D',"04")对应关系执行,然后点亮对应图标**********/
viQueryf(vi, (ViConstString)"PORT A 01\n", "%t", bytesRead);
viQueryf(vi, (ViConstString)"PORT B 02\n", "%t", bytesRead);
viQueryf(vi, (ViConstString)"PORT C 03\n", "%t", bytesRead);
viQueryf(vi, (ViConstString)"PORT D 04\n", "%t", bytesRead);
}
main.cpp
#include "test.h"
int main(void)
{
SessInit(defaultRM);
viOpenDefaultRM (&defaultRM); //初始化VISA资源管理器,返回一个唯一标识符defaultRM
//将端口号和端口号对应的资源描述符组成map,方便后面查找
unordered_map<ViUInt16,string> portmap;//端口号eg:portmap.begin()->first 资源描述portmap.begin()->second.c_str()
FindPort(defaultRM,portmap);
PortInfo pinfo; //初始化port输入输出口结构体
ViUInt16 userinputport=17;//从用户界面下拉框选择端口,然后调用接口连接设备
ConnectPort(defaultRM, portmap, userinputport,pinfo);//连接
FindIDN();//查询IDN
FindSN();//查询SN
/*************设置SN ********************************
/*************暂未实现该功能,后期要实现****************
// const char* user_inputsn = "AAAAA1111111";//这里从用户界面获取输入的SN存入sn中
// SetSN(user_inputsn);//设置SN
// FindSN();//查询SN
FindSwitchNum();// 向设备发送SWITCHCNT?\n查询命令
DoPortin2out(pinfo);//PORT B 16\n
FindAllPort();// PORT?\n 查询当前四路端口的输出口。
///*************设置某路端口的输出端口,输入PORT A 01\n, ****************
/*************该功能还需要进一步封装实现 ****************
memset(bytesRead,0,sizeof(bytesRead));
status = viQueryf(vi, (ViConstString)"PORT A 01\n", "%t", bytesRead);
status = viQueryf(vi, (ViConstString)"PORT B 02\n", "%t", bytesRead);
status = viQueryf(vi, (ViConstString)"PORT C 03\n", "%t", bytesRead);
status = viQueryf(vi, (ViConstString)"PORT D 05\n", "%t", bytesRead);
if (status != VI_SUCCESS)
std::cout << "设置端口失败" << std::endl;
else// 在缓冲区中查看接收的IDN信息
std::cout << "设置端口操作:" << bytesRead;
FindAllPort();// PORT?\n 查询当前四路端口的输出口。
/*************查询某路端口的输出端口,输入PORA A\n, ****************
/*************暂时用不是这个功能, ****************
// memset(bytesRead,0,sizeof(bytesRead));
// status = viQueryf(vi, (ViConstString)"PORT A?\n", "%t", bytesRead);
// memset(bytesRead,0,sizeof(bytesRead));
// status = viQueryf(vi, (ViConstString)"PORT B?\n", "%t", bytesRead);
// memset(bytesRead,0,sizeof(bytesRead));
// status = viQueryf(vi, (ViConstString)"PORT C?\n", "%t", bytesRead);
// memset(bytesRead,0,sizeof(bytesRead));
// status = viQueryf(vi, (ViConstString)"PORT D?\n", "%t", bytesRead);
// if (status != VI_SUCCESS)
// std::cout << "查询PORT失败" << std::endl;
// // 在缓冲区中查看接收的IDN信息
// else
// std::cout << "PORT D输出口:" << bytesRead;
///*************查询某路端口的输出端口,输入PORA A\n, ****************
memset(bytesRead,0,sizeof(bytesRead));
// 向设备发送IDN查询命令
status = viQueryf(vi, (ViConstString)"PORT?\n", "%t", bytesRead);
if (status != VI_SUCCESS)
std::cout << "查询四路端口失败" << std::endl;
else// 在缓冲区中查看接收的IDN信息
std::cout << "四路输出口:" << bytesRead;
viClose (vi);
viClose (defaultRM);
return 0;
}
设置延长的超时时间(单位:毫秒)
//ViUInt32 delayTime = 1000; // 1 秒
//status = viSetAttribute(vi, VI_ATTR_TMO_VALUE, delayTime);
//if (status != VI_SUCCESS) {
// std::cout << "设置延长的超时时间失败" << std::endl;
// viClose(vi);
// viClose(defaultRM);
// return 1;
//}
//status = viOpen (defaultRM, "TCPIP0::192.168.100.254::inst0::INSTR", VI_NULL, VI_NULL, &vi);
/*- Configure VISA Formatted I/O ----------------------------------------*/
//status = viSetAttribute (vi, VI_ATTR_TMO_VALUE, DEFAULT_TIMEOUT); // 设置超时
//status = viSetAttribute (vi, VI_ATTR_SUPPRESS_END_EN, VI_FALSE); // 不发送终止符
//status = viSetAttribute (vi, VI_ATTR_SEND_END_EN, VI_FALSE); // 不接收终止符
//
//int main() {
// ViSession defaultRM, vi;
// ViChar desc[VI_FIND_BUFLEN];
// ViRsrcList resourceList;
// ViUInt32 num_inst;
//
// // 初始化VISA
// viOpenDefaultRM(&defaultRM);
//
// // 查找已连接的设备
// viFindRsrc(defaultRM, "?*INSTR", &resourceList, &num_inst, desc);
//
// // 连接到第一个找到的设备
// viOpen(defaultRM, resourceList, VI_NULL, VI_NULL, &vi);
//
// // 查询设备信息
// ViChar result[256];
// viWrite(vi, (ViBuf)"*IDN?\n", 6, VI_NULL);
// viRead(vi, (ViBuf)result, 256, VI_NULL);
// printf("设备信息:%s\n", result);
//
// // 断开设备连接
// viClose(vi);
// viClose(defaultRM);
//
// return 0;
//}
//ViChar command[] = "PORT D 12\n"; // 要发送的指令
//ViUInt32 retCount;
//status = viWrite(vi, (ViBuf)command, (ViUInt32)strlen(command), &retCount);
//if (status != VI_SUCCESS) {
// std::cout << "viWrite失败" << std::endl;
//}
//ViPUInt32 ret_cnt=0;
//status=viRead(vi,buffer,MAX_CNT,ret_cnt);
viRead()操作同步传输数据。读取的数据将存储在由buffer表示的缓冲区中,retcnt表示读取数据的字节数。此操作仅在传输终止时返回。一次只能进行一次同步读取操作。
//printf("%s %d\n",buffer,ret_cnt);