• Golang 串口通信


    简介

    串口通信是一种常见的硬件通信方式,用于在计算机和外部设备之间传输数据。Golang(Go语言)作为一种高效、可靠的编程语言,提供了丰富的库和工具用于串口通信。本文将介绍如何使用Golang进行串口通信,包括串口配置、数据读写和错误处理等方面。

    安装依赖

    在开始之前,我们需要先安装Golang的串口通信库。目前,有很多第三方的串口通信库可供选择,如"go-serial"和"go-serialport"等。你可以通过以下命令安装其中一个库:

    go get github.com/jacobsa/go-serial/serial
    
    • 1

    打开串口

    在进行串口通信之前,首先需要打开串口。在Golang中,打开串口可以使用Open()函数,该函数接收一个串口配置参数作为输入。下面是一个打开串口的示例代码:

    package main
    
    import (
        "log"
        "github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
        // 配置串口参数
        options := serial.OpenOptions{
            PortName:        "/dev/ttyUSB0",
            BaudRate:        9600,
            DataBits:        8,
            StopBits:        1,
            MinimumReadSize: 4,
        }
    
        // 打开串口
        port, err := serial.Open(options)
        if err != nil {
            log.Fatal(err)
        }
    
        // 关闭串口
        defer port.Close()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在上述代码中,我们首先定义了一个options变量,用于存储串口的配置参数。然后,我们调用serial.Open()函数打开串口,并将返回的port变量存储为串口对象。如果打开串口失败,我们使用log.Fatal()函数输出错误信息并退出程序。最后,我们通过defer关键字在程序结束时关闭串口。

    读取数据

    打开串口后,我们就可以开始读取串口数据了。在Golang中,可以使用port.Read()函数从串口中读取数据。下面是一个读取串口数据的示例代码:

    package main
    
    import (
        "log"
        "github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
        // 配置串口参数
        options := serial.OpenOptions{
            PortName:        "/dev/ttyUSB0",
            BaudRate:        9600,
            DataBits:        8,
            StopBits:        1,
            MinimumReadSize: 4,
        }
    
        // 打开串口
        port, err := serial.Open(options)
        if err != nil {
            log.Fatal(err)
        }
    
        // 关闭串口
        defer port.Close()
    
        // 读取数据
        buf := make([]byte, 128)
        n, err := port.Read(buf)
        if err != nil {
            log.Fatal(err)
        }
    
        // 输出读取到的数据
        log.Printf("Read %d bytes: %v", n, buf[:n])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在上述代码中,我们首先定义了一个buf变量,用于存储读取到的数据。然后,我们调用port.Read()函数从串口中读取数据,并将读取到的数据存储到buf中。最后,我们使用log.Printf()函数输出读取到的数据。

    写入数据

    除了读取数据,我们还可以使用Golang向串口写入数据。在Golang中,可以使用port.Write()函数向串口写入数据。下面是一个向串口写入数据的示例代码:

    package main
    
    import (
        "log"
        "github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
        // 配置串口参数
        options := serial.OpenOptions{
            PortName:        "/dev/ttyUSB0",
            BaudRate:        9600,
            DataBits:        8,
            StopBits:        1,
            MinimumReadSize: 4,
        }
    
        // 打开串口
        port, err := serial.Open(options)
        if err != nil {
            log.Fatal(err)
        }
    
        // 关闭串口
        defer port.Close()
    
        // 写入数据
        buf := []byte("Hello, Serial!")
        n, err := port.Write(buf)
        if err != nil {
            log.Fatal(err)
        }
    
        // 输出写入的字节数
        log.Printf("Write %d bytes: %v", n, buf)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在上述代码中,我们首先定义了一个buf变量,用于存储要写入的数据。然后,我们调用port.Write()函数向串口写入数据,并将写入的字节数存储到n变量中。最后,我们使用log.Printf()函数输出写入的字节数和写入的数据。

    错误处理

    在进行串口通信时,可能会遇到各种错误,如串口打开失败、读写错误等。为了保证程序的稳定性和可靠性,我们需要对这些错误进行适当的处理。

    在前面的示例代码中,我们使用了log.Fatal()函数来处理错误。该函数会输出错误信息并退出程序。除了log.Fatal()函数,我们还可以使用其他错误处理方式,如使用log.Println()函数输出错误信息而不退出程序,或使用fmt.Errorf()函数返回自定义的错误信息。

    案例

    案例1:发送和接收数据

    在这个案例中,我们将演示如何使用Golang进行串口通信来发送和接收数据。我们将通过串口向外部设备发送数据,并从外部设备接收响应。

    package main
    
    import (
    	"log"
    	"time"
    
    	"github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
    	// 配置串口参数
    	options := serial.OpenOptions{
    		PortName:        "/dev/ttyUSB0",
    		BaudRate:        9600,
    		DataBits:        8,
    		StopBits:        1,
    		MinimumReadSize: 4,
    	}
    
    	// 打开串口
    	port, err := serial.Open(options)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// 关闭串口
    	defer port.Close()
    
    	// 发送数据
    	sendData := []byte("Hello, Serial!")
    	n, err := port.Write(sendData)
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Sent %d bytes: %v", n, sendData)
    
    	// 接收数据
    	buf := make([]byte, 128)
    	n, err = port.Read(buf)
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Received %d bytes: %v", n, buf[:n])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    在上述代码中,我们首先通过port.Write()函数向串口发送数据。然后,我们使用port.Read()函数从串口接收响应数据。最后,我们使用log.Printf()函数分别输出发送和接收到的数据。

    案例2:设置串口超时时间

    在某些场景下,我们可能需要设置串口的超时时间。如果在超时时间内没有接收到数据,我们可以选择继续等待或者中断操作。下面是一个设置串口超时时间的示例代码:

    package main
    
    import (
    	"log"
    	"time"
    
    	"github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
    	// 配置串口参数
    	options := serial.OpenOptions{
    		PortName:        "/dev/ttyUSB0",
    		BaudRate:        9600,
    		DataBits:        8,
    		StopBits:        1,
    		MinimumReadSize: 4,
    		InterCharacterTimeout: 500,
    	}
    
    	// 打开串口
    	port, err := serial.Open(options)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// 关闭串口
    	defer port.Close()
    
    	// 设置超时时间
    	timeoutDuration := 2 * time.Second
    	port.SetReadTimeout(timeoutDuration)
    
    	// 读取数据
    	buf := make([]byte, 128)
    	n, err := port.Read(buf)
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Received %d bytes: %v", n, buf[:n])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在上述代码中,我们通过port.SetReadTimeout()函数设置了串口的读取超时时间为2秒。如果在超时时间内没有读取到数据,port.Read()函数将返回io.EOF错误。这样我们可以根据需要选择继续等待数据或者中断操作。

    案例3:配置流控制

    有些串口设备可能需要配置流控制来实现数据传输的控制和同步。在这个案例中,我们将演示如何在Golang中配置串口的硬件流控制。

    package main
    
    import (
    	"log"
    
    	"github.com/jacobsa/go-serial/serial"
    )
    
    func main() {
    	// 配置串口参数
    	options := serial.OpenOptions{
    		PortName:        "/dev/ttyUSB0",
    		BaudRate:        9600,
    		DataBits:        8,
    		StopBits:        1,
    		MinimumReadSize: 4,
    		FlowControl:     serial.HardwareFlowControl,
    	}
    
    	// 打开串口
    	port, err := serial.Open(options)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// 关闭串口
    	defer port.Close()
    
    	// 发送数据
    	sendData := []byte("Hello, Serial!")
    	n, err := port.Write(sendData)
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Sent %d bytes: %v", n, sendData)
    
    	// 接收数据
    	buf := make([]byte, 128)
    	n, err = port.Read(buf)
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Received %d bytes: %v", n, buf[:n])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    在上述代码中,我们通过options.FlowControl字段设置串口的流控制方式为硬件流控制。这样,串口将根据硬件信号来控制数据传输的节奏和同步。根据外部设备的要求,你可以选择硬件流控制、软件流控制或者不使用流控制。

    通过上述案例,我们了解了如何使用Golang进行串口通信,并学习了如何发送和接收数据、设置超时时间以及配置流控制。串口通信在嵌入式系统、物联网和传感器等领域具有广泛的应用,掌握使用Golang进行串口通信的技巧可以帮助我们更好地开发和调试相关应用。Golang提供的丰富的库和工具使得串口通信变得更加便捷和高效。

    总结

    本文介绍了如何使用Golang进行串口通信。我们学习了如何打开串口、读取数据、写入数据和处理错误。串口通信在物联网、嵌入式系统和传感器等领域具有广泛的应用,掌握使用Golang进行串口通信的技巧可以帮助我们更好地开发和调试相关应用。同时,Golang提供的丰富的库和工具也使得串口通信变得更加便捷和高效。

  • 相关阅读:
    怎么恢复格式化的sd卡呢?
    Redis进阶
    JavaScript 65 JavaScript 类 65.2 JavaScript 类继承
    115 双周赛
    案例分享 | 数字化综合人才管理平台
    binlog格式设置
    JavaScript自我学习
    图象的感光原件、成象原理、相机的相关坐标系
    vue - vue基础/vue核心内容(终结篇)
    mybatis-plus 统一管理创建时间、更新时间、创建人与更新人
  • 原文地址:https://blog.csdn.net/hitpter/article/details/134179481