栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

golang实现仪表控制-visa32.dll方式

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

golang实现仪表控制-visa32.dll方式

golang,go语言实现仪表控制可以采用2种方式,一种是使用CGO编程,使用驱动自带的VISA.H文件进行开发,但是感觉怪怪的,感觉这样还不如直接使用C进行开发,还有现成的版本可用。因此本文使用的是调用dll的方式来进行。

  • 常用函数

viOpenDefaultRM:打开设备管理器,初始化。

func OpenRM() uintptr {

    VISA32 := syscall.NewLazyDLL("visa32.dll")

    viOpenDefaultRM := VISA32.NewProc("viOpenDefaultRM")

    ret, _, _ := viOpenDefaultRM.Call(uintptr(unsafe.Pointer(&resourceManager)))

    fmt.Println("硬件信息为:", resourceManager)

    return ret

}

viFindRsrc:查询仪表清单。

func FindRsrc() bool {

    VISA32 := syscall.NewLazyDLL("visa32.dll")

    viFindRsrc := VISA32.NewProc("viFindRsrc")

    var list int = 0

    instrDor := getMyString("?*")

    var data [180]byte

    retcnt := 0

    ret, _, _ := viFindRsrc.Call(uintptr(resourceManager), uintptr(unsafe.Pointer(instrDor.Str)), uintptr(unsafe.Pointer(&list)), uintptr(unsafe.Pointer(&retcnt)), uintptr(unsafe.Pointer(&data)))

    if ret != 0 {

        fmt.Println("查询代码:", ret)

        return false

    }

    fmt.Println("查询成功->")

    viFindNext := VISA32.NewProc("viFindNext")

    viFindNext.Call(uintptr(list), uintptr(unsafe.Pointer(&data)))

    s := string(Bytes2string(data))

    viClose := VISA32.NewProc("viClose")

    viClose.Call(uintptr(list))

    fmt.Println(s)

    return true

}

viOpen:使用地址打开仪表。

    instrDor := getMyString(addr)

    VISA32 := syscall.NewLazyDLL("visa32.dll")

    viOpen := VISA32.NewProc("viOpen")

    var instr int = 0

    ret, _, _ := viOpen.Call(uintptr(resourceManager), uintptr(unsafe.Pointer(instrDor.Str)), uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&instr)))

    if instr == 0 {

        return "打开仪器失败,错误代码为:" + fmt.Sprint(ret)

    }

viClose:关闭设备管理器,关闭仪器清单,关闭打开的仪表(可以理解为释放内存)上面的3个函数都要。

viPrintf/viScanf:发送和接收仪表的数据

// 发送信息给仪表

// addr为仪器地址,m为需要发送的信息,如GPIB0::15::INSTR,send:DISP TX

func SendMsg(addr, m string) string {

    instrDor := getMyString(addr)

    VISA32 := syscall.NewLazyDLL("visa32.dll")

    viOpen := VISA32.NewProc("viOpen")

    var instr int = 0

    ret, _, _ := viOpen.Call(uintptr(resourceManager), uintptr(unsafe.Pointer(instrDor.Str)), uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&instr)))

    if instr == 0 {

        return "打开仪器失败,错误代码为:" + fmt.Sprint(ret)

    }

    m = m + "n"

    msg := getMyString(m)

    viPrintf := VISA32.NewProc("viPrintf")

    ret2, _, _ := viPrintf.Call(uintptr(instr), uintptr(unsafe.Pointer(msg.Str)))

    viClose := VISA32.NewProc("viClose")

    viClose.Call(uintptr(instr))

    if ret2 == 0 {

        return "信息发送成功!---" + m

    }

    return "发送失败,代码为:" + fmt.Sprint(ret2)

}



// 发送信息给仪表,并等待仪表返回数据。

func ReadData(addr, m string) string {

    instrDor := getMyString(addr)

    VISA32 := syscall.NewLazyDLL("visa32.dll")

    viOpen := VISA32.NewProc("viOpen")

    var instr int = 0

    ret, _, _ := viOpen.Call(uintptr(resourceManager), uintptr(unsafe.Pointer(instrDor.Str)), uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&instr)))

    if instr == 0 {

        return "打开仪器失败,错误代码为:" + fmt.Sprint(ret)

    }

    m = m + "n"

    msg := getMyString(m)

    viPrintf := VISA32.NewProc("viPrintf")

    viPrintf.Call(uintptr(instr), uintptr(unsafe.Pointer(msg.Str)))

    readFmt := getMyString("%t")

    viScanf := VISA32.NewProc("viScanf")

    var data [180]byte

    viScanf.Call(uintptr(instr), uintptr(unsafe.Pointer(readFmt.Str)), uintptr(unsafe.Pointer(&data)))

    s := string(Bytes2string(data))

    viClose := VISA32.NewProc("viClose")

    viClose.Call(uintptr(instr))

    return s

}

// 返回的数据后面有很多个0,截断处理会更好些。
func Bytes2string(data [180]byte) string {
	for i := 0; i < len(data); i++ {
		if data[i] == 10 || data[i] == 0 {
			return string(data[:i])
		}
	}
	return string(data[:])
}
  • 常见的坑

go语言的string与C的string是有所区别的,gostring的结构是首字符的指针+长度,而Cstring的结构只有首字符指针,然后读取时顺序读到字符0为止。因此在传递中要进行转换,比如:

使用CGO使用C.CString进行转换,但这个方式会导致内存不能释放。

文中采用了另一种方式,改造结构体的方式,因此采用了另一种结构体MyString。

// 新建类型,代替C.CString

// C.CString使用会产生拷贝,并不会自动释放,需要进行free。

type MyString struct {

    Str unsafe.Pointer

    Len int

}

//类型转换

// x00是必须的,go的string是由首字符指针+长度组成。而C的string只有首字符指针,长度由字节0来确定,即顺序读,直到读到0。x00即代表字符0

func getMyString(s string) *MyString {

    s = s + "x00"

    return (*MyString)(unsafe.Pointer(&s))

}
包的下载,目前还没有完善,后续会上传一个共享包和示例程序,着急的也可以留言。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/907393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号