总结:使用语言实现设备控制有以下三种方式。 一种方法是使用驱动程序自带的文件进行编程开发,但这看起来很奇怪。 我认为直接使用它来开发会更好。 还有一个现成的版本。 可用的。 硬件信息是查询设备列表。 需要类型转换并由第一个字符指针的长度组成。
Golang和go语言可以通过两种方式实现设备控制。 一种是使用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") 变量列表 Instrdor:=G G: etmystring("?*") var data[180] 字节 reetcnt := 0 ret, _, _ := viFindRsrc.Call(uintptr(resourceManager), uintptr(unsafe.Pointer(instrDor.Str)), uintptr(unsafe.Pointer(&list)), uintptr(unsafe. Pointer(instrDor.Str)) 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(资源管理器),uintptr(unsafe.Pointer(instrDor.Str)), uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&instr))) if instr == 0 { return "无法打开设备。错误代码是 没错:" +fmt。 Sprint(ret) }
viClose:关闭设备管理器,关闭仪器列表,关闭打开的仪器(这里可以理解为释放内存)。 以上三个功能都是必需的。
viPrintf/viScanf:发送和接收设备数据
//向设备发送信息 //addr为设备地址,m为要发送的信息,如GPIB0::15。 :INSTR, send:DISP TXfunc 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)) 如果 ret2 == 0 { use 向设备发送使用信息并等待数据返回。 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(指令),uintptr(unsafe.Pointer(msg.Str))) readFmt := getMyString("%t") viScanf := VISA32.NewProc("viScanf") var data [180]byte viScanf.Call(uintptr(instr), uintptr(unsafe.指针(msg.Str))) 指针(readFmt.Str)), uintptr(unsafe.Pointer(&data))) s := string(Bytes2string(data)) viClose := VISA32.NewProc("viClose") viClose.Call (uintptr(instr)) return s }// 返回的数据末尾有很多零,因此您可能需要将其截断。 func Bytes2string(data [180] bytes) string {for i := 0; i < len(data); {if data[i] == 10 || data[i] == 0 {return string(data[ : i])}}return string(data[:])} 常见陷阱
Go 语言中的字符串与 C 中的字符串不同。 gostring的结构是首字符指针+长度,而Cstring的结构只有首字符指针,读取时依次读取到字符0。 因此,必须在传输过程中进行转换。 示例:
CGO用于转换C.CString,但该方法不释放内存。
本文使用了不同的方法来转换结构,因此使用了不同的结构MyString。
// 创建一个新类型而不是 C.CString // 使用 C.CString 创建一个副本并且不会自动释放。 你需要释放它。 MyString 结构类型ct { Str unsafe.Pointer Len int}//类型转换// /需要x00。 Go中的字符串由第一个字符指针+长度组成。 C 字符串只有第一个字符指针,其长度由字节 0 确定。 即,依次读取它们,直到读取到 0。 /x00 代表字符 0func getMyString(s string) *MyString { s = s + "/x00" return (*MyString)(unsafe.Pointer(&s))} 包下载尚未完成,分享一下,我们将上传后面会打包和示例程序,如果有什么问题可以留言。
评论前必须登录!
注册