トップ回答者
Serial Port, send command to 10 devices RS485/USB on C#.

質問
-
Hi,
I have 10 devices connected to the computer through a converter RS485/USB.
I have serial port class, SerialPort.cs
I send the command below. AA and receive in the BB, but sometimes did not receive data or get duplicated. How to fix this?
I will appreciate any help.
AA private void button14_Click(object sender, EventArgs e) { timer3.Enabled = true; inicio = DateTime.Now; #region Wrk ID01 timr_ID06.Enabled = true; string s_ID01_c = "id01"; CommPort com = CommPort.Instance; s_ID01_c = ConvertEscapeSequences(s_ID01_c); ; com.Send(s_ID01_c); com.Send(s_ID01_c); #endregion #region Wrk ID02 string s_ID02_c = "id02"; s_ID02_c = ConvertEscapeSequences(s_ID02_c); ; com.Send(s_ID02_c); com.Send(s_ID02_c); #endregion #region Wrk ID03 string s_ID03_c = "id03"; s_ID03_c = ConvertEscapeSequences(s_ID03_c); ; com.Send(s_ID03_c); com.Send(s_ID03_c); #endregion #region Wrk ID04 string s_ID04_c = "id04"; s_ID04_c = ConvertEscapeSequences(s_ID04_c); ; com.Send(s_ID04_c); com.Send(s_ID04_c); #endregion #region Wrk ID05 string s_ID05_c = "id05"; s_ID05_c = ConvertEscapeSequences(s_ID05_c); ; com.Send(s_ID05_c); com.Send(s_ID05_c); #endregion #region Wrk ID06 string s_ID06_c = "id06"; s_ID06_c = ConvertEscapeSequences(s_ID06_c); ; com.Send(s_ID06_c); com.Send(s_ID06_c); #endregion }
BB #region Event handling - data received and status changed /// <summary> /// Prepare a string for output by converting non-printable characters. /// </summary> /// <param name="StringIn">input string to prepare.</param> /// <returns>output string.</returns> private String PrepareData(String StringIn) { // The names of the first 32 characters string[] charNames = { // "NUL", "SOH", "STX", "ETX", "EOT", //"ENQ", "ACK", "BEL", "BS", "TAB", "LF", "VT", "FF", "CR", "SO", "SI", //"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", //"ESC", "FS", "GS", "RS", "US", "Space" }; string StringOut = ""; foreach (char c in StringIn) { if (Settings.Option.HexOutput) { StringOut = StringOut + String.Format("{0:X2} ", (int)c); } else if (c < 32 && c != 9) { StringOut = StringOut + "";// +"<"+charNames[c]+">"; //StringOut = StringOut + String.Format("[{0:X2}]", (int)c); } else { StringOut = StringOut + c; } } return StringOut; } /// <summary> /// Partial line for AddData(). /// </summary> private Line partialLine = null; /// <summary> /// Add data to the output. /// </summary> /// <param name="StringIn"></param> /// <returns></returns> private Line AddData(String StringIn) { String StringOut = PrepareData(StringIn); // if we have a partial line, add to it. if (partialLine != null) { // tack it on partialLine.Str = partialLine.Str + StringOut; outputList_Update(partialLine); return partialLine; } return outputList_Add(StringOut, receivedColor); } // delegate used for Invoke internal delegate void StringDelegate(string data); /// <summary> /// Handle data received event from serial port. /// </summary> /// <param name="data">incoming data</param> public void OnDataReceived(string dataIn) { //Handle multi-threading if (InvokeRequired) { Invoke(new StringDelegate(OnDataReceived), new object[] { dataIn }); return; } // pause scrolling to speed up output of multiple lines bool saveScrolling = scrolling; scrolling = false; // if we detect a line terminator, add line to output int index; while (dataIn.Length > 0 && ((index = dataIn.IndexOf("\r")) != -1 || (index = dataIn.IndexOf("\n")) != -1)) { String StringIn = dataIn.Substring(0, index); dataIn = dataIn.Remove(0, index + 1); logFile_writeLine(AddData(StringIn).Str); logFile_writeLine1(AddData(StringIn).Str); //listBox3.Items.Add(AddData(StringIn).Str); partialLine = null; // terminate partial line } // if we have data remaining, add a partial line if (dataIn.Length > 0) { partialLine = AddData(dataIn); } // restore scrolling scrolling = saveScrolling; outputList_Scroll(); listBox1_Scroll(); } /// <summary> /// Update the connection status /// </summary> public void OnStatusChanged(string status) { //Handle multi-threading if (InvokeRequired) { Invoke(new StringDelegate(OnStatusChanged), new object[] { status }); return; } textBox1.Text = status; } #endregion
Obrigado por sua participação.
回答
-
Silvio-san
I also recommend that you should provide background information about the "SerialPort.cs", "CommPort" class, etc. and how they are expected to work with your 10 devices through the RS485/USB converter.
I believe that you are NOT using the .Net Framework-standard "Serial Port" class described in the following URL:
http://msdn.microsoft.com/ja-jp/library/system.io.ports.serialport(v=VS.100).aspxKotaro TONOIKE
(ホームページを再開しました)
すべての返信
-
Hello Silvio Pontes,
Thank you for posting your question to our forum.
However, unfortunately, I'm afraid it might be difficult for you to get a reply since people usually use Japanase here...
I'd like to suggest you post your question in an English forum.
Please click here to find an appropreate forum (category) depending on the type of your question.
I hope you find some useful information!
Thank you,
--------------
Harumi Yamamoto (MSKK) -
Silvio-san
I also recommend that you should provide background information about the "SerialPort.cs", "CommPort" class, etc. and how they are expected to work with your 10 devices through the RS485/USB converter.
I believe that you are NOT using the .Net Framework-standard "Serial Port" class described in the following URL:
http://msdn.microsoft.com/ja-jp/library/system.io.ports.serialport(v=VS.100).aspxKotaro TONOIKE
(ホームページを再開しました) -
Kotaro TONOIKE -San,
Thank you, below has my SerialPort.cs.
//SerialPort.cs using System; using System.IO; using System.IO.Ports; using System.Threading; namespace NanoFX { /// <summary> CommPort class creates a singleton instance /// of SerialPort (System.IO.Ports) </summary> /// <remarks> When ready, you open the port. /// <code> /// CommPort com = CommPort.Instance; /// com.StatusChanged += OnStatusChanged; /// com.DataReceived += OnDataReceived; /// com.Open(); /// </code> /// Notice that delegates are used to handle status and data events. /// When settings are changed, you close and reopen the port. /// <code> /// CommPort com = CommPort.Instance; /// com.Close(); /// com.PortName = "COM4"; /// com.Open(); /// </code> /// </remarks> public sealed class CommPort { SerialPort _serialPort; Thread _readThread; volatile bool _keepReading; //begin Singleton pattern static readonly CommPort instance = new CommPort(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static CommPort() { } CommPort() { _serialPort = new SerialPort(); _readThread = null; _keepReading = false; } public static CommPort Instance { get { return instance; } } //end Singleton pattern //begin Observer pattern public delegate void EventHandler(string param); public EventHandler StatusChanged; public EventHandler DataReceived; //end Observer pattern private void StartReading() { if (!_keepReading) { _keepReading = true; _readThread = new Thread(ReadPort); _readThread.Start(); } } private void StopReading() { if (_keepReading) { _keepReading = false; _readThread.Join(); //block until exits _readThread = null; } } /// <summary> Get the data and pass it on. </summary> private void ReadPort() { while (_keepReading) { if (_serialPort.IsOpen) { byte[] readBuffer = new byte[_serialPort.ReadBufferSize + 1]; try { // If there are bytes available on the serial port, // Read returns up to "count" bytes, but will not block (wait) // for the remaining bytes. If there are no bytes available // on the serial port, Read will block until at least one byte // is available on the port, up until the ReadTimeout milliseconds // have elapsed, at which time a TimeoutException will be thrown. int count = _serialPort.Read(readBuffer, 0, _serialPort.ReadBufferSize); String SerialIn = System.Text.Encoding.Default.GetString(readBuffer,0,count); DataReceived(SerialIn); } catch (TimeoutException) { } } else { TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50); Thread.Sleep(waitTime); } } } /// <summary> Open the serial port with current settings. </summary> public void Open() { Close(); try { _serialPort.PortName = Settings.Port.PortName; _serialPort.BaudRate = Settings.Port.BaudRate; _serialPort.Parity = Settings.Port.Parity; _serialPort.DataBits = Settings.Port.DataBits; _serialPort.StopBits = Settings.Port.StopBits; _serialPort.Handshake = Settings.Port.Handshake; // Set the read/write timeouts _serialPort.ReadTimeout = 50; _serialPort.WriteTimeout = 50; _serialPort.Open(); StartReading(); } catch (IOException) { StatusChanged(String.Format("{0} does not exist", Settings.Port.PortName)); } catch (UnauthorizedAccessException) { StatusChanged(String.Format("{0} already in use", Settings.Port.PortName)); } catch (Exception ex) { StatusChanged(String.Format("{0}", ex.ToString())); } // Update the status if (_serialPort.IsOpen) { string p = _serialPort.Parity.ToString().Substring(0, 1); //First char string h = _serialPort.Handshake.ToString(); if (_serialPort.Handshake == Handshake.None) h = "no handshake"; // more descriptive than "None" StatusChanged(String.Format("{0}: {1} bps, {2}{3}{4}, {5}", _serialPort.PortName, _serialPort.BaudRate, _serialPort.DataBits, p, (int)_serialPort.StopBits, h)); } else { StatusChanged(String.Format("{0} already in use", Settings.Port.PortName)); } } /// <summary> Close the serial port. </summary> public void Close() { StopReading(); _serialPort.Close(); StatusChanged("connection closed"); } /// <summary> Get the status of the serial port. </summary> public bool IsOpen { get { return _serialPort.IsOpen; } } /// <summary> Get a list of the available ports. Already opened ports /// are not returend. </summary> public string[] GetAvailablePorts() { return SerialPort.GetPortNames(); } /// <summary>Send data to the serial port after appending line ending. </summary> /// <param name="data">An string containing the data to send. </param> public void Send(string data) { if (IsOpen) { string lineEnding = ""; switch (Settings.Option.AppendToSend) { case Settings.Option.AppendType.AppendCR: lineEnding = "\r"; break; case Settings.Option.AppendType.AppendLF: lineEnding = "\n"; break; case Settings.Option.AppendType.AppendCRLF: lineEnding = "\r\n"; break; } _serialPort.Write(data + lineEnding); } } } }
Obrigado por sua participação. -
Silvio-san
Could you summarize your code? I mean, could you explain how you understand your own code "SerialPort.cs"?
You are behaving in a very typical manner that users of this forum may avoid to discuss with you. Very few people read and analyze your code.
Necessary is NOT showing all code BUT brief explanation:
what you have understood and achieved,
what you intend next, and
what your problem is.We know the last two items because you already told. But, we do not know at all your knowledge base.
Kotaro TONOIKE
(ホームページを再開しました)