how to efficiently send data between microcontrollers using UART? - Page 1
Forum section: electronics / beginners

author: V_King
author_rank: Regular Contributor
timestamp: December 15, 2015, 12:17:01 pm
content: Hello,I am building a system, which requires sending data between two microcontrollers. I only have UART available for it.the uC1 gathers data in time intervals (with interrupt), puts it into a circular buffer, and when the UART transmit register is empty, it unloads the data from the buffer byte by byte.the uC2 receives the data from uC1 and then does the number crunching and data representation.I am using a separate pin to control uC1 data gathering from uC2. when the pin goes low, the uC1 gets a signal to start timer and gather data. The problem is that the first 10-20 data points I receive are garbled with some bad data, after that all is fine. So if I am to pull the UART data from uC2 buffer, as I would have assumed the data have arrived, is in the order as I sent it, the whole received data is rubbish. Something somewhere gets lost/misinterpreted. I always make sure in a code, that the buffers on both microcontrollers are empty before starting data transmission.I tried converting the data in uC1 using utoa(); functions etc, but that takes quite a bit of time which I do not have on uC1 or just don't know how to efficiently use them.what would be an efficient and fast way to send data between microcontrollers? efficient ASCII conversion and string buffers? Is there any good read of how to use those? Any other approaches?Thanks in advance.

author: Jeroen3
author_rank: Super Contributor
timestamp: December 15, 2015, 01:01:11 pm
content: The first dozen chars of ASCII are control chars. You can use these as control chars for the datastream.http://www.ascii-code.com/You can then hex-encode the data, that means that each nibble is exploded to a full ascii digit. Don't bother converting the base if you don't need humans to read it.Code:STX - 0 - 1 - A - B - ETX - repeat - EOTto transfer 427.Or something like that.

author: AndreasF
author_rank: Frequent Contributor
timestamp: December 15, 2015, 01:17:57 pm
content: How confident are you that the data aren't already garbled before being sent by uC1? Are these single bytes or multiple bytes per value? For single bytes nothing is going to be more efficient than sending the raw unconverted bytes (apart from some sort of compression scheme, e.g. run-length-encoding). If these get garbled but come out OK after a while, I would suspect baud rate problems/asynchronies.For multi-byte values you could consider splitting the raw value onto the available bytes differently (or use extra bytes) and use unused bits as identifying markers: e.g. you could split a 16-bit value into 3 bytes:Code:b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0could be split into 3 bytes:byte1: 0 0 b15 b14 b13 b12 b11 b10byte2: 0 1 0 b9 b8 b7 b6 b5byte3: 1 1 0 b4 b3 b2 b1 b0The first 2 bits of each byte would tell you which byte you received. The encoding and decoding involves a bit of bit-shifting and masking, but nothing too serious.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 15, 2015, 01:27:43 pm
content: monitor the data on a PC, and try sending test data from a PC, so you know if the problem is at the Tx or Rx end.Chances are your buffer pointers are messed up and it's reading garbage initially.

author: Ian.M
author_rank: Super Contributor
timestamp: December 15, 2015, 01:54:05 pm
content: While there are many async serial protocols that could be used + methods of bit or byte stuffing the datastream to packetize it so loss of synchronisation can be recognised and corrected, its rarely desirable to use them if you are writing the code for both ends of the link. The problem is that both ends must match which vastly increases the difficulty of debugging all except the most trivial protocols.In most cases, it is preferable to send the data as HEX with human readable ASCII delimiters for the start and end of each packet. That, at best, uses less than 50% of the link capacity for actual data, but has the major benefit that you can write one end's code at a time and debug it while driving/monitoring it with a simple PC terminal program. In most cases, unless you are dealing with long distances or very high data rates, you aren't 'up against the wall' for link speed so can simply regain nearly all the data link capacity by increasing the baud rate to the next higher PC one.

author: tszaboo
author_rank: Super Contributor
timestamp: December 15, 2015, 02:25:11 pm
content: What is the transmission speed? Do you have crystal for both uCs? Are you using the parity bit of UART? Are they the same architecture/ are you sure that the settings are the same?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 15, 2015, 02:32:54 pm
content: ..and have you full yread and understood the UART section of the datasheet?And checked the data on a scope?

author: lukier
author_rank: Unknown
timestamp: December 15, 2015, 02:45:20 pm
content: I wondered about something similar recently. Most of the time I'm using something similar to Modbus, with magic number header, payload length, payload and CRC. Often polling/interrupts to read the header and DMA for the payload.Recently, I wanted to try Consistent Overhead Byte Stuffing to robustify the transmission, but I wonder how to implement that efficiently on STM32, i.e. detect 0x00 demarcation bytes and receive unknown length packet in between them.Even at 115200 bps polling or interrupts are not very efficient and STM32 USART doesn't have a FIFO (like for example 16550 compatible controllers have). Another, efficient, option is DMA, but it requires the number of bytes to transfer to be known beforehand.Any tips?

author: free_electron
author_rank: Super Contributor
timestamp: December 15, 2015, 02:52:57 pm
content: fixed frame size no larger than the fifo on the uart. dma handler on receive firing an interrupt when a packet is in.

author: lukier
author_rank: Unknown
timestamp: December 15, 2015, 03:14:43 pm
content: Sorry, no FIFO in STM32 USART. Byte per byteWith fixed packet size things get much easier and it could be doable, as the DMA controller can be set to this fixed transfer size and interrupt only on transfer complete / half of the transfer etc.This however doesn't solve the problem, when using COBS, of detecting 0x00 demarcation bytes efficiently to synchronize the reception, even of fixed width packets.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 15, 2015, 04:02:44 pm
content: Quote from: lukier on December 15, 2015, 03:14:43 pmAs long as the DMA controller can do double-buffer swapping, you can use it to implement a FIFO of whatever size you want.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 15, 2015, 04:08:14 pm
content: Quote from: lukier on December 15, 2015, 02:45:20 pmSeriously? one byte every 86uS should be trivial to handle under interrupts on an ARM unless you have other interrupts that are taking way too long to service.I'm not familiar with the STM32 but that has to be at least a thousand clocks per byte...I regularly do 4Mbaud on a a PIC32 at 48MHz with only an 8 byte FIFO - it starts getting sketchy at 6Mbaud, mostly because teh PIC32MX1xx don't have shadow registers so int entry/exit overhead is a bit high.

author: Kalvin
author_rank: Super Contributor
timestamp: December 15, 2015, 04:27:06 pm
content: Straight binary using 9-bit UART mode. If the data packet size is of constant length, no overhead is needed. If the data packet size can vary, use the first byte to have the length of the payload.

author: lukier
author_rank: Unknown
timestamp: December 15, 2015, 04:36:43 pm
content: Quote from: mikeselectricstuff on December 15, 2015, 04:02:44 pmGood idea! Thanks. Higher end, STM32F2 and F4 series DMA controllers support that.Quote from: mikeselectricstuff on December 15, 2015, 04:08:14 pm115200 is doable, although I still wince if I get interrupts coming at thousands per second or higher rate, especially when MCU has plenty of other stuff to do. I was just wondering, as per title of the thread, what would be the most efficient way, especially on a bit crippled low end MCU (like STM32F0/F1, no FIFO in UART, basic DMA controller).

author: Wilksey
author_rank: Super Contributor
timestamp: December 15, 2015, 04:53:01 pm
content: When I do a UART comms interface I typically have the following:Sometimes I will add a length in as well for the payload, but I do try and make fixed length and pad the rest.CRC is a simple XOR, not the best by any means, but works OK for what I use it for.The payload can be a number of bytes all within the uchar range (0 - 255) 0 denotes a "null" and can be used for padding or stipulating the end of the payload depending on how you want to implement.STX and ETX are typically defined as 0x02 and 0x03.You can look here for "common" control characters:https://en.wikipedia.org/wiki/Control_characterHTH!

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: December 15, 2015, 05:50:13 pm
content: For a super-simple way of framing packets, I sometimes reserve 0xff as a "start" byte. Especially handy for lighting type applications where you can easily live with only 254 brightness levels. Avoids any need for framing timeouts etc. and keeps the ISR super-simple so handling higher baudrates is easier.