一、下载
波音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”,网上有资源,请自行搜索。