I am new to stackoverflow. I am having a problem with VC# Serial Communication. I need t receive data conyinuously from serial port but my code works only once. That is if I send "This is a Serial Comm Project". The data is received as expected but if I send the data again it doesn't work. Please provide a solution.
private void button1_Click(object sender, EventArgs e)
{
mySerialPort.PortName = cbxCOMPort.Text;
mySerialPort.BaudRate = int.Parse(cbxBaudrate.Text);
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.RequestToSend;
mySerialPort.ReadTimeout = int.Parse(cbxTimeout.Text);
mySerialPort.WriteTimeout = 2000;
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
mySerialPort.Encoding = Encoding.ASCII;
mySerialPort.NewLine = "\r\n";
mySerialPort.ReadBufferSize = 512;
mySerialPort.DataReceived += port_DataReceived;
mySerialPort.Open();
button1.Enabled = false;
button2.Enabled = true;
gbxMsgDel.Enabled = true;
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{// Event for receiving data
// Read the buffer to text box.
this.Invoke(new EventHandler(DoUpdate));
}
private void DoUpdate(object s, EventArgs e)
{
receivedMessage += mySerialPort.ReadExisting();
}
receivedMessage is a private string type. It is private to the class.
I had a similar problem before...
From MSDN
"The DataReceived event is not guaranteed to be raised for every byte
received"
One option is to use a timer to check available data instead of the event, something like this:
private void checkPortDataTimer_Tick(object sender, EventArgs e)
{
//You may want to check available bytes instead of this.
string recievedData = comPort.ReadExisting();
if (!string.IsNullOrEmpty(recievedData))
someTextBox.Text += recievedData;
}
Cheers
Related
so im new in C# Programming. I have programmed a C# Forms Application in Visual Studio to communicate to/initialze a device over the Serial Port. The communication between the device is COBS coded, so there are no 0x00 bytes except on the end of each message. The messages sent and received have different length.
My problem is at the moment, that the Messages I receive are not complete or start at the middle of a message, so i cannot trigger sent messages on a specific value in the received messages. You can determine end of a message with received 0x00 (0x00 means end of message in COBS coded data)
So what i need is something to handle the complete message and put it in a byte array to analyze i.e. byte[11] for a specific value.
Here is what ive done so far:
private bool b_portopen = false;
private byte[] b_rcv_buffer = new byte[256];
private void button1_Click(object sender, EventArgs e) {
//InitTimer();
if (b_portopen == false)
{
serialPort1.PortName = comboBox1.SelectedItem.ToString();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
serialPort1.Open();
b_portopen = true;
button1.Text = "Close";
button2.Enabled = true;
Console.WriteLine("Serial Port Opened");
}
else if (b_portopen == true)
{
serialPort1.Close();
b_portopen = false;
button1.Text = "Open";
button2.Enabled = false;
Console.WriteLine("Serial Port Closed");
}
}
private async void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
serialPort1.Read(b_rcv_buffer, 0, 256);
//serialPort1.Read(b_rcv_buffer1, 11, 2);
richTextBox1_receive.Invoke(new Action(() =>
{
richTextBox1_receive.AppendText(BitConverter.ToString(b_rcv_buffer) + "\n");
richTextBox1_receive.ScrollToCaret();
}));
switch (b_rcv_buffer[10])
{
case b_state_startup:
do something
case b_state_be_start_conf:
do something
case b_state_keepalive_conf:
do something
case b_state_unprepare_conf:
do something
case b_state_prepare_conf:
do something
}
}
So, i found a solution with using ConcurrentQueue:
ConcurrentQueue<byte> b_rcv_buffer = new ConcurrentQueue<byte>();
private Timer timer2;
public void InitTimer()
{
timer2 = new System.Windows.Forms.Timer();
timer2.Tick += new EventHandler(timer2_Tick);
timer2.Interval = 1; // in miliseconds
timer2.Start();
}
private async void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
int bytes = serialPort1.BytesToRead;
byte[] buf = new byte[bytes];
serialPort1.Read(buf, 0, serialPort1.BytesToRead);
for(int i = 0; i < buf.Length; i++)
{
b_rcv_buffer.Enqueue(buf[i]); //Enqueue every received Byte in Concurrentqueue
}
}
private async void timer2_Tick(object sender, EventArgs e)
{
if (b_rcv_buffer.Contains<byte>(0x00))
{
byte[] array = b_rcv_buffer.ToArray();
richTextBox1_receive.Invoke(new Action(() =>
{
richTextBox1_receive.AppendText(BitConverter.ToString(array) + "\n");
//richTextBox1_receive.ScrollToCaret();
}));
byte ignored;
while (b_rcv_buffer.TryDequeue(out ignored));
}
I want to create Serial port listener with GUI.
I'm trying to print received data into textBox. When i click button program has to start listening, everything works but not printing into textBox.
Here is EventHandler code:
void serialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
textBox1.AppendText(indata + "\r\n");
}
And the button code which starts listening:
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
Need some help :)
You can use RichTextBox as follows:
1st option:
RichTextBox1.Text += sp.ReadExisting() + "\n";
2nd option - The second option uses delegate, you can say, a signature of method:
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
private void Form1_Load(object sender, EventArgs e)
{
this.myDelegate = new AddDataDelegate(AddDataMethod);
}
public void AddDataMethod(String myString)
{
TextBox1.AppendText(myString);
}
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s= sp.ReadExisting();
TextBox1.Invoke(this.myDelegate, new Object[] {s});
}
i want to call a service number like that *21*2# with AT Command using gsm modem but also i want to receive the answer ( because it is a service number ) in RichtextBox , hox to do that ? :(
private void button1_Click(object sender, EventArgs e)
{
SerialPort po = new SerialPort();
po.PortName = "COM3";
po.BaudRate = int.Parse( "9600");
po.DataBits = Convert.ToInt32("8");
po.Parity = Parity.None;
po.StopBits = StopBits.One;
po.ReadTimeout = int.Parse("300");
po.WriteTimeout = int.Parse("300");
po.Encoding = Encoding.GetEncoding("iso-8859-1");
po.Open();
po.DtrEnable = true;
po.RtsEnable = true;
po.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
po.Write("ATD9030665834;");
}
public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
{
}
}
I have got myself a little lost with this Windows forms application:(
I have a stream of data arriving at a serial port in the format of \W0987654321\L555666444\W3456789900\L9842429009 and so it repeats with different values for \L and \W
I need to split out the \W and \L values and add them to an array which is to expand as needed. and then plot them on a graph in real time.
Where i'm lost is how to read the port to get each complete value once it has arrived and not truncate it. I just can't get my brain around this so any help would be great...
I open the port thus:
port.PortName = "COM9";
port.BaudRate = 38400;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.DtrEnable = false;
port.Handshake = Handshake.None;
port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
port.Open();
textBox1.Clear();
port.DiscardInBuffer();
port.DtrEnable = true;
Currently i have it all writing to a text box:
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
InputData = port.ReadExisting();
if (InputData != String.Empty)
{
this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
}
}
private void SetText(string text)
{
this.textBox1.AppendText(text);
}
which shows all the data OK
var readQueue = string.Empty;
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
readQueue += port.ReadExisting();
while (readQueue.Substring(1).Contains(#"\"))
{
var slashPos = readQueue.IndexOf(#"\",1);
var completeEntry = readQueue.Substring(0, slashPos);
Console.WriteLine(completeEntry);
readQueue = readQueue.Substring(slashPos);
}
}
I'm trying to make a serial connection to another machine. I'm using a Virtual Serial Port Emulator to try this. The settings that I use on hyperterminal are like the ones below. I can see the portopen is true, but I can't check whether I can write or read. When I try the ReadLine method it gives TimeoutException and when it's readExisting command it does nothing. DataReceived is never triggered too. Can you help me out with that ?
private void Page1_Load(object sender, EventArgs e)
{
//Port name can be identified by checking the ports
// section in Device Manager after connecting your device
serialPort1.PortName = "COM14"; // that one works for me
//Provide the name of port to which device is connected
//default values of hardware[check with device specification document]
serialPort1.BaudRate = 115200;
serialPort1.Parity = Parity.None;
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Handshake = Handshake.None;
serialPort1.RtsEnable = true;
serialPort1.DtrEnable = true;
serialPort1.ReceivedBytesThreshold = 8;
serialPort1.ReadTimeout = 2000;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived); //
// Writes data to the Serial Port output buffer
//opens the port
serialPort1.Open();
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
inputData = serialPort1.ReadExisting();
this.Invoke((MethodInvoker)delegate { DoUpdate(); });
}
public void DoUpdate()
{
textOutput.Text = (textOutput.Text + inputData);
}
private void btnReadExist_Click(object sender, EventArgs e)
{
if ((serialPort1.IsOpen == true))
{
serialPort1.WriteLine("something");
string read= serialPort1.ReadExisting();
//string output = serialPort1.ReadLine();
textOutput.Text += read;
}
}
private void Page1_FormClosed(object sender,System.Windows.Forms.FormClosedEventArgs e)
{
// Close the Serial Port
serialPort1.Close();
}
The problem seems to be that you're reading in two code blocks: first, directly after sending the text in the button's event. Secondly you have an event assigned that reads data when called asynchronously. You should decide which one to use and remove the other.