首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#为什么Serial.WriteLine()这么慢?

C#为什么Serial.WriteLine()这么慢?
EN

Stack Overflow用户
提问于 2021-10-11 19:54:12
回答 1查看 89关注 0票数 2

当我想给一个小小的3.5微控制器编程时,我会通过一个硬件串口发送一个.HEX文件给它。我有两种方法;一种方法是使用像Tera Term这样的串行通信应用程序来发送文件,另一种方法是通过我编写的一个小型C#命令行应用程序来做同样的事情。

当我向微控制器发送一个3000+行十六进制文件时,大约需要14秒。当我用我的C#程序做同样的事情时,它需要两倍的时间(或者更长!)。Tera Term和我的C#程序的波特率是相同的,当然,这两个程序的设置都很简单。当我使用数字示波器查看串行传输时,我看到了以下内容(两张照片中的时间刻度相同):

第一张照片显示了使用Tera Term时的传输,第二张照片显示了使用我的C#程序使用Serial.WriteLine()逐行传输文件内容时的传输,如下所示:

代码语言:javascript
复制
using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Timers;
using System.Diagnostics;

/*
Small console app to facilitate over-the-air (OTA) updates to a Teensy 3.x/4.x controller,
using VS2019 with the Visual Micro extension as the Arduino IDE. It is called by a post-build
'hook' statement in a file called 'board.txt' located in whatever Teensy program is 
being updated.  This app does the following:

 - Extract the project path and selected COMPORT number from the arguments to the call to Main()
 - Opens a UART serial port connection to the Teensy, typically one provided by a BT adaptor
   operating in 'pass-through' mode. The serial port COMPORT number is passed into this app
   as an argument.
 - Sends whatever command is required to put the existing Teensy firmware into 'update' mode
 - Using the path of the updating program (passed in as an argument), locates the .HEX file 
   associated with the project, and sends it's contents to the Teensy, one line at a time, counting
   lines and confirming checksums line-by-line
 - Compares the number of lines sent to the Teensy with the number of lines received by the Teensy,
   and if there is a match, allows the Teensy update process to complete; otherwise aborts
*/

namespace TeensyFlash
{  
    class Program
    {
        const string startCmdStr = "U"; //used in sketch's 'GetUserInput()' to start upload sequence
        static string rcvStr = string.Empty;
        private static System.Timers.Timer aTimer;
        private static bool bTimedOut;

        static void Main(string[] args)
        {
            //Extract the build path and selected COMPORT number from the arguments to the call to Main()
            Console.WriteLine("Teensy Flash Console");
            Console.WriteLine("Number of arguments in args = {0}\n", args.Length);
            int argindex = 0;
            string comPortStr = string.Empty;
            foreach (var item in args)
            {
                Console.WriteLine(item);
                if (item.Contains("COM"))
                {
                    comPortStr = args[argindex];
                }

                argindex++;
            }

            string build_path = args[0];
            string projectName = args[args.Length - 1];
            projectName = projectName.Substring(0, projectName.Length - 4); //remove extension
            build_path = build_path.Replace("\"", string.Empty).Trim();
            string hexfilename = build_path + "\\" + projectName + ".hex";
            Console.WriteLine("path = {0}", build_path);
            Console.WriteLine("comport = {0}", comPortStr);
            Console.WriteLine("build name = {0}", projectName);
            Console.WriteLine("path to HEX file = {0}", hexfilename);

            try
            {
                Stopwatch stopwatch = Stopwatch.StartNew();
                string[] lines = System.IO.File.ReadAllLines(hexfilename);
                foreach (string item in lines)
                {
                    Console.WriteLine(item);
                }

                Console.WriteLine("this took " + stopwatch.ElapsedMilliseconds + " Msec");



            }
            catch (Exception)
            {

                throw;
            }

            Console.WriteLine("Opening Serial Port...");

            try
            {
                SerialPort _serport = new SerialPort(comPortStr, 115200);
                _serport.WriteTimeout = 1000;
                _serport.WriteBufferSize = 20480;
                _serport.Open();
                _serport.DiscardOutBuffer();
                _serport.DiscardInBuffer();
                Thread.Sleep(100);


                Console.WriteLine("Sending Trigger Character " + startCmdStr);
                Console.WriteLine(startCmdStr);
                _serport.Write(startCmdStr);


                Console.WriteLine("Waiting for 'waiting' from Teensy...");
                rcvStr = string.Empty;
                aTimer = new System.Timers.Timer();
                //aTimer.Interval = 5000;
                aTimer.Interval = 25000;
                aTimer.Elapsed += OnTimedEvent;

                aTimer.Start();
                
                while (!rcvStr.Contains("waiting") && !bTimedOut)
                {
                    if (_serport.BytesToRead > 0)
                    {
                        rcvStr = _serport.ReadLine();
                    }
                }
                aTimer.Stop();

                if (bTimedOut)
                {
                    Console.WriteLine("Timed out waiting for 'waiting' response from Teensy");
                }
                else
                {
                    //if we get to here, the Teensy is ready to receive HEX file contents
                    Console.WriteLine("Received " + rcvStr + " from Teensy");
                     
                    Stopwatch stopwatch2 = Stopwatch.StartNew();
                    int numlines = 0;
                    string[] lines = System.IO.File.ReadAllLines(hexfilename);
                    foreach (string item in lines)
                    {
                        numlines++;
                        _serport.WriteLine(item);
                    }
                    Console.WriteLine("total lines = {0}, time = {1} mSec", numlines, stopwatch2.ElapsedMilliseconds);

                    //now we wait for Teensy to emit "hex file: xx lines xx bytes..." and then "enter xx to flash..."
                    aTimer.Start();
                    while (!rcvStr.Contains("hex file:") && !bTimedOut)
                    {
                        if (_serport.BytesToRead > 0)
                        {
                            rcvStr = _serport.ReadLine();
                        }
                    }
                    aTimer.Stop();
                    aTimer.Dispose();

                    if (bTimedOut)
                    {
                        Console.WriteLine("Timed out waiting for 'hex file' response from Teensy");
                    }
                    else
                    {
                        //extract number of lines from Teensy string, and compare with numlines.
                        //If they match, then send the number back to Teensy to complete the update.
                        //Otherwise, send '0' to abort

                        int colonIdx = rcvStr.IndexOf(':');
                        int lineIdx = rcvStr.IndexOf("lines");
                        string compareStr = rcvStr.Substring(colonIdx + 1, lineIdx - colonIdx - 1);
                        compareStr = compareStr.Trim();
                        int numTeensyLines = Convert.ToInt16(compareStr);

                        Console.WriteLine("sent {0} teensy replied {1}", numlines, numTeensyLines);
                        if (numTeensyLines == numlines)
                        {
                            Console.WriteLine("numlines {0} matches numTeensyLines {1} - send confirmation",
                                numlines, numTeensyLines);

                            _serport.WriteLine(compareStr);
                        }
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }

            try
            {

                }
            catch (Exception)
            {

                throw;
            }
        }

        static string chksum(string input)
        {
            int TwosComplement(string s)
            {
                if (s.Length % 2 != 0)
                    throw new FormatException(nameof(input));

                var checksum = 0;

                for (var i = 0; i < s.Length; i += 2)
                {
                    var value = int.Parse(s.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);

                    checksum = (checksum + value) & 0xFF;
                }

                return 256 - checksum & 0xFF;
            }

            //return string.Concat(":", input, " ", TwosComplement(input).ToString("X2"));
            return TwosComplement(input).ToString("X2");
        }
        private static void SetTimer()
        {
            // Create a timer with a two second interval.
            aTimer = new System.Timers.Timer(2000);
            // Hook up the Elapsed event for the timer. 
            aTimer.Elapsed += OnTimedEvent;
            //aTimer.AutoReset = true;
            aTimer.Enabled = true;
        }

        private static void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
                              e.SignalTime);
            bTimedOut = true;
        }
    }

}

实际执行文件传输的代码是:

代码语言:javascript
复制
Stopwatch stopwatch2 = Stopwatch.StartNew();
int numlines = 0;
string[] lines = System.IO.File.ReadAllLines(hexfilename);
foreach (string item in lines)
{
    numlines++;
    _serport.WriteLine(item);
}
Console.WriteLine("total lines = {0}, time = {1} mSec", numlines, stopwatch2.ElapsedMilliseconds);

当'_serport.WriteLine(item);‘行被注释掉时,报告的运行时间是0 mSec,正如预期的那样-因此'ReadAllLines()’步骤不是问题。

有没有人知道为什么'WriteLine(item)‘处理这么慢?

EN

回答 1

Stack Overflow用户

发布于 2021-10-11 20:09:43

这取决于设备的方法本身的结构,但我在同一网站上找到了一个可以帮助你的查询和方法

stackoverflow: console writeline slow

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69531785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档