如何在 RS232 串口和本地笔记本电脑之间获取命令历史记录?

Posted

技术标签:

【中文标题】如何在 RS232 串口和本地笔记本电脑之间获取命令历史记录?【英文标题】:How to have command history between RS232 Serial Port and local laptop? 【发布时间】:2021-11-30 16:59:01 【问题描述】:

我正在开发一个C# Console app 来与 SAS 扩展卡上的固件进行交互。

卡是通过RS232端口连接的。

我已经发送了一个命令,并且在控制台应用程序上得到了结果。

现在我想要一个记录命令的功能。

当我使用PuTTY发送命令时,

我意识到当我按下UpArrow 键时,它会显示最后一个命令。

这是PuTTY的结果:

在按下UpArrow Key之前→

UpArrow Key后→

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.IO.Ports;
using System.Threading;

namespace ConsoleApp3

    class Program
    
        [STAThread]
        static void Main()
        

            SerialPort mySerialPort = new SerialPort("COM5");

            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.Open();
            if (mySerialPort.IsOpen)
            

                mySerialPort.Write("\r");

            
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            while (true)
            
                
                if (Console.KeyAvailable)
                
                    ConsoleKeyInfo userResponse = Console.ReadKey(true);
                    List<string> Command = new List<string>();
                    if (userResponse.KeyChar.ToString() == "s")
                    
                        Command.Add("s");
                        mySerialPort.Write("s");

                    
                    else if (userResponse.KeyChar.ToString() == "y")
                    
                        Command.Add("y");
                        mySerialPort.Write("y");

                    
                    else if (userResponse.Key == ConsoleKey.UpArrow)
                    

                        for (int i = 0; i < Command.Count; i++)
                        
                            Console.WriteLine(Command[i]);

                        
                        Console.ReadLine();
                        Command.Clear();
                    
                    else
                    
                        mySerialPort.Write("\r");
                        
                    
                 
            
        
        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
            Console.Write(indata);
        

    


代码的结果是什么:

当我按UpArrow 键两次时,应用程序显示两个空格供输入。

那是图片中的第二个bp1&gt;

图片如下:

enter键后,又出现bp1&gt;

我开始发送sys命令并没有得到响应,但它出现了一个空格。

当我再次按下EnterUpArrow 键后,sys 命令出现。

我的代码有什么问题?

还有其他改进的方法吗?

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

【问题讨论】:

例如,为什么不合并和应用这样的项目呢? mono/LineEditor 最好在向设备发送正常击键的同时缓冲历史记录,使用向上/向下光标键进入此类编辑器模式,编辑历史记录然后重新发送结果字符串。 【参考方案1】:

更好的方法是使用mono/LineEditor,kunif 在 cmets 中怎么说。另一种方式是这样的:

using System;
using System.Collections.Generic;
using System.IO.Ports;

namespace ConsoleApp3

    class Program
    
        static void Main()
        

            SerialPort mySerialPort = new SerialPort("COM5");

            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";     // implement this if you use "string indata = sp.ReadLine();" in event handler
            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");
                    ClearCurrentConsoleLine();
                    command = "";
                
                else if (consoleInput.Key == ConsoleKey.UpArrow)
                
                    if ((counter >= 0) && (counter < Commands.Count))
                    
                        ClearCurrentConsoleLine();
                        Console.Write(Commands[counter]);
                    

                    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();      // it might be better to use --> string indata = sp.ReadLine();
            Console.Write(indata);
        

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

我在没有串行通信的情况下测试了代码。如果您清除我的 cmets,串行通信应该可以工作。

【讨论】:

以上是关于如何在 RS232 串口和本地笔记本电脑之间获取命令历史记录?的主要内容,如果未能解决你的问题,请参考以下文章

UART,串口,RS232,RS485等等,之间有啥联系和区别?

请问RS232-C接口的特点及典型应用,谢谢!!

如何修复 rs232 串口超时?

电脑如何和三菱Q系列PLC通讯

FANUC(法那科)数控机床与电脑连接

9针串口RS232RS485之间的差异