向串口发送数据时如何获得链接速度和传输百分比?

Posted

技术标签:

【中文标题】向串口发送数据时如何获得链接速度和传输百分比?【英文标题】:How to have link speed and transfer percentage when sending data to serial-port? 【发布时间】:2021-12-12 14:13:46 【问题描述】:

我正在开发 .Net Console app 以与 SAS 扩展卡上的固件进行通信。

当我更新固件时,Tera Term 的页面会显示:

你可以看到[4.09KB/S]是链接速度,71.6%是传输百分比。

这里有一个问题:

如何在我的控制台应用上设置链接速度和传输百分比?

链接速度和传输百分比会不断变化,直到数据完全被卡接收。

我已经在我的控制台应用中添加了XmodemProtocol 库。

这是我的代码:


using XModemProtocol;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Windows.Forms;
using System.IO;
using System.Threading;



namespace XModemProtocolExample

    class Program
    
        [STAThread]
        static void Main()
        
           
            
            string[] ports = SerialPort.GetPortNames();
            string com = "";
            Console.WriteLine("The following serial ports were found:");
            foreach (string port in ports)
            
                Console.WriteLine(port);
                Console.WriteLine("Please choose which port name you want ?");
                com = Console.ReadLine();
                Console.Clear();
            
            SerialPort mySerialPort = new SerialPort(com);

            mySerialPort.BaudRate = 115200;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.RtsEnable = true;
            mySerialPort.DtrEnable = true;
            mySerialPort.ReadTimeout = 2000;
            mySerialPort.WriteTimeout = 1500;
            
            mySerialPort.NewLine = "\r";
            mySerialPort.Open();

            if (mySerialPort.IsOpen)
            
                mySerialPort.Write("\r");
            

            List<string> Commands = new List<string>();
            string command = "";
            int counter = 0;
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            while (true)
            
                ConsoleKeyInfo consoleInput = Console.ReadKey();

                if (consoleInput.KeyChar == '\r')
                
                    Commands.Add(command);
                    counter = Commands.Count - 1;
                    mySerialPort.Write(command + "\r");
                    if (command == "fwdl")
                    
                        ClearCurrentConsoleLine();
                    
                    if (command == "y")
                    
                        String FileName = "";
                        OpenFileDialog openfile1 = new OpenFileDialog();
                        if (openfile1.ShowDialog() == DialogResult.OK)
                        
                            FileName = openfile1.FileName;
                        
                        if (FileName == "")
                        
                            Console.ReadLine();
                        
                        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);
                            xmodem.Completed += (s, e) =>
                            
                               
                                
                                port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler2);
                                port.Write("\r");
                              
                                
                            ;
                            xmodem.Aborted += (s, e) =>
                            
                                Console.WriteLine("Operation Aborted.\nPress enter to exit.");
                            ;

                            xmodem.StateUpdated += (s, e) =>
                            
                                Console.WriteLine(xmodem.State);
                            ;

                            port.Open();

                            // Send Data.
                            xmodem.Send();
                            

                            if (xmodem.State != XModemStates.Idle)
                            
                                xmodem.CancelOperation();
                                Console.ReadLine();
                            
                            Thread.Sleep(10000);
                            port.Close();
                            if (!port.IsOpen)
                            
                                mySerialPort.Open();
                            
                        
                    
                    if (command == "mfgdl")
                    
                        ClearCurrentConsoleLine();
                    

                    ClearCurrentConsoleLine();
                        command = "";
                
                else if (consoleInput.Key == ConsoleKey.UpArrow)
                
                    if ((counter >= 0) && (counter < Commands.Count))
                    
                        ClearCurrentConsoleLine();
                        Console.Write(Commands[counter]);
                        foreach (string obj in Commands)
                        
                            command = obj;
                        
                        if (consoleInput.KeyChar == '\r')
                        
                            Commands.Add(command);
                            counter = Commands.Count - 1;
                            mySerialPort.Write(command + "\r");
                            ClearCurrentConsoleLine();
                            command = "";
                        
                    

                    if (counter > 0)
                    
                        counter--;
                    

                    else
                    
                        counter = Commands.Count - 1;
                    
                
                else
                
                    command += consoleInput.KeyChar.ToString();
                
              
                      
        
        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
             Console.Write(indata);
        

        private static void DataReceivedHandler2(object sender, SerialDataReceivedEventArgs e)
        
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
            Console.Write(indata);
        

        private static void ClearCurrentConsoleLine()
        
            int currentLineCursor = Console.CursorTop;
            Console.SetCursorPosition(6, Console.CursorTop);
            Console.Write(new string(' ', Console.WindowWidth));
            Console.SetCursorPosition(6, currentLineCursor);
        
     
    


我的控制台显示的内容:

我只能知道 xmodem 的状态。

我不知道如何建立链接速度和传输百分比。

XmodemProtocol 可以做这件事吗?如果有,该怎么做?

我的控制台应用正在使用.Net Framework 4.7.2

Received xxxxxxxx Bytes 是卡片的响应。

只有在数据完全发送到卡(100%)后才能出来。

.................................................. ..

更新1:

添加后

xmodem.PacketToSend += (s, e) =>
                            
                                Console.WriteLine(e.PacketToSend.Count);
                            ;

控制台显示如下:

..................................

更新2:

我删除后

xmodem.PacketToSend += (s, e) =>

       Console.WriteLine(e.PacketToSend.Count);
;

,我换成

xmodem.PacketReceived += (s, e) =>

      Console.WriteLine(e.PacketReceived.Count);                        
;

控制台的结果:

为什么PacketReceived 事件不会触发?

【问题讨论】:

由于XModemProtocol的PacketToSend/PacketReceived事件的EventArgs中有PacketNumber和实际数据的列表,如果为每个事件加上大小,可以看到传输了多少字节那个时候? @kunif 如何为每个事件添加大小?我只在我的代码中构建了xmodem.PacketToSend += (s,e) =&gt; xmodem.PacketReceived += (s,e) =&gt; 这两个事件。我已经使用long length=new System.IO.FileInfo(FileName).Length 知道文件大小(以字节为单位)。 例如可以在类中为全局位置发送的字节数准备一个变量,将EventArgs.PacketToSend中减去控制数据和CRC/Checksum字节得到的值相加。每个事件的长度。 @kunif 你的意思是使用 [CRCChecksumCalculator.cs] (github.com/emancipatedMind/XmodemProtocol/blob/master/…) 的_currentByte?抱歉,我还是不太清楚。 是库当前正在处理的字节数据,在整个文件中的位置无关紧要。 【参考方案1】:

我猜你希望能够显示这样的东西:

...
SenderPacketsBeginSent
PendingCompletion
Idle

Link speed: 4.09KB/s
Transfer percentage: 34%

链接速度和传输百分比在您的控制台上更新到位?

您可以使用Console.SetCursorPosition(x, y); (https://docs.microsoft.com/en-us/dotnet/api/system.console.setcursorposition?view=net-5.0) 移动屏幕光标,将输出移动到您要显示指标的两个不同位置。

您需要自己进行转移完成计算。但这很简单:

百分比 =(传输的总字节数 / 文件大小)x 100。

因此您的程序流程将如下所示: 当您传输数据时,在您的 while 循环中,

    将屏幕光标移动到要输出“链接速度”的位置,然后在控制台上。写下您当前测量的速度。 将屏幕光标移动到要输出“传输百分比”的位置,然后使用控制台。写下您当前计算的百分比。

【讨论】:

OK....那么如何知道串口的链接速度呢?

以上是关于向串口发送数据时如何获得链接速度和传输百分比?的主要内容,如果未能解决你的问题,请参考以下文章

串口uart发送出错

ROS串口通信简析(一)——串口发送

STM32串口发送中断

#导入Word文档图片# CC2530 串口配置步骤

如何传输大容量文件

C#中怎么向串口发送数据