如何在.NET串口固件更新工具中显示传输速率与进度百分比?
PacketReceived事件未触发的原因
你当前处于Xmodem发送方角色,执行的是Send()发送固件的操作。PacketReceived事件仅在接收模式下(即调用Receive()方法接收数据时),收到对端发来的数据包才会触发,发送场景下该事件不会被激活,属于正常表现。
实时进度、传输速率实现方案
你已经找到的PacketToSend事件刚好可以用来统计发送进度,该事件会在每个数据包准备发送前触发,你可以通过累加每个包的大小计算已发送总字节数,结合总文件大小和传输耗时计算进度和速率,具体修改代码如下:
else { var xmodem = new XModemCommunicator(); mySerialPort.Close(); var port = new SerialPort { BaudRate = 115200, DataBits = 8, Parity = Parity.None, StopBits = StopBits.One, Handshake = Handshake.None, PortName = com, RtsEnable = true, DtrEnable = true, NewLine = "\r", }; xmodem.Port = port; xmodem.Data = File.ReadAllBytes(FileName); // 新增统计相关变量 long totalBytes = xmodem.Data.Length; long sentBytes = 0; DateTime startTime = DateTime.Now; xmodem.Completed += (s, e) => { // 传输完成覆盖进度行 Console.SetCursorPosition(0, Console.CursorTop); Console.WriteLine($"进度:100% | 传输完成,共发送{Math.Round(totalBytes/1024.0,2)}KB数据"); port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler2); port.Write("\r"); }; xmodem.Aborted += (s, e) => { Console.SetCursorPosition(0, Console.CursorTop); Console.WriteLine("传输已终止\nPress enter to exit."); }; xmodem.StateUpdated += (s, e) => { Console.WriteLine(xmodem.State); }; // 新增PacketToSend事件绑定,实现进度速率刷新 xmodem.PacketToSend += (s, e) => { sentBytes += e.PacketToSend.Count; double progress = Math.Round((double)sentBytes / totalBytes * 100, 1); double usedSeconds = (DateTime.Now - startTime).TotalSeconds; double speed = Math.Round(sentBytes / 1024 / usedSeconds, 2); // 清空当前行刷新显示,避免多行输出 Console.SetCursorPosition(0, Console.CursorTop); Console.Write(new string(' ', Console.WindowWidth)); Console.SetCursorPosition(0, Console.CursorTop); Console.Write($"进度:{progress}% | 传输速率:{speed}KB/s"); }; port.Open(); // 发送数据 xmodem.Send(); if (xmodem.State != XModemStates.Idle) { xmodem.CancelOperation(); Console.ReadLine(); } Thread.Sleep(10000); port.Close(); if (!port.IsOpen) { mySerialPort.Open(); } }
注意事项
- 如果遇到Xmodem重发场景,同一个包可能多次触发
PacketToSend事件,若需要更精准的统计,可以额外监听串口的ACK响应后再累加已发送字节,普通固件升级场景下重发概率极低,上述实现足够使用。 - 若不需要进度显示占满整行,可以调整
Console.SetCursorPosition的坐标参数适配你原有控制台的输出布局。
内容的提问来源于stack exchange,提问作者Jacky
相关产品推荐
相关产品推荐

