NI-VISA 安裝教程和IEEE-488通信(VS)

一、下載

波音747航班:https://www.ni.com/zh-cn/support/downloads/drivers/download.ni-visa.html#329456

選擇合適的版本下載

 

二、安裝

安裝之前請關閉防火牆和其他殺毒軟件等;

按照流程一路next即可。

 

三、.lib、.dll、.h文件位置

64位WIN10系統爲例,.lib文件和.h文件在“C:\Program Files\IVI Foundation\VISA\Win64”目錄下的include和lib_x64目錄下,.dll文件在“C:\Windows\System32”和“C:\Windows\SysWOW64”中

 

四、案例

1】ComPort.h

#pragma once

#include <string>
#include <atlconv.h>
#include <map>

//包含VISA頭文件和庫文件
#include "visa.h"   

 #ifdef COMMUNICATION_EXPORTS
 #define COMMUNICATION_API __declspec(dllexport)
 #else
 #define COMMUNICATION_API __declspec(dllimport)
 #endif

//通信基類
class COMMUNICATION_API CComPort
{
protected:
	//通信口是否已打開
	bool m_bIsOpened;
	//通信接口的互斥鎖
    CRITICAL_SECTION m_csComm;

public:
	CComPort(void);
	virtual ~CComPort(void);

public:
	//打開通信端口
	virtual bool Open(std::string strParam) = 0;

	//關閉通信端口
	virtual void Close(void) = 0;

	//發送數據
	virtual int Send(const unsigned char *cData, int nLen) = 0;

	//接收數據
	virtual int Recv(unsigned char *cData, int nLen) = 0;

	//重新打開通信口
	virtual bool ReOpen(void) = 0;

	//通信口可能同時只能供一個線程調用,使用時請求鎖
	virtual bool TryToLock(bool bMode = true);

	//線程使用完串口後,爲通信口實例釋放鎖
	virtual void ReleaseLock(void);

	//通信口是夠已經打開
	virtual bool IsOpened(void) { return m_bIsOpened; }
};

2】ComPort.cpp

#include "stdafx.h"
#include "ComPort.h"


CComPort::CComPort(void)
{
	m_bIsOpened = false;
	InitializeCriticalSection(&m_csComm); 
}


CComPort::~CComPort(void)
{
	DeleteCriticalSection(&m_csComm);
}

//通信口可能同時只能供一個線程調用,使用時請求鎖
bool CComPort::TryToLock(bool bMode)
{
	EnterCriticalSection(&m_csComm);
	return true;
}

//線程使用完串口後,爲通信口實例釋放鎖
void CComPort::ReleaseLock(void)
{
	LeaveCriticalSection(&m_csComm);
}

 

3】IEEE488Port.h

#pragma once
#include "comport.h"


class CComIEEE488Fun
{
public:
	//校驗位類型和int的對應
	static std::map<std::string, int> cComParityMap;
};

//IEEE-488通信類
class COMMUNICATION_API CIEEE488Port :
	public CComPort
{
private:
	//IEEE-488通信口地址
	char *m_pStrIEEEAddress;

	//IEEE-488參數
	char *m_pStrIEEEParam;

	// 默認資源管理器會話的唯一邏輯標識符。
	ViSession m_vfaultRM;
	//IEEE-488句柄
	ViSession m_vIEEEHandle;

public:
	CIEEE488Port(void);
	virtual ~CIEEE488Port(void);

public:
	//打開通信端口
	virtual bool Open(std::string strParam);

	//關閉通信端口
	virtual void Close(void);

	//發送數據
	virtual int Send(const unsigned char *cData, int nLen);

	//接收數據
	virtual int Recv(unsigned char *cData, int nLen);

	//重新打開通信口
	virtual bool ReOpen(void);

private:
	//解析Open函數傳遞過來的串口參數
	bool parseOpenParam(std::string strParam);

	//設置初始化參數,如緩衝區大小和超時時間等
	bool initSetting(void);
};

4】IEEE488Port.cpp

#include "stdafx.h"
#include "IEEE488Port.h"

std::pair<std::string, int> pairParityType[]= 
{
	std::make_pair("N", 0),
	std::make_pair("O", 1),
	std::make_pair("E", 2),
	std::make_pair("M", 3),
	std::make_pair("S", 4),

};
std::map<std::string, int> CComIEEE488Fun::cComParityMap(pairParityType, pairParityType+sizeof(pairParityType)/sizeof(pairParityType[0]));


CIEEE488Port::CIEEE488Port(void) : CComPort()
{
	// 存放IEEE-488通信地址
	m_pStrIEEEAddress = new char[128];
	m_pStrIEEEAddress[0]=0;
	// 存放參數
	m_pStrIEEEParam = new char[32];
	m_pStrIEEEParam[0] = 0;
}


CIEEE488Port::~CIEEE488Port(void)
{
	//試圖關閉通信口
	Close();

	delete []m_pStrIEEEAddress;
	delete []m_pStrIEEEParam;
}

//打開通信端口
bool CIEEE488Port::Open(std::string strParam)
{
	//通信口已被打開
	if(m_bIsOpened)
		return true;

	//解析IEEE-488通信口打開參數
	if(parseOpenParam(strParam)==false)
	{
		return false;
	}

	// 初始化一個VISA資源管理器
	ViStatus status = viOpenDefaultRM (&m_vfaultRM);
	if(status!= VI_SUCCESS)
		return false;
	//打開IEEE-488通信口,並創建操作句柄
	status = viOpen(m_vfaultRM, m_pStrIEEEAddress,VI_NULL,VI_NULL, &m_vIEEEHandle);
	if(status != VI_SUCCESS)
	{
		return false;
	}
	
	//設置IEEE-488通信口初始化參數
	if(initSetting()==false)
		return false;

	m_bIsOpened = true;
	return true;
}

//關閉通信端口
void CIEEE488Port::Close(void)
{
	if(m_bIsOpened==false)
		return;

	// viClose:關閉特定的會話、事件或查找列表
	viClose(m_vIEEEHandle);
	viClose (m_vfaultRM);
	m_bIsOpened = false;
}

//發送數據
int CIEEE488Port::Send(const unsigned char *cData, int nLen)
{
	ViPUInt16 status = NULL;
	DWORD dwRealSend = 0;

	if(m_bIsOpened==false)
		return -1;

	////如果IEEE-488有錯誤,則清除輸入/輸出緩衝區
	viReadSTB(m_vIEEEHandle, status);
	if(status != VI_SUCCESS)
	{
		// 終止操作(VISA將中止當前進程中對指定vi執行的任何調用)
		viTerminate(m_vIEEEHandle, VI_NULL,  VI_NULL);
		//格式化指定緩衝區
		viFlush(m_vIEEEHandle,VI_WRITE_BUF_DISCARD);
	}
	
	//寫數據(同步)
	// viPrintf(m_vIEEEHandle, (ViString)cData)
	if(viWrite(m_vIEEEHandle, cData, nLen, &dwRealSend) != VI_SUCCESS)
	{
		return -2;
	}

	//返回實際發送的數據大小
	return dwRealSend;
}

//接收數據
int CIEEE488Port::Recv(unsigned char *cData, int nLen)
{
	ViPUInt16 status = NULL;
	DWORD dwRealRead = 0;
	
	if(m_bIsOpened==false)
		return -1;

	//如果IEEE-488有錯誤,則清除輸入/輸出緩衝區
	viReadSTB(m_vIEEEHandle, status);
	if(status != VI_SUCCESS)
	{
		// 終止操作(VISA將中止當前進程中對指定vi執行的任何調用)
		viTerminate(m_vIEEEHandle, VI_NULL,  VI_NULL);
		 //格式化指定緩衝區
		viFlush(m_vIEEEHandle,VI_READ_BUF_DISCARD);
	}

	//讀數據(同步)
	// 從設備讀取一個字符串,然後格式化後保存值dwRealRead中(隱式分割符是被忽略的)
	// viScanf(m_vIEEEHandle, (ViString)cData)
	if(viRead(m_vIEEEHandle, cData, nLen, &dwRealRead) != VI_SUCCESS)
	{
		return -2;
	}

	return dwRealRead;
}

//重新打開通信口
bool CIEEE488Port::ReOpen(void)
{
	if(strlen(m_pStrIEEEAddress)==0 || strlen(m_pStrIEEEParam)==0)
		return false;

	//關閉通信口
	Close();

	//打開通信口
	std::string strParam = m_pStrIEEEAddress + std::string(";") + m_pStrIEEEParam;
	return Open(strParam);
}

//解析Open函數傳遞過來的串口參數
bool CIEEE488Port::parseOpenParam(std::string strParam)
{
	//尋找IEEE-488通信地址的結束位置(";"號)
	std::size_t nFound = strParam.find(';');
	//未找到通信口名
	if (nFound==std::string::npos)
		return false;
	
	//分解參數字符串爲端口名和參數兩個部分
	strcpy_s(m_pStrIEEEAddress, 128, strParam.substr(0, nFound).c_str());
	strcpy_s(m_pStrIEEEParam, 32, strParam.substr(nFound+1).c_str());

	return true;
}

//設置初始化參數,如緩衝區大小和超時時間等
bool CIEEE488Port::initSetting(void)
{
	//設置I/O讀/寫緩衝區大小(初始化一個指定的通信設備的通信參數。)
	if(!viSetBuf(m_vIEEEHandle, VI_READ_BUF|VI_WRITE_BUF, 1024))
	{
		Close();
		return false;
	}

	//設置超時參數
	viSetAttribute(m_vIEEEHandle,VI_ATTR_TMO_VALUE,1000);

	//格式化指定緩衝區
	viFlush(m_vIEEEHandle,VI_READ_BUF |VI_WRITE_BUF);

	/******************************************************/
	//開始設置通信口的波特率,數據位,停止位,流控,校驗等參數
	char **cRemainder = NULL;
	char* cBaud = strtok_s(m_pStrIEEEParam, ",", cRemainder);
	viSetAttribute(m_vIEEEHandle,VI_ATTR_ASRL_BAUD, atoi(cBaud));
	char* cDataBits = strtok_s(NULL, ",", cRemainder);
	viSetAttribute(m_vIEEEHandle,VI_ATTR_ASRL_DATA_BITS, atoi(cDataBits));
	char* cParity = strtok_s(NULL, ",", cRemainder);
	viSetAttribute(m_vIEEEHandle,VI_ATTR_ASRL_PARITY, CComIEEE488Fun::cComParityMap[cParity]);
	char* cStopBits = strtok_s(NULL, ",", cRemainder);
	viSetAttribute(m_vIEEEHandle,VI_ATTR_ASRL_STOP_BITS, atoi(cStopBits));

	return true;
}

【注】請自覺在項目屬性頁->【配置屬性】->【鏈接器】->【常規】->【附加庫目錄】中添加所需lib文件所在位置;

            項目屬性頁->【配置屬性】->【鏈接器】->【輸入】->【附加依賴項】中添加所需.lib文件;

             dll文件需放在項目對應的目錄下。

【注】具體的信息參見“NI-VISA用戶手冊和NI-VISA程序員參考手冊.zip”,網上有資源,請自行搜索。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章