|
I am developing an application in C#.NET , for transferring data between two PC's using RS232 protocol. For communication, i m using "SerialPort" class of "System.IO.Ports" namespace. but now i have a problems in recieveing the data and sending the data. even one major problem is whenever i'll recieve at that time i have to identify the begining of message and ending of message as well as if two messagees are recieveing at thae same time then how to differentiate that messagees. please help me i nthat. i really stuck in that. thank you in advance
Arpita Patel
|
|
|
|
|
Hi,
did you mention to use a start and a stop character, e.g. (char)1 start and (char)2 to stop.
Then use
recvStr = recvStr.Remove(0, recvStr.IndexOf((char)1)-1);
msg = recvStr.Substring(recvStr.IndexOf((char)1), recvStr.IndexOf((char)2, recvStr.IndexOf((char)1));
Kind regards
|
|
|
|
|
I used this code for sending the data
private void SendData()
{
if (CurrentDataMode == DataMode.Text)
{
// Send the user's text straight out the port
comport.Write(txtSendData.Text);
// Show in the terminal window the user's text
Log(LogMsgType.Outgoing, txtSendData.Text + "\n");
}
else
{
try
{
// Convert the user's string of hex digits (ex: B4 CA E2) to a byte array
byte[] data = HexStringToByteArray(txtSendData.Text);
// Send the binary data out the port
comport.Write(data, 0, data.Length);
// Show the hex digits on in the terminal window
Log(LogMsgType.Outgoing, ByteArrayToHexString(data) + "\n");
}
catch (FormatException)
{
// Inform the user if the hex string was not properly formatted
Log(LogMsgType.Error, "Not properly formatted hex string: " + txtSendData.Text + "\n");
}
}
txtSendData.SelectAll();
}
For the Recieving purpose I used
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// This method will be called when there is data waiting in the port's buffer
// Determain which mode (string or binary) the user is in
if (CurrentDataMode == DataMode.Text)
{
// Read all the data waiting in the buffer
string data = comport.ReadExisting();
// Display the text to the user in the terminal
Log(LogMsgType.Incoming, data);
}
else
{
// Obtain the number of bytes waiting in the port's buffer
int bytes = comport.BytesToRead;
// Create a byte array buffer to hold the incoming data
byte[] buffer = new byte[bytes];
// Read the data from the port and store it in our buffer
comport.Read(buffer, 0, bytes);
// Show the user the incoming data in hex format
Log(LogMsgType.Incoming, ByteArrayToHexString(buffer));
}
}
now give me appropriate answer for my question.
thanks a lot fro replying me.
Arpita Patel
|
|
|
|
|
To parse individual messages out of a stream of them there needs to be a start message flag that signals the beginning of a message. Just pick a unique character or pattern of characters and put that at the beginning of each message. Pick a different flag and put it at the end to identify where each message stops.
|
|
|
|
|
Hi,
if you can choose the protocol freely, then this would probably be the easiest set-up with reasonable reliability:
- send everything as text using ASCII, i.e. don't use binary data;
- end each message on a reserved character, \n is a good choice; you can achieve this by setting
SerialPort.NewLine to '\n' and using WriteLine()
- create a receiver thread, which basically is an eternal loop performing a ReadLine(); this one will block until a SerialPort.NewLine was received, then return all the data received so far, which would be exactly one message.
WARNING: the receiver thread cannot directly access any GUI Controls, it needs Control.Invoke for that.
Luc Pattyn [Forum Guidelines] [My Articles]
DISCLAIMER: this message may have been modified by others; it may no longer reflect what I intended, and may contain bad advice; use at your own risk and with extreme care.
|
|
|
|
|
I do a lot of RS232 programming for my job. All of our messages usually start with a special character, such as the <stx> hex 0x02 character, followed by a message identifier that we use to let the program know what to do with the message. Then the message is ASCII encoded text followed by a termination character, such as <etx> hex 0x03. When a message is received, the starting character, message identifier, and ending character are stripped from the message which is then passed to whatever part of the application it is intended for. If you are having trouble with receiving and sending data, make sure that you are using a crossover cable <null modem=""> which has the send and receive wires switched at one end of the cable. If you use a straight through cable then the receiving computer will not be getting the data on the receive pin but the transmit pin, which it won't process. By definition, serial communication means that you cannot get two messages at the same time as you are transmitting the bytes in a 'series'. So as long as you are looking for the stop character to terminate a message then the next message should not get jumbled or lost as long as you don't overrun the buffer.
|
|
|
|
|
thanks for replying me
hey you said you do lot of RS232 programming. can you teach me that because I am new in RS232 programming with multithreading and i have to do it in time so I dont have enough time but I will manage if you are ready to teach me.
I really appriciate for that.
I am waiting for your reply.
thanks.
|
|
|
|
|
hey need help for serial port.
please give me your email addres or something so i can send info about it.
please.
thanks
|
|
|
|
|
I don't mind offering assistance on your project if you have specific questions. I understand deadlines and your issue with getting this done in a certain amount of time but for me to 'teach' you about threading and serial port communication is a considerable task. What do you know already? If you are just starting out then I suggest you read the documentation at MSDN on the Threading class and the SerialPort class or check out one of the fine articles here at CP on the subject. That's how I learned how to do a lot of the stuff you are wanting to do. If you have a specific question feel free to contact me (you can click the email link at the bottom of this post) and I will answer the best I can.
|
|
|
|
|
thanks for help.
and I know basic info about threading and serial port. but the main problem is in my project computer has to recieve signals from device in continous manner. Its like embedded tech. so new for that. thats why confused. cant find your email link so have to put on general blog. if you dont mind give me your email id so i can send you my problem.
but thanks a lot.
|
|
|
|
|
This problem is giving me a lot of headaches and can´t find the solution...
I´m reading this article Custom Configuration Sections for Lazy Coders[^]
I´m reading the part titled "The Hello, World ConfigurationSection" , using exactly same code (copy paste directly) and always obtain an error when execute the program (it not returns error/warnings on compiling time).
The error says that can´t load config.SomeSettings from asembly...
My app.config:
<?xml version="1.0" encoding="utf-8" ?><br />
<configuration><br />
<configSections><br />
<section name="SomeSettings" type="config.SomeSettings, config" /><br />
</configSections><br />
<SomeSettings FillColor="LightBlue" TextSize="9.5" FillOpacity="50" /><br />
</configuration>
Proyect --> properties , shows me that the name of my assembly is "config"
I´m totally lost, found more codes similar to the one explained into this article and always, ALWAYS, always obtain the same error.... perhaps someone can give me a hand, thanks
|
|
|
|
|
Just a quick check, but your namespace that the class sits in is definately config right?
Eg, the code should look something like this:
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace config
{
public class SomeSettings : ConfigurationSection
{
private SomeSettings() { }
[ConfigurationProperty("FillColor", DefaultValue = "Cyan")]
public System.Drawing.Color FillColor
{
get { return (System.Drawing.Color)this["FillColor"]; }
set { this["FillColor"] = value; }
}
[ConfigurationProperty("TextSize", DefaultValue = "8.5")]
public float TextSize
{
get { return (float)this["TextSize"]; }
set { this["TextSize"] = value; }
}
[ConfigurationProperty("FillOpacity", DefaultValue = "40")]
public byte FillOpacity
{
get { return (byte)this["FillOpacity"]; }
set { this["FillOpacity"] = value; }
}
}
}
|
|
|
|
|
I solved it definetly... i not defined any namespace, so the problem was in App.config...
<?xml version="1.0" encoding="utf-8" ?><br />
<configuration><br />
<configSections><br />
<section name="SomeSettings" type="SomeSettings, config" /><br />
</configSections><br />
<SomeSettings FillColor="LightBlue" TextSize="9.5" FillOpacity="50" /><br />
</configuration>
And all works good
|
|
|
|
|
|
Hi.
I'm having a problem and cannot find the solution. trust me, i've read lots on msdn and google'd, in the wrong places obviously but i hope someone here can help me.
I'm porting an application to compact framework 3 and to reduce client side load i created a webservice for the BL (also, else i would have to copy all code and compile to CF since i cant use "regular" dll's in CF)
this webservice exposes some custom classes and a couple of methods. a simple example would be
(in webservice)
public enum ToStringType {
FirstName,
LastName
}
public class person
{
public string firstname {get;set;}
public string lastname {get;set;}
public ToStringType stringtype {get;set;}
public person(){
stringtype = ToStringType.FirstName ;
}
public override ToString(){
public override string ToString()
{
string tostr = string.Empty;
switch (stringtype )
{
case ToStringType.FirstName :
tostr = FirstName;
break;
case ToStringType.LastName:
tostr = LastName;
break;
}
return tostr;
}
and the ws has a method returning person[]
on the client. when i run the method and get a list of persons
first of all:
myperson.ToString() returns the object class name. not first/last-name
so i add a method:
tostr (){
...
}
with the logic in tostring(),
this works. returns firstname. but
if i (on the client) myperson.stringtype =ToStringType.LastName;
and debug the application, i see that myperson.stringtype IS ToStringType.LastName
but the method returns firstname.
i would really get the tostring to work since i'm adding the person[] to a combobox and i prefer not to use datasource/bindings. (tried those to. same problem, Displaymember has no effect)
how come this split personality disorder in my classes, and why does ToString return the class name instead of my overloaded ToString method?
I hope someone can help me
regards Tomas
There is no spoon
modified on Tuesday, June 30, 2009 10:54 AM
|
|
|
|
|
Why didn't you make lastName public like firstName?
|
|
|
|
|
Edited, Thanks for noticing! allthough this was just an example and not the actual code, else the post would have been very very long
If it' stuck, DO NOT pull harder!
|
|
|
|
|
Maybe the StringType is not serialized correctly. I think you have to think about, how to serialise this type...
|
|
|
|
|
I tried changing StringType to int. did nothing. This confuses me a little.
The properties of the object can be modified and keeps their state on the client. but all changes
are lost on the server. since it is stateless one would think that the "original" values also
would be lost, and why isnt the client object values passed to the server for method invocation.
thank god for Apress Books and vacation coming up
Anyway, i solved this by having a local class with the same properties and my custom ToString.
If it' stuck, DO NOT pull harder!
|
|
|
|
|
Just wondering as rxMessage is looking at the 3rd byte not the second am I right putting :
switch (rxMessage[2])
{
case 0x56: // "V" Version Number Request
if (rxMessage.Length == 3)
{
rxCommmandType = commandType.VersionNumRequest;
}
else
{
throw new IndexOutOfRangeException("Inavlid data entered, "
+ "Incorect number of bytes for a display update");
}
break;
|
|
|
|
|
I don't quite know what you are trying to do but one thing that stands out is you are checking to see if the array length is big enough after you access the data. If you want to check if it is available to access then do it before the switch.
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
Ah im just using it to check that i have recieved the correct number of bytes.
If there are more than three bytes in the recieved array then something is wrong throwing an exception.
In other words checking nothing follows the Version number request
|
|
|
|
|
switch (rxMessage[2]) <- change to rxMessage[1] since arrays starts at 0.
rgds Tomas
If it' stuck, DO NOT pull harder!
|
|
|
|
|
byte 0 and one are filled i didnt add this code because it would have crowded the message
<code> // COMMAND HEADER
if (rxMessage[0] != (byte)'J')
{
throw new InvalidDataException("Error: Invalid Command Header found");
}
// MCU TYPE
if (rxMessage[1] != (byte)DEVICE_ID)
{
throw new InvalidDataException("Error: Invalid Device ID");
}
|
|
|
|
|
Ok. i cant say i really understand your question, but rxMessage[2] is the 3'rd byte if that's what you're asking. MCU's are cool btw. i use AVR's alot
If it' stuck, DO NOT pull harder!
|
|
|
|