Serial Communication c# terminal, changing the stop bits ruins the comunication - c#

so I wrote a terminal in c# and I need to communicate with a kl25z microprocessor.
the application needs to support the option to choose the number of stop bits, the baud rate and the parity method.
I managed to sort it out with the baud rate but when I try to change the stop bits something goes out of sync and I cant figure out what.
the problem is that the uart is getting jibrish kind of chars instead of what I intended it to get, it does work well when I use one stop bit so I assume I just missed something in my code
I'll add the part of the code that gives me hard time:
this is only the c# part, my terminal I'm pretty sure that the problem is here
and not in the kl25z code
public Form1() {
InitializeComponent(); //init all variables
getAvailablePorts(); //fill the ports combo box with all the ports
}
void getAvailablePorts() {
String[] ports = SerialPort.GetPortNames(); //get the names of all availoable ports
comboBox1.Items.AddRange(ports); //add all the ports names to the combo box
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
try {
SerialPort sp = (SerialPort) sender;
if (serialPort1.IsOpen & sp.IsOpen) {
string indata = sp.ReadLine();
Invoke(new Action(() => textBox1.Text = indata));
if (indata.Equals("new settings been set") ||
indata.Equals("\0new settings been set") ||
indata.Equals("new settings been set??")) {
// baud rate
Invoke(new Action(() => baud = Convert.ToInt32(comboBox3.Text)));
Invoke(new Action(() => serialPort1.BaudRate = baud));
//end bits
Invoke(new Action(() => serialPort1.StopBits = end));
}
}
} catch (System.IO.IOException error) {
return;
} catch (System.InvalidOperationException error) {
return;
}
}
//here i open the port
private void button3_Click(object sender, EventArgs e) { //start port
try { // give the micro processor the info it needs about the settings
serialPort1.Handshake = Handshake.RequestToSendXOnXOff;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
serialPort1.PortName = comboBox1.Text; //port
serialPort1.BaudRate = baud; //baud rate current
// serialPort1.Parity= parity;//parity current
serialPort1.StopBits = end; //stopBits current
serialPort1.DataBits = bits; //current
//sort strings to send
String baudString = comboBox3.Text;
String StopString = comboBox6.Text;
String bitsString = comboBox2.Text;
String parityString = comboBox4.Text;
String startString = comboBox5.Text;
serialPort1.Open(); //open port
bitsString = "8";
//send properties to klz
serialPort1.Write("prop" + "$" + baudString + "$" + StopString + "$" + bitsString + "$" + parityString + "$" + startString + "$");
if (Convert.ToInt32(comboBox6.Text) == 1) {
end = StopBits.One;
} else {
end = StopBits.Two;
}
bits = Convert.ToInt32(comboBox2.Text);
} catch (UnauthorizedAccessException) {
textBox1.Text = "Unauthorized Access";
}
try {
progressBar1.Value = 100;
button1.Enabled = true;
button2.Enabled = true;
button3.Enabled = false;
button4.Enabled = true;
textBox2.Enabled = true;
} catch (UnauthorizedAccessException) {
textBox1.Text = "Unauthorized Access";
}
}

Related

Wait for thread to finish without blocking UI thread

I am writing winForm app which have to listem SerialPort and print the data into multi line textbox in real time.
Here is the code:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.ComponentModel;
namespace SCPListener
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
GetAvailablePortNames();
panel1.BackColor = ColorTranslator.FromHtml("#f44147");
cbDefaultValue();
}
String[] PortNames;
bool conn = true;
String data;
public string datetime;
Form2 frm = new Form2();
void GetAvailablePortNames()
{
PortNames = SerialPort.GetPortNames();
comboBox1.Items.AddRange(PortNames);
}
void RefreshAvailablePortNames()
{
comboBox1.Items.Clear();
PortNames = SerialPort.GetPortNames();
comboBox1.Items.AddRange(PortNames);
}
public string getDataTime()
{
DateTime time = DateTime.Now;
string date = time.ToString(#"hh\:mm\:ss");
return date;
}
public void GetData()
{
string date = getDataTime();
data = serialPort1.ReadLine();
textBox1.AppendText("[" + date + "] " + "Received: " + data + "\r\n");
}
public void cbDefaultValue()
{
comboBox1.SelectedIndex = 0;
comboBox5.SelectedIndex = 0;
comboBox2.SelectedIndex = 0;
comboBox3.SelectedIndex = 0;
comboBox4.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (comboBox1.Text == "" || comboBox2.Text == "" || comboBox3.Text == "" || comboBox4.Text == "" || comboBox5.Text == "")
{
MessageBox.Show("Please port settings", "Incorrect port settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
DateTime time = DateTime.Now;
string date = time.ToString(#"hh\:mm\:ss");
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
switch (comboBox3.Text)
{
case "5":
serialPort1.DataBits = 5;
break;
case "6":
serialPort1.DataBits = 6;
break;
case "7":
serialPort1.DataBits = 7;
break;
case "8":
serialPort1.DataBits = 8;
break;
default:
serialPort1.DataBits = 5;
break;
}
switch (comboBox4.Text)
{
case "None":
serialPort1.Parity = Parity.None;
break;
case "Odd":
serialPort1.Parity = Parity.Odd;
break;
case "Even":
serialPort1.Parity = Parity.Even;
break;
case "Mark":
serialPort1.Parity = Parity.Mark;
break;
case "Space":
serialPort1.Parity = Parity.Space;
break;
}
switch (comboBox5.Text)
{
case "One":
serialPort1.StopBits = StopBits.One;
break;
case "Two":
serialPort1.StopBits = StopBits.Two;
break;
case "OnePointFive":
serialPort1.StopBits = StopBits.OnePointFive;
break;
}
serialPort1.Open();
string CurrentPornName = comboBox1.Text;
label7.Text = "Opened " + CurrentPornName;
panel1.BackColor = ColorTranslator.FromHtml("#42f477");
comboBox1.Enabled = false;
comboBox2.Enabled = false;
comboBox3.Enabled = false;
comboBox4.Enabled = false;
comboBox5.Enabled = false;
//button5.Enabled = false;
//button6.Enabled = false;
}
}
catch (Exception ex)
{
if (ex is UnauthorizedAccessException)
{
MessageBox.Show("Unauthorized Acces","Access Error",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (ex is System.IO.IOException)
{
MessageBox.Show("Please plug in your device", "IO Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
panel1.BackColor = ColorTranslator.FromHtml("#f44147");
string CurrentPornName = comboBox1.Text;
label7.Text = "Closed " + CurrentPornName; ;
serialPort1.Close();
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
//button5.Enabled = true;
//button6.Enabled = true;
}
private void button5_Click(object sender, EventArgs e)
{
RefreshAvailablePortNames();
}
private void button3_Click(object sender, EventArgs e)
{
//backgroundWorker1.RunWorkerAsync();
Thread thread = new Thread(start: ()=>
{
try
{
datetime = getDataTime();
string date = getDataTime();
startListening:
if (serialPort1.BytesToRead > 0)
{
datetime = getDataTime();
data = serialPort1.ReadLine();
textBox2.AppendText("[" + datetime + "] " + "Received: " + data + "\r\n");
}
else
textBox2.AppendText("[" + datetime + "] " + "Error: There is no data to read" + "\r\n");
if (conn)
goto startListening;
}
catch (Exception ex)
{
DateTime time = DateTime.Now;
string date = time.ToString(#"hh\:mm\:ss");
if (ex is TimeoutException)
{
textBox1.AppendText("[" + date + "] " + "Timuot Exception" + "\r\n");
}
else if (ex is InvalidOperationException)
{
MessageBox.Show("Plese check settings", "Error: Invalid Operation", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (ex is System.IO.IOException)
{
MessageBox.Show("Port opened, but device unpluged..", "IO Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
});
thread.Start();
}
private void button4_Click(object sender, EventArgs e)
{
conn = false;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
datetime = getDataTime();
string date = getDataTime();
startListening:
if (serialPort1.BytesToRead > 0)
{
datetime = getDataTime();
data = serialPort1.ReadLine();
textBox2.AppendText("[" + datetime + "] " + "Received: " + data + "\r\n");
}
else
textBox2.AppendText("[" + datetime + "] " + "Error: There is no data to read" + "\r\n");
if (conn)
goto startListening;
}
catch (Exception ex)
{
DateTime time = DateTime.Now;
string date = time.ToString(#"hh\:mm\:ss");
if (ex is TimeoutException)
{
textBox1.AppendText("[" + date + "] " + "Timuot Exception" + "\r\n");
}
else if (ex is InvalidOperationException)
{
MessageBox.Show("Plese check settings", "Error: Invalid Operation", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (ex is System.IO.IOException)
{
MessageBox.Show("Port opened, but device unpluged..", "IO Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
About Code:
comboBox1 -> where the Ports are listed
comboBox2 -> where the Baud Rates options are listed
comboBox3 -> where the Stop Bits options are listed
comboBox4 -> where the Data Bits options are listed
comboBox5 -> where the Parity options are listed
button1 -> to connect chosen port
button2 -> to disconnect port
button3 -> to start listening and print data into textBox in real time
button4 -> to stop listening
button5 -> refresh available ports
panel1-> to identify port is connected or not (if connected it is green if it is not connected it is red)
So, what i want to do is that when I click the stop button (button4), program have to stop listening. I am trying to achieve this result using backgroundWorker .
Using this code when i try to listen port (clicking start button button3 there is opening the small error window and tell please check settings (so it catching InvalidOperationException according to my code); If I wont use backgoundWorker and also remove try{...} cath{...} program start do display the received data from port but blocking the UI. Any ideas will be very helpful.
button4_click needs to call backgroundWorker1.CancelAsync() instead of setting a bool. With BackgroundWorkers, you need to specify that you want them to end and then check for it, setting and checking an outside bool will not work. The try block in your backgroundWorker1_DoWork() method should look like the following. Keep in mind, it is easier for you and others to help you if you rename your variables (either done in the UI or by right clicking the variable and selecting 'Rename'). Another note before the code, it is almost never ok to use 'goto', there is almost always a better option (a while loop in this case).
datetime = getDataTime();
string date = getDataTime();
while (!backgroundWorker1.CancellationPending)
{
if (serialPort1.BytesToRead > 0)
{
datetime = getDataTime();
data = serialPort1.ReadLine();
textBox2.AppendText($"[{datetime}] Received: {data}\r\n");
}
else
{
textBox2.AppendText($"[{datetime}] Error: There is no data to read\r\n");
}
}
Edit to say: This should get you started, you will also want to check out this link to access your UI from backgroundWorker1, the problem is your UI is on one thread and your BackgroundWorker on another, threads do not work well together without some complimenting code

Serial port keep prompt time out error

private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (Clos_flag) return;
try
{
Listening = true;
if (serialPort.IsOpen)
{
this.txt_weight.Invoke(new MethodInvoker(delegate
{
serialPort.NewLine = "\r";
string weight = serialPort.ReadLine();
weight = weight.Trim();
MessageBox.Show(weight);
if (weight.IndexOf("i") > 0)
{
weight = weight.Substring(3, 8);
txt_weight.Text = weight.Substring(0, weight.LastIndexOf("0") + 1);
}
}));
}
}
catch (Exception eg)
{
MessageBox.Show(eg.ToString());
}
finally
{
Listening = false;
}
}
I use the above code to read the weighing machine, but it keep on prompt the timeout error I'm not sure which part of the coding is wrong.
You check your configure serialport.
It may be error while run code serialPort.Open().
you can refer code:
void InitialComport1()
{
mySerialPort1 = new SerialPort(Temp._comport1);
if (mySerialPort1.IsOpen)
{
mySerialPort1.Close();
}
mySerialPort1.BaudRate = Temp._baudRate1;
mySerialPort1.Parity = Parity.None;
mySerialPort1.StopBits = StopBits.One;
mySerialPort1.DataBits = Temp._dataBit1;
mySerialPort1.Handshake = Handshake.None;
mySerialPort1.RtsEnable = true;
mySerialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler1);
try
{
mySerialPort1.Open();
}
catch
{
Messagebox.Show("Error myserialPort1")
}
}
private void DataReceivedHandler1(object sender, SerialDataReceivedEventArgs e)
{
try
{
string indata = mySerialPort1.ReadLine();
try
{
string mass = indata.Substring(7, 7);
SetText1((Convert.ToInt32(mass)).ToString());
}
catch
{
string mass = indata.Substring(3, 7);
SetText1((Convert.ToInt32(mass)).ToString());
}
}
catch (Exception eg)
{
MessageBox.Show(eg.ToString());
}
}

Serialport port fault when i work with embedded system

I want to create communication with Com Ports.
I can write and read any data on my computer, but when I work with embedded system, my system doesn't read data.
My code:
if (!serialPort1.IsOpen)
{
serialPort1.PortName = cbComPort.SelectedItem.ToString();
serialPort1.BaudRate = 9600;
serialPort1.Open();
serialPort1.ReadTimeout = 5000;
//serialPort1.WriteTimeout = 1500;
serialPort1.WriteLine("USB>>READ<END");
string gelenveri;
bool durum = false;
while (!durum)
{
try
{
gelenveri = serialPort1.ReadLine();
lblGelen.Text = gelenveri;
serialPort1.Close();
durum = true;
lblKarakterDeneme.Text = hextobinary(karakter_temizle(gelenveri));
veriyerlestir(lblKarakterDeneme.Text);
}
catch (TimeoutException)
{
MessageBox.Show("Veri Alınamadı");
serialPort1.Close();
}
break;
}
}
i find answer for this my question,
i canceled serialPort1.ReadLine(); and i use SerialDataReceivedEventArgs

Cancel "tcplistener" from backgroundworker's CancelAsync()

I have a Windows form from which when a button is clicked an instance of Backgroundworker starts a tcplistener method in another class.
I would like to be able to cancel the tcplistener after it's started or while it's receiving\writing data to disk.
I have set the backgroundworker arguments to be available for the tcplistener class so that the cancellationpendingargument can be used to cancel operations in the tcplistener class.
The issue is that once the "tcplistener.server" is started, if the cancel button is clicked, the listener is not being stopped or terminated.
To achieve this I have put the tcplistener code in a while (bgw.CancellationPending != true) assuming if the argument is wrong the listening would be cancelled
Here is my back groundworker code:
private void startBtn_Click(object sender, EventArgs e)
//private void startBtn_Click(BackgroundWorker bw, EventArgs e)
{
if (bgw.IsBusy != true)
{
if (ipTxt.Text != "" && portTxt.Text != "" && dirTxt.Text != "" && bufferTxt.Text != "")
{
cancelBtn.Enabled = true;
listenerLabel.Text = "...";
resultLabel.Text = "...";
netwrkLst.Enabled = false;
ipTxt.Enabled = false;
portTxt.Enabled = false;
bufferTxt.Enabled = false;
dirTxt.Enabled = false;
brwsBtn.Enabled = false;
startBtn.Enabled = false;
this.bgw.RunWorkerAsync();
}
else
{
MessageBox.Show("Fill in all fields first");
}
}
}
//This event handler cancels the backgroundworker
private void cancelBtn_Click_1(object sender, EventArgs e)
{
//if (bgw.WorkerSupportsCancellation == true)
if (bgw.IsBusy == true)
{
// Cancel the asynchronous operation.
this.bgw.CancelAsync();
cancelBtn.Enabled = false;
startBtn.Enabled = true;
listenerLabel.Text = "Listening canceled.";
resultLabel.Text = "...";
netwrkLst.Enabled = true;
ipTxt.Enabled = true;
portTxt.Enabled = true;
bufferTxt.Enabled = true;
dirTxt.Enabled = true;
brwsBtn.Enabled = true;
}
}
// This event handler is where the work is done.
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
if (this.bgw.CancellationPending == true)
{
e.Cancel = true;
return;
}
listener.tcp(
ipTxt.Text,
portTxt.Text,
dirTxt.Text,
bufferTxt.Text, bgw, e);
}
// This event handler updates the progress.
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
}
// This event handler deals with the results of the background operation.
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
resultLabel.Text = "Done!";
}
}
And here is my tcplistener code:
namespace McServer
{
public class listener
{
// Raise the UpdateLabel event, passing "Outside" as
// the message.
public static event Action<string> UpdateLabel;
public static event Action<string> UpdateLabel2;
//public volatile bool shutdown = false;
public static void tcp(string ip, string portID, string path, string buffer, BackgroundWorker bgw, DoWorkEventArgs ev)
{
//if (bgw.CancellationPending == true)
//{
// ev.Cancel = true;
// return;
//}
//while (bgw.CancellationPending != true)
//{
TcpListener server = null;
string time = DateTime.Now.ToString("yyyyMMdd" + "_" + "HH-mm-ss");
while (bgw.CancellationPending != true) try
{
// Set the TcpListener.
Int32 port = Int32.Parse(portID);
IPAddress localAddr = IPAddress.Parse(ip);
Int32 buff = Int32.Parse(buffer);
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
// Buffer for reading data
//Byte[] bytes = new Byte[1000 * 1024];
Byte[] bytes = new Byte[buff];
server.Start();
// Enter the listening loop.
while (true)
{
UpdateLabel("Waiting for a connection...");
// Perform a blocking call to accept requests.
// Can also also use server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
UpdateLabel("Connected...");
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
int j = 0;
int k = 0;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) > 0)
{
j++;
k = k + i;
if (k >= 1024)
{
k = k / 1024;
UpdateLabel("Received:" + k + " MB");
}
if (k >= 1024 * 1000)
{
k = k / 1024 / 1024;
UpdateLabel("Received:" + k + " GB");
}
UpdateLabel("Received:" + k + " Bytes");
//write to file
using (FileStream stream2 = new FileStream(path + j + "_" + time + "_" + ".tcp", FileMode.Create))
{
stream2.Write(bytes, 0, i);
stream2.Close();
}
// Send back a response.
stream.Write(bytes, 0, bytes.Length);
}
// Shutdown and end connection
client.Close();
UpdateLabel2("Connection closed by client...");
}
}
catch (SocketException e)
{
UpdateLabel2("An error occured: SocketException:" + e);
}
finally
{
// Stop listening for new clients.
server.Stop();
UpdateLabel2("Listening stopped...");
}
//}
{
ev.Cancel = true;
return;
}
}
}
}

SerialPort.Write method hanging, timeout not fired in C#

I have to write a program that writes on a serial port but sometimes the call to the Write method hangs and the WriteTimeout is never fired so my program hangs indefinitely.
Here is the port creation code:
void DetectX1BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
String[] ports = SerialPort.GetPortNames();
int i = 0;
foreach (string PortName in ports)
{
try
{
Console.WriteLine("Trying to open:" + PortName);
SerialPort port = openSerial(PortName);
Console.WriteLine("Port is open:" + PortName);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Write("$ST+IMEI=0000\r\n");
if (IMEIFoundEvent.WaitOne(250))
{
Console.WriteLine("IMEI Found:[" + imei + "]");
if (addresses.ContainsKey(imei))
{
((BackgroundWorker)sender).ReportProgress(0, new X1Model(imei, PortName, addresses[imei]));
}
else
Console.WriteLine("imei not in file: " + imei);
}
port.Close();
}
catch (Exception ex)
{
Console.WriteLine("Erreur port " + PortName + ex.Message);
}
finally
{
i++;
((BackgroundWorker)sender).ReportProgress(i * 100 / ports.Length);
}
}
}
private SerialPort openSerial(string PortName)
{
SerialPort port = new SerialPort(PortName);
port.BaudRate = 57600;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReceivedBytesThreshold = 1;
port.Handshake = Handshake.None;
port.DtrEnable = true;
port.RtsEnable = true;
port.WriteTimeout = 5000;
port.ReadTimeout = 5000;
if (!port.IsOpen)
port.Open();
return port;
}
Is there anything I'm missing ?
I don't know if it's relevant but I'm using Serial To USB Adapters.
Edit: I'm using Windows XP with .Net 4.0. The line doesnt't exceed 50 characters and ends by a EOL character.
I know it's an old question, which you've probably solved by now, but there's no accepted answer yet. I was having the same issue yesterday and seem to have fixed it -- were you setting the Write Timeout?
_serialPort.WriteTimeout = 500;
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.writetimeout.aspx
You also need to set the PortName. You can get the list of ports from GetPortNames. This will typically be like COM1 or COM2

Categories