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 } } }