View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Sending straight binary data on a serial port |
Posted: Sun Nov 29, 2009 11:11 am |
|
|
Hello,
I have a question for the many experts in this forum:
I am trying to use a serial RS232 port to send binary data, that is binary data in various format lengths; i.e. floats, 32bit or 16 bit variables. In the past I have done this many times using the serial port by using a “command” type format where you have a start like STX and end ETX delimiters and all the data is sent as ascii bytes and then you have to do all the parsing at the other end. But now I need to send straight binary values and data, I realize that the standard serial ports are meant to only handle a frame of bits of either 7 or 8 bits with start and end delimiters. I imagine that one would have to use some form of packed or packetized data which I have never done before, any ideas hints or resources would be greatly appreciated.
Thanks |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Nov 29, 2009 11:44 am |
|
|
The rs232 interface sends zeros and ones wrapped with start and stop bits. The receiver and the transmitter are configured to accept the same parameters as to parity and stop bits. The physical layer of rs232 transmission is isolated from the logical layer. The transmitter sends bits and the receiver accepts them. It matters little to rs232 as to what the zeros and ones represent ( ascii char integer part of a float). If the transmitter and the receiver both use the same notational format of a float then the zeros and ones received can be immediately accepted into a float variable. Ex a float is 4 bytes so transmit 4 bytes and have the receiver save the 4 bytes into a variable that is assigned to represent the same float notation as the transmitter was using ( 23 bit mantissa 8 bit exponent with compatible big endian or little endian format). Often a union is used to to overlay a 4 byte array on the float so the RS232 interface can be fed a byte of the float at a time ( same goes for 16bit integers and 32 bit integers) |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sun Nov 29, 2009 12:20 pm |
|
|
Thank you for your help. The only thing I don't understand is how does the receiver (either PIC or PC) know how to handle the next incoming variable, 16 bit, 32 bit or float. Does it count the number of incoming bytes into a receive buffer then determine what the type of data is? if that is so, it would also need to somehow know the begining and end for that data sequence. |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sun Nov 29, 2009 12:25 pm |
|
|
I guess I left one thing out of my previous statement, based on your approach description the data assumes to be a fixed data length or format, but I need to send various types of data lengths from a simple char to a signed 32 bit or float (although I guess I could just use floats for all values greater than a byte in length) |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Nov 29, 2009 1:10 pm |
|
|
Quote: | how does the receiver (either PIC or PC) know how to handle the next incoming variable | The PIC doesn't know anything. You have to define an suitable application protocol. I see two options:
- Define your private protocol
- Use an existing one, even if it has other features that arent's presently used in your application. MODBUS would be a
possible candidate, as an advantage, CCS C comes with ready-to-use (more or less) drivers for it. I guess however,
you are able to indentify about a half hundred different UART based field bus protocols, so you have many other options. |
|
|
mbradley
Joined: 11 Jul 2009 Posts: 118 Location: California, USA
|
|
Posted: Thu Dec 03, 2009 1:23 am |
|
|
just a thought, have a start byte that defines what is being sent...
example a 1 is for 1 byte, 2 is for 2 bytes (16bit), 4 for 4byte (float)
Code: |
putc(1);
putc(byte);
putc(2);
putc(make8(int16,0));
putc(make8(int16,1));
putc(4);
putc(make8(int16,0));
putc(make8(int16,1));
putc(make8(int16,2));
putc(make8(int16,3));
|
or something to that effect....
on the rx side, reassemble the bytes according to the first byte.
just my 2 cents _________________ Michael Bradley
www.mculabs.com
Open Drivers and Projects |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Thu Dec 03, 2009 9:16 am |
|
|
mbradley wrote: | just a thought, have a start byte that defines what is being sent...
|
This will work as long as the transmitter and the receiver don't ever get out of sync. In short, it is a dangerous protocol that does not have some means of ensuring synchronization. For example, if the application allows, you could use timing as a source of synchronization. If more than, say, 3 character times goes by without anything being received, then the receiver would assume that the next character is the start byte you spoke of, even if the receiver thought it was only part-way through the previous packet. Of course that relies on having an application that can afford to enforce these inter-packet gaps, and having a receiver that is capable of measuring incoming character timing.
Another solution is to encode binary data into a less-efficient stream that ensures synchronization. For example you could encode each byte as 2 characters. The 8-bit data can be contained in the low-order 4-bits of each of the 2 characters, and the remaining bits can be used to mark the beginning of a packet and type of packet contents. It is less efficient in terms of bandwidth, but easier to implement than the timer method. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah Guest
|
|
Posted: Thu Dec 03, 2009 10:50 am |
|
|
Yes.
The problem you always have, is that you need to reserve codes for your 'start' marker, so if you are sending all possible 8bit values, the marker may accidentally happen in the data, and disaster may result.
RLScott has mentioned one solution, which is to avoid sending all possible 8bit values (send alpha text, or hex for example, leaving other characters for control). The alternative, is to take advantage of 9bit support. Use the presence of bit 9 set, as a 'start' marker, and turn it off for the rest of the data. This then allows binary data to be sent, and a packet sync, at the cost of only one extra bit per byte.
Best Wishes |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Thu Dec 10, 2009 6:53 am |
|
|
Thank you guys!!! for all the pointers; as usual I am always learning from others in this forum. |
|
|
|