C#でシリアル通信する方法をメモ WPF

C#でシリアル通信する方法をメモ WPF

C#でシリアル通信を行う方法を書いておきます。確認用の最小構成のコードも載せておきます。

 

Windows10, Visual Studio 2017, WPF

ポートの選択と接続、切断、テキストボックスのテキスト送信ができます。

(仮装ポートには対応していません)

 

ポート設定はリファレンスを参照
https://msdn.microsoft.com/ja-jp/library/system.io.ports.serialport

その他参考

C#でシリアル通信を行う
http://kana-soft.com/tech/sample_0007.htm

 

MainWindow.xaml

<Window x:Class="testapp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:testapp"
        mc:Ignorable="d"
        Title="MainWindow" Height="247.72" Width="395.44">
    <Grid>
        <ComboBox Name="cmb" HorizontalAlignment="Left" Margin="4,10,0,0" VerticalAlignment="Top" Width="120"/>
        <Button Name="connect" Content="接続" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="4,38,0,0" Click="connect_Click"/>
        <Button Name="disconnect" Content="切断" HorizontalAlignment="Left" Margin="84,38,0,0" VerticalAlignment="Top" Width="75"/>
        <TextBox Name="sendText" HorizontalAlignment="Left" Height="23" Margin="4,64,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
        <Button Name="send" Content="送信" HorizontalAlignment="Left" Margin="129,64,0,0" VerticalAlignment="Top" Width="75" Click="send_Click"/>
    </Grid>
</Window>

 

MainWindow.xaml.cs

using System;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Text;
using System.Windows;

namespace testapp
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            selPort();
        }
        System.IO.Ports.SerialPort serialPort = null;
        public class ComPort
        {
            public string DeviceID { get; set; }
            public string Description { get; set; }
        }

        /*----------------------------
         * シリアルポート列挙
         *---------------------------*/
        private void selPort()
        {
            // シリアルポートの列挙
            string[] PortList = SerialPort.GetPortNames();
            var MyList = new ObservableCollection<ComPort>();
            foreach (string p in PortList)
            {
                System.Console.WriteLine(p);
                MyList.Add(new ComPort { DeviceID = p, Description = p });
            }
            cmb.ItemsSource = MyList;
            cmb.SelectedValuePath = "DeviceID";
            cmb.DisplayMemberPath = "Description";
        }

        /*----------------------------
         * 接続ボタンを押した時の処理
         *---------------------------*/
        private void connect_Click(object sender, RoutedEventArgs e)
        {
            // ポートが選択されている場合
            if (cmb.SelectedValue != null)
            {
                // ポート名を取得
                var port = cmb.SelectedValue.ToString();
                // まだポートに繋がっていない場合
                if (serialPort == null)
                {
                    // serialPortの設定
                    serialPort = new SerialPort();
                    serialPort.PortName = port;
                    serialPort.BaudRate = 9600;
                    serialPort.DataBits = 8;
                    serialPort.Parity = Parity.None;
                    serialPort.StopBits = StopBits.One;
                    serialPort.Encoding = Encoding.UTF8;
                    serialPort.WriteTimeout = 100000;

                    // シリアルポートに接続
                    try
                    {
                        // ポートオープン
                        serialPort.Open();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        /*----------------------------
         * 切断ボタンを押した時
         *---------------------------*/
        private void disconnect_Click(object sender, RoutedEventArgs e)
        {
            // 既に繋がっているか確認処理を入れたほうが良い。
            serialPort.Close();
            serialPort = null;
        }

        /*----------------------------
         * 送信ボタンを押した時
         *---------------------------*/
        private void send_Click(object sender, RoutedEventArgs e)
        {
            // 繋がっていない場合は処理しない。
            if (serialPort == null) return;
            if (serialPort.IsOpen == false) return;

            // テキストボックスから、送信するテキストを取り出す。
            String data = sendText.Text + "\r\n";

            try
            {
                // シリアルポートからテキストを送信する.
                serialPort.Write(data);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

 

コマンドラインだとポート選択が毎回面倒なのでこんな小構成でも作っておくと便利。

 


 

追記 2018-10-17

メッセージの受信方法。上記のコードをそのまま利用します。

MainWindow.xaml.cs シリアルポートの設定に追加

private void connect_Click(object sender, RoutedEventArgs e)
{
    if (cmb.SelectedValue != null)
    {
        if (serialPort == null)
        {
            //ここまで一部を省略
            serialPort.WriteTimeout = 100000;

            //新たに追加 データ受信時のイベントを設定 関数は後述のserialPort_DataReceived
            serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);

MainWindow.xaml.cs

//データ受信イベントで呼び出される関数
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    // 繋がっていない場合は処理しない。
    if (serialPort == null) return;
    if (serialPort.IsOpen == false) return;

    try
    {
        //! 受信データを読み込む.
        string data = serialPort.ReadExisting();

        //! 受信したデータをテキストボックスに書き込む.
        Console.WriteLine(data);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

ほぼ参考ページのままです。

.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(fnc);

データ受信時のイベントハンドラを追加。fncに関数を指定。

今回はコンソールにメッセージを表示するように。

コンソールを表示しておくにはプロジェクトのプロパティ(プロジェクトを右クリックから選ぶ、またはメニューのプロジェクトから選ぶ)の出力の種類をコンソールアプリケーションに変更しておきましょう。

直接コントロールを操作してメッセージを表示したりする場合はInvokeメソッドを利用したりします。

 

この記事へのコメント

  1. 名前:名無しさん 2018/10/17(水) 16:44:20返信する

    拝見させていただきました.
    逆にWPFを用いてシリアルを受信するにはどうしたらよいのでしょうか?

  2. 名前:hyper_T 2018/10/17(水) 16:58:45返信する

    >>1
    すぐに個別に解説できないので他に解説されている参考ページを紹介させていただきます。
    C#でシリアル通信を行う(その4)

  3. 名前:名無しさん 2018/10/17(水) 17:11:49返信する

    迅速な対応,誠にありがとうございます.
    お時間があるときで構いませんので,そのような記事を書いていただけると幸いです.

  4. 名前:hyper_T 2018/10/17(水) 18:46:16返信する

    >>3
    追記しておきました。ほとんど参考ページのままです。
    この記事で紹介したコードに追記部分を足すことで確認できると思います。
    シリアルから受信したメッセージの内容や利用方法などは各環境でことなるので・・・。

  5. 名前:名無しさん 2018/10/18(木) 11:00:47返信する

    >>4
    迅速な対応,誠にありがとうございました.大変助かりました…

コメントを残す

メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。URLを含むコメントは承認待ちになります。