2016-12-28 6 views
0

私は大学で私のコースの1つで使用されるプログラムをC#でビルドしています。非同期接続は、RS-232と2台のコンピュータを使ってどのように動作するのかを実証します。私のコースはプログラミングではなく、データネットワークなので、接続性は私が探しているものです。私は私のプログラムで実装したい機能のシリアルポートの入力バッファを知るには、C#で情報がありますか?

picture 1 - sample layout of GUI using Visual Studio 2015

一つが表示される方法をマスター・スレーブ、シンプレックス接続工事(すなわち、キーボードからの入力を送信するためにマスターしてから選ぶことができますプログラム、またはスレーブは情報を受信して​​テキストボックスに印刷するだけです)。

私は既にシリアルポートを特定の特性(ボーレート、データビット、ストップビットなど)で初期化することができます。この機能は、GUIのコンボボックスを使用して選択され、ユーザがボタンをクリックして「ポートを開く」ときにポートに割り当てられます。

わからないのは、プログラムの「スレーブ」部分を作成する方法です。私ができることの私の考えは、あなたが "スレーブ"になるプログラムを選択した後、入力バッファにデータが格納されているときに何らかのフラグやイベントが発生するのを待つポートを開きます。

私はいくつかのフォーラムを読んでいて、必要なものに似たものは見つけられません。しかし、私は、私が必要としているものに近づかせると信じていた複数の選択肢をテストしました。私は何が間違っているのか、この問題に取り組む方法についての提案を求めるようになりました。問題のある行は、太字(または2つ星(*))は次のとおりです。

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 SerialCommTester 
{ 
public partial class frmSerialComm : Form 
{ 
    static SerialPort _PuertoSerial; 

    public frmSerialComm() 
    { 
     InitializeComponent(); 
     getAvailablePorts(); 
    } 

    //---------------------------------my functions-------------------------------------- 
    void getAvailablePorts() 
    { 
     string[] ports = SerialPort.GetPortNames(); 
     cmbPortList.Items.AddRange(ports); 
    } 

    void activatePort() 
    { 
    //Note that all the combo boxes are named somewhat accordingly to what the information they are meant to display. 
     if (cmbPortList.Text != "" && cmbBaudRate.Text != "" && cmbParity.Text != "" && cmbStopBits.Text != "") 
     { 
      _PuertoSerial.PortName = cmbPortList.Text; 
      _PuertoSerial.BaudRate = Convert.ToInt32(cmbBaudRate.Text); 
      _PuertoSerial.RtsEnable = true; 
      _PuertoSerial.DtrEnable = true; 

      _PuertoSerial.DataBits = Convert.ToInt32(cmbDataBits.Text); 

      if (cmbParity.Text == "Even") { _PuertoSerial.Parity = Parity.Even; } 
      else if (cmbParity.Text == "Odd") { _PuertoSerial.Parity = Parity.Odd; } 
      else if (cmbParity.Text == "Space") { _PuertoSerial.Parity = Parity.Space; } 
      else if (cmbParity.Text == "Mark") { _PuertoSerial.Parity = Parity.Mark; } 
      else { _PuertoSerial.Parity = Parity.None; } 

      if (cmbStopBits.Text =="2") { _PuertoSerial.StopBits = StopBits.Two; } 
      else if (cmbStopBits.Text == "1.5") { _PuertoSerial.StopBits = StopBits.OnePointFive; } 
      else { _PuertoSerial.StopBits = StopBits.One; } 

      if (cmbHandShake.Text == "Software Flow Control") { _PuertoSerial.Handshake = Handshake.XOnXOff; } 
      else if (cmbHandShake.Text == "Hardware Flow Control") { _PuertoSerial.Handshake = Handshake.RequestToSend; } 
      else { _PuertoSerial.Handshake = Handshake.None; } 

      _PuertoSerial.ReadTimeout = 500; 
      _PuertoSerial.WriteTimeout = 500; 

      _PuertoSerial.Open(); 
//in my understanding, this line of code is needed to handle data being received. Does it trigger a flag or something? 
      **_PuertoSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);** 
     } 
     else 
     { 
      txtRecieve.Text = "Input selection missing 1 or more characteristics"; 
     } 
    } 

    ** 
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
    { 
     SerialPort testing = (SerialPort)sender; 
     txtRecieve.AppendText(testing.ReadExisting()); //txtRecieve cannot be reached within this function. It indicates the following error: "An object reference is required for the non-static field, method, or property 'frmSerialComm.txtRecieve' 
    } 
    ** 

    void enableDisableGUI(bool[] input) 
    { 
     grpConnection.Enabled = input[0]; 
     grpCharacteristics.Enabled = input[1]; 
     btnOpenPort.Enabled = input[2]; 
     btnClosePort.Enabled = input[3]; 
     txtSend.Enabled = ((cmbControlMasterSlave.Text == "Slave") ? false : true); 
    } 

    //----------------------------C# objects/functions-------------------------------------- 
    private void btnOpenPort_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      _PuertoSerial = new SerialPort(); 
      activatePort(); 
     } 
     catch(Exception ex) 
     { 
      MessageBox.Show(ex.Message, "Message ", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 

     bool[] format = { false, false, false, true}; 
     enableDisableGUI(format); 
    } 

    private void btnClosePort_Click(object sender, EventArgs e) 
    { 
     _PuertoSerial.Close(); 
     bool[] format = { true, true, true, false}; 
     enableDisableGUI(format); 
    } 

    private void txtSend_KeyPress(object sender, KeyPressEventArgs e) 
    { 
     _PuertoSerial.Write(e.KeyChar.ToString()); //this is how I send data through the serial port. 
    } 

    private void btnClearTxts_Click(object sender, EventArgs e) 
    { 
     txtRecieve.Clear(); 
     txtSend.Clear(); 
    } 

} //class closes 
} //program closes 

私はちょうど私の学生のために有用なものを作りたい、経験豊富なプログラマではありませんよ。どんな建設的な批判も高く評価されます。

答えて

0

私はあなたに決定的な答えがありません。 2つの可能性のある不具合を乗り越えたら、必要なものを提供する必要があります。

  1. 私はあなたが_PuertoSerial.Open()を呼び出し 前に、あなたのSerialDataReceivedEventHandlerを添付しなければならないと思います。

    通常、イベントハンドラは動的に有効/無効にできるので効果がない可能性がありますが、MSDNの.Netソースコードから得た以下のコメントに基づいています。

    //すべての魔法は、インスタンスの.Open()メソッドの呼び出しで発生します。

    //内部的に、SerialStreamコンストラクタはファイルハンドルを開き、デバイスコントロールブロックと関連するWin32構造体を設定し、イベント監視サイクルを開始します。

  2. 静的修飾子をDataReceivedHandlerから削除すると、「オブジェクト参照」エラーが解決される場合があります。そうでない場合や何らかの理由で 静的修飾子が必要な場合は、おそらく txtRecieveコントロールにprivate修飾子があり、 をinternalまたはpublicに変更する必要があります。 デバッグモードでVisual Studioを使用してInitializeComponent()メソッドにステップインし、txtRecieveがインスタンス化されている を参照する必要があります。

+0

助けてくれてありがとう! – DonPandon

0

私はもっと読む必要があると思います。これは、(これは本当の解決策ではない場合は、少なくとも今のために働いている、)私はこの問題を解決する方法である:

  1. 私は_PuertoSerial.open前に「SerialDataReceivedEventHandler」行を移動しました();

  2. 私はこの記事からの提案に従っ:

https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true

だから私のfuntions(1 existings +新しいもの)は次のようになります。今思えるのために

void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
    { 
     printReceivedText(_PuertoSerial.ReadExisting()); 
    } 

    private void printReceivedText(string text) 
    { 
     if (this.txtSend.InvokeRequired) 
     { 
      SetTextCallback d = new SetTextCallback(printReceivedText); 
      this.Invoke(d, new object[] { text }); 
     } 
     else 
     { 
      this.txtRecieve.AppendText(text); 
      _PuertoSerial.DiscardInBuffer(); 
     } 
    } 

をうまく動作するように。最終テストは、別の端末に接続してお互いにやりとりするプログラムを見たときに行われます。

関連する問題