如何读取串行数据。 [英] How can I read serial data.

查看:160
本文介绍了如何读取串行数据。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个GUI应用程序。应用程序需要读取串行数据。我需要处理1个字节。我已经建立了一个串行连接。我目前正在使用arduino向我发送一些文字。

I am building a GUI application. And the application needs to read serial data. I need to process 1 byte at the time. I have already set up a serial connection. I am currently using an arduino which sends me some text.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            setupSerialConnection();
            

            SerialPort Serial = new SerialPort();
            Serial.BaudRate = 115200;
            Serial.PortName = "COM3";
            Serial.DataBits = 8;
            Serial.Open();
            Serial.DataReceived += new SerialDataReceivedEventHandler(Serial_available);
        }

        public void Serial_available(object sender, SerialDataReceivedEventArgs e)
        {                    
            SerialAvailable('a'); // currently sends the letter 'a'
        }

        private void setupSerialConnection()
        {
            String[] portNames = SerialPort.GetPortNames();

            for (int i = 0; i < portNames.Length; i++)
            {
                textBox1.Text += portNames[i];
                textBox1.Text += '\r';
                textBox1.Text += '\n';
            }     
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void SerialAvailable(char c)
        {
            MethodInvoker inv = delegate
            {
                this.textBox1.Text += c; 
            };
            this.Invoke(inv);

        }
    }
}

我已经注意到处理过程显着比接收慢,这意味着我没有为每个接收到的字节得到'a'。我知道我需要把它们放在一个缓冲区数组中,并从那里读取。

I have already noticed that the processing goes significantly slower than the receiving, meaning I am not getting an 'a' for every received byte. I understand that I need to stuff them in a buffer array, and read from there.

所以在我浪费一大堆时间,谷歌搜索和尝试外面之前,我认为更好的来吧这个论坛并询问有经验的人。

So before I go waste a bucketload of time, googling and trying things out, I figured better come on this forum and ask experienced people.

推荐答案

首先提出一些建议:

First a few suggestions:

方法" ; setupSerialConnection"没有做它所说的,而是显示连接的端口。将串行设置的代码移动到该方法中,并将mothod中的代码移动到另一个新方法("printConnectedPorts"),以便
代码可读。

The method "setupSerialConnection" does not do what it says it does, instead it display connected Ports. Move the Code of the Serial setup into that method and the code inside the mothod to another new method ("printConnectedPorts") so that the Code is readable.

您的EventHandler Serial_available可以理解为想要连接的新SerialPort,将Handler重命名为"Serial_dataIncoming"。

Your EventHandler Serial_available could be understand as a new SerialPort wanting to connect, rename that Handler to something like "Serial_dataIncoming".

重命名"SerialAvailable"。 to"UpdateSerialDataText"。

Rename the "SerialAvailable" to "UpdateSerialDataText".

尽可能避免使用this关键字,只是搞砸了可读性而没有任何目的。

Avoid the this keyword wherever possible, it is just messing up the readability and has no purpose.

重命名是你可能会在它完成之后再回到这段代码然后不明白你做了什么因为命名建议不同的行为然后是方法体。还要记住,也许其他人(比如现在正确的
)正在阅读代码并且不理解它只是因为命名已关闭。

The reason for renaming is that you probably will come back to this code after it was long finished and then dont understand what you've done cause the naming suggests different actions then the method bodies. Also keep in mind that maybe others (like right now) are reading the code and dont understand it just cause the naming is off.

现在问题,首先制作一个您的Serial的classMember,以便在离开构造函数后,Serial仍然可用,而GarbageCollector不会选择它。它可能适用于第一个char到达或更多,因为GrabageCollector会立即清理
但是在Grabage Collector命中之后它不应该收到任何字符。 

Now to the issue, first make a classMember of your Serial so that after leaving the Constructor the Serial is still available and not picked up by the GarbageCollector. It might work for the first char arriving or some more since the GrabageCollector does not clean up immediately but it should not receive any chars after the Grabage Collector hit. 

然后我建议你把收到的真实数据交给EvenHandler并让你的adrunino发送不同的字符,可能只是从0x30(字节的十六进制表示)向上到0x5A,即字符'0'到'Z',其间有一些特殊的字符。以
的方式你会知道哪个Byte被遗漏了(如果有的话,我怀疑)。还可以通过Debugger.Write将一些日志记录添加到Handler中,以便查看收到的数据。然后还在你调用的代码中添加一个Debugger.Write,将收到的char绘制到你的表单上
(我的猜测是表单的更新会使字符消失或被卡住)。

Then i suggest you give the real data received to the EvenHandler and make your adrunino send different chars, probably just from 0x30 (Hex presentation of the Byte) upwards to 0x5A, that are characters '0' to 'Z' with some special chars in between. That way you will know which Byte was left out (if any, which i doubt). Also add some logging via Debugger.Write to the Handler, so that you see what data was received. Then also add a Debugger.Write to the code you call to draw the received char onto your form (my guess is that the updating of the Form is making the characters disappear or be jambled up).

将接收到的字符写入StringBuilder并将绑定(如果使用WPF)Text属性绑定到返回StringBuilder.ToString的Property可能是个好主意。但是,这可能会导致一些线程问题,所以为了避免
,你需要在添加字符时锁定StringBuilder。您也可能想使用Dispatcher.Invoke(()=> this.textBox1.Text = StringBuilder.ToString())而不是MehtodInvoker。那个MethodInvoker没有真正的用途。如果你不使用WPF绑定,这也适用于
,特别是一旦你将Serial移动到你可能想要保持UI被动的其他线程上下文。

It probably is a good idea to write the received chars into a StringBuilder when received and to bind (if you use WPF) the Text Property to a Property that returns StringBuilder.ToString. However, this will probably lead to some Threading issue, so to avoid that, you would need to lock the StringBuilder when adding chars. You also might wanna use the Dispatcher.Invoke(() => this.textBox1.Text = StringBuilder.ToString()) instead of MehtodInvoker. That MethodInvoker has no real purpose there. This also applies if you dont use WPF binding, especially once you move the Serial to an other Thread Context which you probably want to do to keep the UI reactive.

BTW,只要您对使用Windows窗体执行此操作没有任何要求,请考虑转移到WPF。 Froms已经过时了。如果您有要求在表单中执行此操作,请尝试说服任何人让您转到WPF。它在UI
Reactivity中具有很大的好处,并且将比Windows Forms(由Microsoft)维护更长时间。

BTW, so long as you dont have any requirements in doing this with Windows Forms, please consider moving to WPF. Froms is outdated. And if you have requirements to do it in Forms, try convincing whomever to let you move to WPF. It has great benefits in UI Reactivity and will be maintained longer than Windows Forms (by Microsoft).


这篇关于如何读取串行数据。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆