2

みなさん、こんにちは。私はここで初めてです。このWebサイトについて、本当に役立つと聞いています。あなたが私を助けてくれることを願っています!

私は非常に単純なプログラムを持っています。その唯一の目的は、シリアルポートから読み取り、それをC#のコンソールウィンドウに2000回印刷することです。

マイクロコントローラーの可変抵抗器を回しているだけです。

以下はコードです

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

namespace Testing_serial_v3._0
{
    class Program
    {
        static void Main(string[] args)
        {

            string buff;


            SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
            port.Open();

            for (int i = 0; i < 2000; i++)
            {


                buff = port.ReadLine();
                Console.WriteLine(buff);
                //Console.ReadLine();
            }
        }
    }
}

しかし、このコードでは面白いことが起こっています。上記のコードに示されているようにコンソールreadlineがコメント化されると、可変抵抗器のノブを回すとポートからの値が変化します。つまり、これは正常に機能していることを意味します。一方、readlineを実行して、各値の後にキーを押す必要がある場合、ポートは現在の値を読み取り、ノブを変更してEnterキーをもう一度押しても、値はリセットされていないかのように最初のままになります。まったく?

ポートがリセットされるように、他のコマンドラインを含める必要がありますか?

あなたが私の問題とあなたが知る必要がある他の質問を理解することを願っています。私が本当にこの問題をできるだけ早く修正する必要があることを躊躇しないでください。よろしくお願いします

4

3 に答える 3

2

ポートを通過するデータはストリームです。読み取りを行うと、ストリームが徐々に消費されます。「最新の値」が表示されているのではなく、「ストリーム内の次の値」が表示されています。読み取り行を追加すると、遅延が追加されます。これは、大量のデータのバックログがあることを意味します。「同じままだった」というわけではありません...単に最後まで(そして最近の値を)まだ読んでいないということです。

多くの場合、ストリームからの値の読み取りが人間のデータ入力のような遅延に結び付けられないように、非同期コールバックを介してネットワーク IO を処理することが望ましいでしょう。ただし、それにはスレッド化の知識が必要になる場合があります。

于 2012-11-24T09:30:47.960 に答える
2

Task を使用して別のスレッドで読み取り、そこで観察することもできます。@Marc Gravel が言及しているようなものです。タスクが完了するまで待つか、Enter キーを押して手動でキャンセルする必要があります。タスクを別のスレッドにオフロードするもう 1 つの例です。

次に例を示します。

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ReadStreamAsyncTask
{
    internal class Program
    {
        private static CancellationToken _cancelTaskSignal;
        private static byte[] _serialPortBytes;
        private static MemoryStream _streamOfBytesFromPort;
        private static CancellationTokenSource _cancelTaskSignalSource;

        private static void Main()
        {
            _serialPortBytes = Encoding.ASCII.GetBytes("Mimic a bunch of bytes from the serial port");
            _streamOfBytesFromPort = new MemoryStream(_serialPortBytes);
            _streamOfBytesFromPort.Position = 0;

            _cancelTaskSignalSource = new CancellationTokenSource();
            _cancelTaskSignal = _cancelTaskSignalSource.Token; // Used to request cancel the task if needed.

            var readFromSerialPort = Task.Factory.StartNew(ReadStream, _cancelTaskSignal);
            readFromSerialPort.Wait(3000); // wait until task is complete(or errors) OR 3 seconds

            Console.WriteLine("Press enter to cancel the task");
            _cancelTaskSignalSource.Cancel();
            Console.ReadLine();
        }

        private static void ReadStream()
        {
            // start your loop here to read from the port and print to console

            Console.WriteLine("Port read task started");

            int bytesToReadCount = Buffer.ByteLength(_serialPortBytes);
            var localBuffer = new byte[bytesToReadCount];

            int bytesRead = 0;

            bool finishedReading = false;

            try
            {
                while (!finishedReading)
                {
                    _cancelTaskSignal.ThrowIfCancellationRequested();

                    bytesRead += _streamOfBytesFromPort.Read(localBuffer, 0, bytesToReadCount);

                    finishedReading = (bytesRead - bytesToReadCount == 0);
                }
            }
            catch (TaskCanceledException)
            {
                Console.WriteLine("You cancelled the task");
            }

            Console.WriteLine(Encoding.ASCII.GetString(localBuffer));
            Console.WriteLine("Done reading stream");
        }
    }
}
于 2012-11-24T10:31:58.993 に答える
1

マイクロコントローラーからシリアルポートに何千ものデータを送信しています(例では1ミリ秒の遅延があります)。これにより、シリアルポートのバッファーが同じ値で満たされます。エンターキーを押して1つずつ読むと、最初に受け取ったものを読んでいます...

「Enter」キーでコンピューターのデータを読みたい場合は、プッシュボタンでマイクロコントローラーから日付を送信する必要があると思います。抵抗器で値を設定し、プッシュボタンを押すと、マイクロが「1バイト」をコンピューターに送信します。コンピューターの Enter キーを押すと、コンピューターはシリアル ポートから「1 バイト」だけを読み取ることができます。

また、コードにいくつかの変更を加えます:

static void Main(string[] args)
{
    int buff;  // string to int

    SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
    port.Open();

    for (int i = 0; i < 2000; i++)
    {
        Console.ReadLine();  // wait for the Enter key
        buff = port.ReadByte();  // read a byte
        Console.WriteLine(buff);
    }
}

これがうまくいくことを願っています!:)

于 2012-11-24T10:02:47.530 に答える