Electronic – Sending “larger than 8-bit” quantities over an 8-bit link

uart

I have data that I logically manipulate in 12-bit quantities which I need to move over an UART link. (actually soft-serial from Mbed to PC over USB cable, but that's irrelevant)

I was thinking about using the common 8N1 (8 data bits, no parity, 1 stop bit) UART setup, which just leaves me with the question of how to "chop up" my 12-bit values in to two 8-bit "packets".

I could of course implement something trivial myself like sending the 8 lowest bits first and then sending the 4 highest bits in the second packet, with the other 4 bits of the second packet not used. Or I could chop it up in to two 6-bit pieces, with the other 2 bits of each packet either unused or designated for meta-information (like whether the current packet is the first or second half of a 12-bit quantity).

Before doing that I wanted to see if there was any standard or a "standard industry practice" way of chopping up data larger then 8 bits in to 8 bit quantities?

Link speed should is not a issue since my requirements are about 3 kbps.

(In the absence of a "low level communications protocol"-Stack-Exchange I feel this is the most suitable platform for this type of question, per various discussions on Meta.)

EDIT: All answers were valid and good. I marked Olin's answer as correct since it's the way I went with my project.

Best Answer

No, there is no standard or even generally accepted common practise.

If you are really sure all you will ever send over this link is a stream of 12 bit values, then you can put 6 bits in each byte and use the remaining 2 bits to identify whether this byte contains the high or low 6 bits of the 12 bit word. That leaves two more codes for a little expansion.

However, that's not what I'd, and certainly not what I usually do. No matter how much you think to the contrary now, chances are good that sooner or later you'll wish you could send something else over the link, even if just for debugging. Since you say bandwidth is not a problem, do it right now so that expanding the protocol will be easy.

What I usually do is send data in packets that start with a opcode byte, which is then followed by whatever data goes along with that opcode. I have done this many times. For clarity of documentation, I call packets from the host to the micro commands, and from the micro to the host responses, but that doesn't mean responses must be only a result of commands.

This scheme is easy to implement in firmware. It's easy on the host too, but that doesn't matter. With the infinite processing power and memory of a PC, any protocol you cook up that is tractable on the micro will be easy on the host. The point is to keep it simple on the small resource-limited system and have the other system adapts as necessary.

On receiving, I use a jump table for the opcode byte. That dispatches to the routine unique for that command, which knows how many more input stream bytes to read and what to do with them. When done, command routines jump back to a common return point, which fetches the next opcode, dispatches thru the table, which runs the next command routine, etc.

Once you have this mechanism set up and a test program on the host to read and write this protocol, it is really simple to add another command or response. Being so simple, you'll start to use this facility in ways you might not have envisioned at the start. For example, you can make a command that sets a debug bit in the firmware which causes other code to do something special. Or you realize there are some options you would like to control, maybe read back data memory, a special command that does something one-off for testing, etc, etc. This sort of stuff comes in really handy a lot.

To solve the particular case you asked about, you'd have a response that is followed by 2 bytes which contain the 12 bit number. In the micro, that's as simple as sending the response opcode byte followed by the two data bytes periodically. Meanwhile it leaves open the option of sending other things without messing up the stream of 12 bit values.

Related Topic