C# シリアル ポート データの送受信

複数のスレッドの作成と管理


https://blog.csdn.net/u010307521/article/details/50238997

1.スタート

最近、社内の上位コンピュータと機器間のシリアル通信プロジェクトに取り組み、シリアル通信ツールを自作しましたが、今日で3日目ですが、シリアルポートの双方向通信に気づきました。

2. ソフトウェアインターフェース

まずインターフェースを設計し、そこに必要な機能を実装します。 
インターフェースデザイン 
主な機能には、シリアル ポートのオープン、シリアル ポートのクローズ、シリアル ポートへのデータの送信、シリアル ポートからのデータの読み取りが含まれます。送受信のテキストボックスに、デバッグに便利な16進数の切り替え機能を追加しました。 
メイン フォームでは、シリアル ポート名やシリアル ポート バッファ データなどの関連情報を格納するためにいくつかの変数が必要です。

private string[] portNames = null;
private List<SerialPort> serialPorts;
private byte[] portBuffer;
  • 1
  • 2
  • 3
  • 4

シリアル ポート番号の選択にはドロップダウン メニューが採用されており、フォームの初期化時に使用可能なすべてのシリアル ポートをスキャンしてコンボボックスに表示する必要があります。初期化後、次のコードを追加する必要があります。

this.serialPorts = new List<SerialPort>();
this.portNames = SerialPort.GetPortNames();
this.portBuffer = new byte[1000];   
  • 1
  • 2
  • 3
  • 4

2 行目は、スキャンされたシリアル ポート名を文字列として this.portNames 配列に保存します。次に、スキャンしたシリアル ポートをコンボボックスに読み取る必要があります。

//Assign the value of port names to serial ports display
if (this.portNames.Length > 1)
{         
    for(int i = 0;i<this.portNames.Length;i++)
    {
        this.serialPorts.Add(new SerialPort(this.portNames[i]));
    }                
}
            this.portNumberComboBox1.Items.AddRange(this.portNames);             this.portNumberComboBox2.Items.AddRange(this.portNames); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上記のコードはこれを行います。この時点で、ソフトウェア インターフェイスの初期化とシリアル ポート番号の初期スキャンが完了し、その後、ボタンの応答機能を完了する必要があります。

3. シリアルポートの操作機能

シリアルポートの開閉は非常に簡単で、対応する API を直接呼び出すだけです。

private void openButton_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < this.portNames.Length; i++)
        {
            try
            {
                if (this.portNames.ElementAt(i) == this.portNumberComboBox1.Text.ToString())
                {
                    if (!this.serialPorts.ElementAt(i).IsOpen)
                    {
                        this.serialPorts.ElementAt(i).Open();
                        MessageBox.Show("已打开串口!");
                    }
                    //this.serialPorts.ElementAt(i).
                }
            }
            catch (IOException eio)
            {
                MessageBox.Show("打开串口异常:" + eio);
            }

        }
    }

    private void closeButton_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < this.portNames.Length; i++)
        {
            try
            {
                if (this.portNames.ElementAt(i) == this.portNumberComboBox1.Text.ToString())
                {
                    if (this.serialPorts.ElementAt(i).IsOpen)
                    {
                        this.serialPorts.ElementAt(i).Close();
                        MessageBox.Show("已关闭串口!");
                    }

                }
            }
            catch (IOException eio)
            {
                MessageBox.Show("关闭串口异常:" + eio);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

シリアル ポート経由でデータを送信する場合は、まずテキスト ボックスで送信する内容を読み取ってから、write 関数を呼び出す必要があります。

private void sendButton_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < this.portNames.Length; i++)
        {
            try
            {
                if (this.portNames.ElementAt(i) == this.portNumberComboBox1.Text.ToString())
                {
                    if (this.serialPorts.ElementAt(i).IsOpen)
                    {
                        string sendContent = this.sendTextBox.Text.ToString();
                        this.serialPorts.ElementAt(i).Write(sendContent);                            
                        MessageBox.Show("已发送数据!");
                    }

                }
            }
            catch (IOException eio)
            {
                MessageBox.Show("串口发送异常:" + eio);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

読み取り操作の場合、シリアル ポートには監視できる dataReceived イベントがあるため、ここではスレッドを使用せず、イベントを監視することを選択します。2 番目のコンボボックスをスキャンするタイマーを作成します。2 番目のコンボボックスが選択されると、イベントが監視されます。

private void timer1_Tick(object sender, EventArgs e)
{
    this.AddEventHandlerForResponse();
}

private void AddEventHandlerForResponse()
    {
        for (int i = 0; i < this.portNames.Length; i++)
        {
            try
            {
                if (this.portNames.ElementAt(i) == this.portNumberComboBox2.Text.ToString())
                {
                    if ((this.serialPorts.ElementAt(i).IsOpen)&&(this.serialPorts.ElementAt(i).BytesToRead > 0))
                    {
                        this.serialPorts.ElementAt(i).Read(this.portBuffer, 0, this.serialPorts.ElementAt(i).BytesToRead);
                        this.serialPorts.ElementAt(i).DataReceived += new SerialDataReceivedEventHandler(this.DataReceiveEventHandler);
                    }

                }
            }
            catch (IOException eio)
            {
                MessageBox.Show("串口异常:" + eio);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

上記のコードには、DataReceived イベントを処理する関数があります。this.DataReceiveEventHandler 
シリアル ポートの読み取り操作は比較的特殊であるため、シリアル ポートは補助スレッドを通じてバッファ データを読み取ります。読み取り操作を実行すると、UI のコンテンツが表示されます。直接変更することはできないため、テキスト ボックスで受信した内容は、invoke を通じて実現する必要があります。

private void DataReceiveEventHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    this.receiveTextBox.Invoke(
        new MethodInvoker(
            delegate 
        {
                this.receiveTextBox.AppendText(sp.ReadExisting());
                this.receiveTextBox.Text += " ";

        }
                        )
                            );
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

ここまでで、シリアルポートのオープン、シリアルポートのクローズ、読み書き動作など、シリアルポート通信の基本的な機能が実現されました。

おすすめ

転載: blog.csdn.net/u010655348/article/details/80677553