78 lines
1.4 KiB
Go
78 lines
1.4 KiB
Go
package serialport
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"log"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"go.bug.st/serial"
|
||
|
|
|
||
|
|
"bjhardman.cn/bjhardman/hougai_insize_micrometer/insize"
|
||
|
|
)
|
||
|
|
|
||
|
|
type Port struct {
|
||
|
|
port serial.Port
|
||
|
|
frames chan insize.Frame
|
||
|
|
errs chan error
|
||
|
|
done chan struct{}
|
||
|
|
}
|
||
|
|
|
||
|
|
func Open(name string, baud int) (*Port, error) {
|
||
|
|
mode := &serial.Mode{
|
||
|
|
BaudRate: baud,
|
||
|
|
DataBits: 8,
|
||
|
|
Parity: serial.NoParity,
|
||
|
|
StopBits: serial.OneStopBit,
|
||
|
|
}
|
||
|
|
sp, err := serial.Open(name, mode)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("打开串口 %s: %w", name, err)
|
||
|
|
}
|
||
|
|
if err := sp.SetReadTimeout(500 * time.Millisecond); err != nil {
|
||
|
|
}
|
||
|
|
|
||
|
|
p := &Port{
|
||
|
|
port: sp,
|
||
|
|
frames: make(chan insize.Frame, 16),
|
||
|
|
errs: make(chan error, 4),
|
||
|
|
done: make(chan struct{}),
|
||
|
|
}
|
||
|
|
go p.readLoop()
|
||
|
|
return p, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Port) Frames() <-chan insize.Frame { return p.frames }
|
||
|
|
|
||
|
|
func (p *Port) Errors() <-chan error { return p.errs }
|
||
|
|
|
||
|
|
func (p *Port) Close() error {
|
||
|
|
close(p.done)
|
||
|
|
return p.port.Close()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Port) readLoop() {
|
||
|
|
reader := insize.NewReader(p.port)
|
||
|
|
for {
|
||
|
|
select {
|
||
|
|
case <-p.done:
|
||
|
|
return
|
||
|
|
default:
|
||
|
|
}
|
||
|
|
f, err := reader.ReadFrame()
|
||
|
|
if err != nil {
|
||
|
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||
|
|
p.errs <- fmt.Errorf("串口读取结束: %w", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
log.Printf("serialport: 跳过非法帧: %v", err)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
select {
|
||
|
|
case p.frames <- f:
|
||
|
|
case <-p.done:
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|