一、通信流程
大体的通信流程如下:
//1.打开串口
//2.生成读指令
//3.发送读指令
//4.接收并验证返回指令
//5.解析返回指令
二、简单示例
以rtu为例,不能运行!
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io"
"time"
"github.com/tarm/serial"
)
func main() {
//1.打开串口
//打开串口的参数,name:串口名称,baud:波特率,size:数据位,parity:校验位,stopBit:停止位
//例:串口名称:/dev/ttyS1 波特率9600,数据位8位,停止位1位,无校验
cfg := &serial.Config{
Name: comName,
Baud: GetBaudrate(baudRate),
Size: GetDataBits(dataBit),
Parity: GetParityBits(checkBit),
StopBits: GetStopBits(stopBit),
}
readPort, portErr := serial.OpenPort(cfg)
if portErr != nil {
fmt.printf("打开串口错误:%v",portErr)
return
}
defer readPort //要关闭
//2.生成读指令
//根据实际情况,该函数就是根据具体的协议生成读指令
readByteArr, generateErr := GenerateRead()
if generateErr != nil {
fmt.Printf("generate cmdByte err: %v", generateErr)
return
}
//3.发送读指令
wn, writeErr := readPort.Write(readByteArr)
if writeErr != nil {
fmt.Printf("write err: %v", writeErr)
return
}
//4.接收并验证返回指令
//计算返回命令的长度
reslength := countResponseLength(cmdByteArr)
//接收返回指令
msg, msgErr := receiveData(iorwc, reslength )
if msgErr != nil {
fmt.Printf("receiveData err: %v", msgErr)
return
}
//5.解析返回指令
res,resBool:=ParseData(msg)
if !resBool{
println("parse error")
return
}
println("res data:",res)
}
rtu和ascii和流程是一样的,不同的就是在拼接读指令,接收返回指令, 读取返回指令。ascii的读取返回指令可以直接使用scanLines
三、建议细节
比较难处理的部分是,解析返回的指令,根据协议不同,解析的方式也会完全不同。比如要理解golang中byte ,rune string。因为我们能理解的是string,而机器接收的是[]byte。还有byte和ascii码的关系。