PowerShell与优派显示器串口通信读取返回值异常问题咨询
问题原因
- .NET的
System.IO.Ports.SerialPort.Read()方法默认是非阻塞调用:只要输入缓冲区中存在至少1字节数据,就会立刻返回当前已读取到的字节数,不会等待指定长度的所有数据全部接收完成再返回。 - 正常直接运行代码时,发送请求后立刻执行读取操作,此时串口仅完成了1字节的接收,剩余8字节还在传输过程中未进入输入缓冲区,因此第一次Read仅返回1字节。
- 调试单步执行时,断点停留的时间足够串口完成全部9字节的接收并写入输入缓冲区,因此第一次Read就能拿到完整数据。
最优实现方案
推荐通过循环读取累加的方式,直到拿到指定长度的所有数据,同时设置超时避免设备无响应时程序卡死,示例代码如下:
# 定义请求指令、预期返回长度 [Byte[]] $request = 0x38, 0x30, 0x31, 0x67, 0x6C, 0x30, 0x30, 0x30, 0x0D $expectedLength = 9 [Byte[]] $portreturn = [System.Byte[]]::CreateInstance([System.Byte], $expectedLength) # 初始化串口,设置读取超时为1000ms $port = New-Object System.IO.Ports.SerialPort COM3, 9600, None, 8, One $port.ReadTimeout = 1000 try { $port.Open() $port.Write($request, 0, $request.Count) $totalRead = 0 # 循环读取直到拿够预期长度的字节 while ($totalRead -lt $expectedLength) { $readCount = $port.Read($portreturn, $totalRead, $expectedLength - $totalRead) $totalRead += $readCount } Write-Host "完整返回值:" $portreturn -ForegroundColor Black -BackgroundColor White # 显示器状态判断 $status = if ($portreturn -join " " -eq "56 48 49 114 108 48 48 49 13") { "显示器开启" } elseif ($portreturn -join " " -eq "56 48 49 114 108 48 48 48 13") { "显示器关闭" } else { "状态未知" } Write-Host "当前显示器状态:$status" } catch { Write-Host "操作失败:$_" } finally { # 确保串口正常关闭释放资源 if ($port.IsOpen) { $port.Close() } $port.Dispose() }
方案优势
- 完全兼容串口数据分批到达的场景,不会出现数据拆分读取的问题
- 增加了超时机制和异常捕获,避免程序无响应
- 增加了资源自动释放逻辑,避免串口被异常占用
内容的提问来源于stack exchange,提问作者DarkMatter
相关产品推荐
相关产品推荐

