package uhf import ( "errors" "github.com/tarm/serial" "io" "os" "time" ) type SerialReader struct { COMPort string BaudRate int port *serial.Port isConnected bool buffer []byte // 拼包缓冲区 } func NewSerialReader(comPort string, baudRate int) *SerialReader { return &SerialReader{ COMPort: comPort, BaudRate: baudRate, } } func (s *SerialReader) Connect() error { cfg := &serial.Config{ Name: s.COMPort, Baud: s.BaudRate, ReadTimeout: 1 * time.Second, Size: 8, Parity: serial.ParityNone, StopBits: serial.Stop1, } port, err := serial.OpenPort(cfg) if err != nil { s.isConnected = false return err } s.port = port s.isConnected = true return nil } func (s *SerialReader) Disconnect() error { if s.port != nil { _ = s.port.Close() } s.isConnected = false s.buffer = nil return nil } func (s *SerialReader) IsConnected() bool { return s.isConnected } func (s *SerialReader) SendData(data []byte) error { if !s.isConnected { return errors.New("串口未连接") } n, err := s.port.Write(data) if err != nil { return err } if n != len(data) { return errors.New("发送不完整") } return nil } // ============================== // 🔥 关键修复:串口返回完整25字节帧 // ============================== func (s *SerialReader) ReadData() ([]byte, error) { if !s.isConnected { return nil, errors.New("串口未连接") } buf := make([]byte, 1024) for { n, err := s.port.Read(buf) if err != nil { if err == io.EOF || os.IsTimeout(err) { break } s.isConnected = false return nil, err } if n > 0 { s.buffer = append(s.buffer, buf[:n]...) } // 找25字节完整帧 for len(s.buffer) >= 25 { if s.buffer[0] == 0xCF { frame := s.buffer[:25] s.buffer = s.buffer[25:] return frame, nil } else { s.buffer = s.buffer[1:] } } // 超时退出 if len(s.buffer) == 0 { break } } return nil, errors.New("等待完整帧") } func (s *SerialReader) SendAndRecv(data []byte) ([]byte, error) { _ = s.SendData(data) time.Sleep(100 * time.Millisecond) return s.ReadData() }