VISA串口通信函数-自己测试用

底层会用到visa定义的一些函数和库,visa.h;visatype.h;…;visa32.lib
这里用射频开关做了一个测试

VISA串口通信函数

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);

调试结果
VISA串口通信函数-自己测试用_第1张图片

你可能感兴趣的:(笔记,算法)