我正在C#中构建一个程序,用于我在大学的一门课程中,演示如何使用RS-232和连接在一起的两台计算机进行异步连接。我的课程不是编程,而是数据网络,因此我正在寻找连接。
picture 1 - sample layout of GUI using Visual Studio 2015
我想在程序中实现的功能之一是显示主从,单工连接是如何工作的(即程序可以选择从主机发送键盘输入;或从机只接收信息和将其打印在文本框上。)
我已经具备了初始化具有特定特性(波特率,数据位,停止位等)的串行端口的能力。使用GUI中的组合框选择此功能,并在用户单击按钮时将其分配给端口,以打开端口"。
我不知道如何创建"奴隶"该计划的一部分。我的想法是,在你选择程序为" slave"之后,你打开端口等待某种标志或事件在输入缓冲区存储数据时触发。
我一直在阅读几个论坛,但我找不到类似于我需要的东西。然而,我已经测试了多种替代品,我认为这些替代品会让我更接近我需要的东西,几乎没有结果。我来问一下我可能做错了什么,或者如何解决这个问题的建议。有问题的行是粗体(或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 :(得分:0)
我没有给你任何明确的答案。一旦你遇到两个可能的故障,你的代码看起来应该提供你需要的东西。
我认为你应该在BEFORE之前附上你的SerialDataReceivedEventHandler 你打电话给_PuertoSerial.Open()。
它可能没有任何效果,因为事件处理程序通常可以动态启用/禁用,但我的建议基于MSDN上的SerialPort的.Net源代码中的以下注释。
//所有的魔法都发生在对实例的.Open()方法的调用中。
//在内部,SerialStream构造函数打开文件句柄,设置设备控制块和相关的Win32结构,并开始事件监视周期。
"对象参考"删除可能会解决错误 DataReceivedHandler中的static修饰符。如果没有,或者如果那样 静态修饰符由于某种原因是必要的,那么也许是 txtRecieve控件有一个私有修饰符,需要更改 内部或公共。您应该能够使用Visual Studio 调试模式进入InitializeComponent()方法并查看 其中txtRecieve正在实例化。
答案 1 :(得分:0)
嗯,我相信我需要阅读更多内容。这就是我解决问题的方法(如果这不是真正的解决方案,至少目前是否有效):
我移动了" SerialDataReceivedEventHandler"在_PuertoSerial.open();
我遵循了本文的建议:
所以我的功能(一个存在+一个新的)看起来像这样:
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();
}
}
目前似乎工作正常。当我连接另一个终端并看到程序相互交互时,最终测试将会到来。