6
\$\begingroup\$

I just have a few general questions that those with more experience could easily answer.

I am working with an arduino, and interfacing with various devices such as the PC that I use to write the arduino C code, which is obviously plugged in via USB, and I have had success with a serial link to an iphone by connecting the tx/rx pins.

  • What sort of data integrity guarantees are there for the serial link? For example if the cable connecting two devices becomes frayed or damaged, what sort of changes might I expect my data stream to undergo? Could it start receiving garbled data, or will it just cut off?

  • Is its functionality fully encapsulated by a byte stream? Suppose I want to relay 16-bit numbers. My first and only instinct is that I must come up with my own protocol (big-endian or little, for example) to pack my data into a byte stream and write to the port? It functions more or less like a network socket (minus the concept of packets) does it not?

\$\endgroup\$
16
\$\begingroup\$
  • Async serial has no data integrity guarantees. If data integrity is important to your application, add a checksum. But if everything is connected properly, it should be pretty solid.

  • You get a series of bytes. The rest is up to you.

  • If the serial is connected while transmission is underway, it will not automatically synchronize. Some garbage will appear on the line.

One common scheme is to represent data with packets. Then the packet format is like:

[sync byte][data length byte][data bytes][checksum byte]

There are a lot of variations on it. The sync byte lets the receiver synchronize if it gets a partial message. The sync byte can be escaped if it appears elsewhere in the packet, or not. Checksum can be a sum of all bytes, or XOR, or CRC16, etc.

An alternative is to only use ASCII for the serial communications. Then you can synchronize on the '\n' at the end of the message. This is a nice format for debugging, because you can use your favorite terminal emulator.

\$\endgroup\$
  • 7
    \$\begingroup\$ +1 for using ASCII. Most apps have processing and bandwidth to spare for this. It's also more immediately apparent when you're getting garbage. \$\endgroup\$ – John Lopez Feb 16 '11 at 4:38
  • 2
    \$\begingroup\$ +1 for mentioning that it will not automatically synchronize. Many experienced engineers don't seem to get this. \$\endgroup\$ – MikeJ-UK Feb 16 '11 at 10:49
  • 1
    \$\begingroup\$ @JustJeff - And I've seen people send a stream of 0x55 bytes with no gaps as a 'synchronization pattern' without realizing that if connected 'mid-stream', the receiver could take any of the zero bits as a start bit and get valid bit-framing, only to fall-over when the first real data byte arrives. \$\endgroup\$ – MikeJ-UK Feb 16 '11 at 23:34
  • 2
    \$\begingroup\$ It doesn't necessarily work - that was my point. I think we were over-complicating the issue from your point of view. Just be aware that if you need very reliable communications, your receiver should check the data against some expected pattern. If the pattern doesn't match, throw the data away and wait until it does. The more complicated you make the pattern, the less likely it will be to be erroneously detected in corrupted data. \$\endgroup\$ – MikeJ-UK Feb 17 '11 at 11:27
  • 1
    \$\begingroup\$ You can have bitwise synchronization problems too, if the receiver see a low bit and thinks it is a start bit. Then you have a 50-50 chance of the "stop" bit being valid too, so the UART thinks it has a valid byte. The checksum will save you from this. \$\endgroup\$ – markrages Feb 21 '11 at 2:43
5
\$\begingroup\$

Just to clarify the various comments about synchronisation at the bit level, I have sketched some example bit patterns (not very well!). First, remember that the async bitstream consists of a logic-low start-bit, a number of data-bits (typically 7 or 8), an optional parity-bit and a number of logic-high stop-bits (typically 1 or 2). The data-bits are sent LSB first. Parity is not that often used as the integrity it provides is minimal compared to a vertical checksum as markrages has recommended. The most common format is 8 data-bits, no parity and one stop-bit.

Async serial examples

The first trace shows a pair of 0x55 bytes - the green and red rectangles representing the start and stop-bits respectively. As you can see, this is a square wave so the receiver can't tell which low bit is the start bit, since every low bit is preceded by a high bit (which could be a stop bit). Which ever way the receiver looks at it, this represents a pair of 0x55 bytes but only one way has the correct framing. This was the basis of my earlier comment.

The second trace represents a pair of 0x10 bytes. However, the receiver may see the bits marked by the triangles as framing bits and (incorrectly) decode a pair of 0x04 bytes.

The third trace represents a pair of 0xFF bytes. There is no ambiguity here as all the low bits are genuine start-bits - hence JustJeff's earlier comment.

A typical sequence is as markrages says in his answer. Traditionally, 0x01 (Start-Of-Header) or 0x02 (Start-Of-Text) have been used as a start byte but a pair of 0xFF bytes is more reliable as JustJeff says. You might also want to put a 'stop-byte' at the end. Traditionally, 0x04 (End-Of-Transmission) and 0x03 (End-Of-Text) have been used for this purpose. Finally, always check your receivers framing-error status!

\$\endgroup\$
  • \$\begingroup\$ Remember, even with the best-chosen start bits, if the receiver starts listening during the data bytes, it can be out-of-sync until the next message. Hence, checksums. \$\endgroup\$ – markrages Feb 21 '11 at 18:42
  • \$\begingroup\$ This is really great. Thanks for further clarifying! \$\endgroup\$ – Steven Lu Feb 22 '11 at 4:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.