質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

C# SerielPortで機器の初期化でレスポンスが戻ってこない

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,288

TrainRain

score 20

こんにちは。

 前提・実現したいこと

先日はXORについてご回答いただき、ありがとうございました。

Windows10を使ってVisual Studo 2017でWindows Formアプリケーションのプロジェクトを作っています。
DensoのQK20-ICというICカード読み取り機でICカードを読もうとしています。

 試したこと

QK20-ICのセットアップは完了しており、COM4に接続しています。
他のアプリケーションでは動作しているので、接続は確実です。

まず、Initializeしてみようとしています。

Formに

SerialPort ComIcCard;
TextBox ReceivedData;


を配置しました。

これでシリアルポートを初期化してコマンドを実行しているだけなので、レスポンスが戻って当然と思っているのですが、戻ってきません。
原因のヒントなどアドバイスをいただければ幸いです。

 発生している問題・エラーメッセージ

ComIcCard_DataReceivedで待ち受けているがレスポンスが戻ってこない。
レスポンスイベントが発生しません。

 該当のソースコード

        private void Initialize_Click(object sender, EventArgs e)
        {
            var command = 排他的論理和XOR();
            OpenRS232C();
            string text = System.Text.Encoding.ASCII.GetString(command.ToArray());
            ComIcCard.Write(text);//\b\0\u0005\0\u0001\0\0\u0001\r
        }

        delegate void SetTextCallback(string text);
        private void Response(string text)
        {
            if (ReceivedData.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(Response);
                BeginInvoke(d, new object[] { text });
            }
            else
            {
                ReceivedData.AppendText(text + "\r\n");
            }
        }

        private void ComIcCard_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                string receivedtext = ComIcCard.ReadLine();
                Response(receivedtext);
            }
            catch (Exception ex)
            {
                string error = ex.Message;
            }
        }

        public bool OpenRS232C()
        {
            ComIcCard = new SerialPort()
            {
                PortName = "COM4",
                BaudRate = 9600,
                Parity = Parity.None,
                DataBits = 8,
                StopBits = StopBits.One
            };
            ComIcCard.DataReceived += ComIcCard_DataReceived;
            try
            {
                ComIcCard.Open();
            }
            catch (Exception ex)
            {
                ProjectData.SetProjectError(ex);
                ProjectData.ClearProjectError();
                return false;
            }
            return true;
        }
        public List<byte> InitializeCommands = new List<byte> { 0x08, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x01 };

        public List<byte> 排他的論理和XOR()
        {
            byte answer0 = 0x08 ^ 0x00;
            byte answer1 = (byte)(answer0 ^ 0x05);
            byte answer2 = (byte)(answer1 ^ 0x00);
            byte answer3 = (byte)(answer2 ^ 0x01);
            byte answer4 = (byte)(answer3 ^ 0x00);
            byte answer5 = (byte)(answer4 ^ 0x00);
            byte answer6 = (byte)(answer5 ^ 0x01);
            InitializeCommands.Add(answer6);
            return InitializeCommands;
        }
//メインのリセット(初期化)コマンドは、9バイトのコマンドからなる。
//各値の意味は次のとおり。
//-----------------------------------------------------------------------------
//                値        byte数        説明
//-----------------------------------------------------------------------------
//RCB            08h        1byte        リーダライタコマンド
//-----------------------------------------------------------------------------
//LEN(length)    00h 05h    2byte        DAT部(CLA, INS, P1, P2, Le)の長さ(=5byte)。
//CLA(clear?)    00h        1byte        固定
//INS(insert?)    01h        1byte        メインリセットコマンド
//P1                00h        1byte        固定
//P2                00h        1byte        固定
//Le(?)            01h        1byte        固定
//-----------------------------------------------------------------------------
//BCC                ?        1byte        ブロック検査符号。RCBからBCCまでの排他的論理和を00hにする値。->ちなみに1316進数では0x0D

 補足情報(FW/ツールのバージョンなど)

Intel Pentium(R) CPU 4415 Y 1.60GHz
RAM 8GB
Windows10Pro 64bit 1803 17134.345 
Microsoft Visual Studio Community 2017 
Version 15.8.5
VisualStudio.15.Release/15.8.5+28010.2036
Microsoft .NET Framework
Version 4.7.03056 
インストールされているバージョン:Community 
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

まず、そのICカードリーダのコマンド体系はどういうものであるのか、初期化部分だけでいいので提示してください。

コードを見るに、そのICカードリーダというのはバイナリデータのコマンド/レスポンスになると思われますが、コードではデータの読み出しにreadlineを使ってます。
これはテキストデータを1行読み出すというメソッドになります。
また、データ送信にしても、バイナリデータをムリヤリ文字列として送信してるようにみえますが、これもまたまずいかと思われます

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/03 16:24

    コメントありがとうございます。
    バイナリにしてみます。

    マニュアルを読み込めていないのですが、初期化コマンドは、
    0x08, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x01, 0x13(XORの計算値)
    でOKと思います。
    質問に追記します。

    キャンセル

  • 2018/12/03 16:44

    送信をバイナリ送信にして、受信イベント中でもデータ構成を見てメッセージ終了を判断する、ってテですね

    キャンセル

  • 2018/12/03 18:13

    var command = 排他的論理和XOR();
    OpenRS232C();
    //バイナリデータを送信する。Write(byte[] buffer, int offset, int count)
    ComIcCard.Write(command.ToArray(), 0, 9);//\b\0\u0005\0\u0001\0\0\u0001\r
    としてみたのですが、依然DataReceivedは発生しませんでした。
    イベントが発火しさえすればと思うのですが…。なにが欠けているでしょう?

    キャンセル

  • 2018/12/03 18:27

    ボーレートやパリティ、ビット長はあってるか、実際に送信してるか、ホンマに受信してないのか、オシロで信号を確認してみるとかですねー

    キャンセル

0

確認事項として、DataReceivedイベントが発生していないのでしょうか?
それとも発生して、ReadLineが帰ってこないのでしょうか?

後者である場合、SerialPort.ReadLineメソッドにあるようにNewLine値まで読み込もうとしますので、NewLine値(\r\n)を受信するまで帰ってこなくなります。
(正確にはSerialPort.ReadTimeoutに設定した時間ですが、規定値はInfiniteTimeoutとなっています)
ですので、ご使用機器の通信プロトコルを確認してください。
コマンドの終端がNewLine値ではない場合、SerialPort.ReadLineメソッドを使用するのは不適切となります。

送信コマンドはASCIIコードでの送信が正しいのでしょうか?
ぱっと見た感じ、バイナリでの送信が正しそうなデータだと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/03 16:20

    コメントありがとうございます。
    DataReceivedイベントが発生しません。
    バイナリにしてみます。

    キャンセル

  • 2018/12/03 16:45

    var command = 排他的論理和XOR();
    OpenRS232C();
    //バイナリデータを送信する。Write(byte[] buffer, int offset, int count)
    ComIcCard.Write(command.ToArray(), 0, 9);//\b\0\u0005\0\u0001\0\0\u0001\r
    としてみたのですが、依然DataReceivedは発生しませんでした。

    キャンセル

  • 2018/12/03 20:22

    ぱっと見た感じ合ってそうですので、y_waiwaiさんがおっしゃる通り、通信設定を確認、プロトコルアナライザー等のシリアルをモニタできる環境を調えて実際の通信データを確認するのが解決の早道のような気はします。
    私は使用したことがありませんが、PortMon(https://technet.microsoft.com/ja-jp/sysinternals/bb896644)が使えるかもしれません。
    モニタ出来るようであれば、実際に通信を行っている他のアプリケーションの通信もモニタできるはずですから、比べてみるとよろしいかと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る