cancel
Showing results for 
Search instead for 
Did you mean: 

possibly more efficient USART comm?

jonphenry
Associate II
Posted on June 05, 2013 at 23:25

I've been working on a project with an stm32f4 and the .NETMF framework. I hit a wall with the garbage collector in .NET hampering my timing abilities and so have erased the chip and gone native. My background is in C# (where memory usage isnt a big issue) and am diving back into C.

Im reading my devices (I2C) fine and am now working on sending the readings out over USART. im using snprintf at the moment, but after some research have found that the function is quite a memory hog. I was taking my values (floats), converting them to chars and building a string with them. IE $TEL,-44,74,41,\r\n --> About 10-12 more values, but you get the picture. I was using 8 for the size of the snprintf() function (signed number up to 9..-***.xx\0 plus the null terminator). So, I was converting a float into 8 bytes or chars in C while losing some resolution in limiting to two decimal places.

While contemplating how to do it better, this hit me. In converting a number to a string or char[] in C, all were doing is taking its actual number value and converting each number to an ascii byte. The USART is still pushing out and taking in 8 or 9 bits at a time for use. Whats to stop us from doing this?

float gyro; /* Create float of 4 bytes named gyro */
char *pGyro; /* Create pointer pGyro */
pGyro = gyro; /* Copy address of gyro into pGyro */
int main(void)
{
USART_SendData(USART6, *pGyro++); /* Send 1st byte or 'char' of float gyro to USART */
USART_SendData(USART6, *pGyro++); /* Send 2nd byte or 'char' of float gyro to USART */
USART_SendData(USART6, *pGyro++); /* Send 3rd byte or 'char' of float gyro to USART */
USART_SendData(USART6, *pGyro); /* Send 4th byte or 'char' of float gyro to USART */
}

(Its been a long time since Ive dealt with pointers, forgive me if Im using them wrong, but the general concept I think is apparent.)

Basically:

  • create a float...gyro.
  • Create a pointer.....*pGyro.
  • Copy the address of gyro to *pGyro
  • Send *pGyro++ to USART to send out 1st 8 bits then increment the address by a ‘char’s worth of bits or a byte and repeat three more times.

If Im thinking about this correctly, this would basically send the 'float value' of gyro over USART while it sits in its memory place without having to use more memory to store its numerical values in characters somewhere. This would also cut transmitting down 4 bytes and keepi the resolution instead of 8 bytes and losing resolution. Wed also lose all the overhead of converting to char using snprintf() or something like that.

The receiving end of this transmission would have to know exactly what is coming type-wise and in what order and require some checks, but Id think this could be done.I know way too little about this microcontroller or C in general to know for sure.

Anyone ever attempt to or actually implement something like this?

5 REPLIES 5
Posted on June 06, 2013 at 01:00

Anyone ever attempt to or actually implement something like this?

People have been doing it for decades. It's called a binary protocol, and usually has a defined packet structure.

http://gpsd.googlecode.com/files/Ashtech-Missile-Applications-Condensed-Measurements.pdf

When spitting out GPS measurements as 64-bit doubles at 20 Hz, you don't lose precision, and you don't waste time converting to/from decimal. Decimal is only helpful for humans, the machines really don't care for it.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 06, 2013 at 06:55

pGyro = &gyro; /* Copy address of gyro into pGyro */

trevor23
Associate III
Posted on June 06, 2013 at 11:04

Wrap into a function like below. But you must think carefully about Endianness problems with this approach. A more portable approach is to run the data through a function that ensures a pre-defined Endianness format. See here:

http://www.ibm.com/developerworks/aix/library/au-endianc/index.html?ca=drs-

void tx(const unsigned char *data, int size)

{

    while (size--)

        USART_SendData(USART6, *data++);

}

float f = 1.999;

int32_t my_int32 = 32;

int16_t my_int16 = 16;

// send float

tx(&f, sizeof(f));

// send 32 bit int

tx(&my_int32, sizeof(my_int32));

// send 16 bit int

tx(&my_int32, sizeof(my_int32));

jonphenry
Associate II
Posted on June 06, 2013 at 18:27

Welcome to the Embedded World! lol   Thank you gentlemen.I shall research this and definitely implement it.

I guess I should leave the comfy confines of my memory rich desktop world more often, seems the embedded world has much to teach me about efficiency.
jj2
Associate II
Posted on June 06, 2013 at 18:46

You'll often hear ''squawks'' here re: lack of vendor participation.  (so true)  And yet the breadth & depth of response - erupted here in your behalf - unlikely to result from, ''this - and this MCU only'' indoctrination/focus.

May I say, ''Great job, guys!''  Benefits not only op - but all those who follow.  Thanks to all.

On occasion - ''inside info'' really speeds/eases/extends MCU tech problem solving - and the ''seeming'' absence of vendor care/concern cannot positively impact sales.  And - in aggregate - users here may surpass ''hallowed'' clients who are regularly/exhaustively tech serviced...

Its not that only vendor's best/brightest are needed here - but eased/accelerated access to ''inside info'' can solve many issues - and prevent delays caused by ''enforced guessing - blind-alley experimentation'' - necessitated by too little vendor attendance. 

And - might ''forum lurking'' be an efficient means to train/develop new tech staff?  Many sharp, diverse & original minds here - suspect that even key (exhaustively serviced) clients may not hit upon all of the issues/methods - regularly bubbling forth - this (far underserved) space...