-1

I am using Tiva C Series TM4C123GH6PM with Code Composer Studio for getting data from another microcontroller of the same type. Well, I get the data in bytes. The Goal of project is to assemble each 8 bytes and convert them to double then send these double to the computer. I have to use USART to send the data to the computer.

When I use USART, I have two Methods:

  1. One to get data from a USART_x: UARTCharGet(UART1_BASE)
  2. The other to send the data over USART_x: UARTCharPut(UART0_BASE,d)

The problem consists in having two methods that accept only characters. So using these methods for double is impossible since a double is 8 bytes and a character is one byte. I am trying to send doubles to my computer. Any idea?

The second Problem is to write a program from the side of the computer to get the data (bytes) from the microcontroller.

Should I write this program in c (an alternative is using matlab because I will use these data for simulation)? How can I access com-Port in c (or in matlab if it is possible)?

amitakCs
  • 355
  • 9
  • 25
  • There are numerous examples of how to read/write a serial port in C (http://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c). What OS are you using? – Cloud Aug 17 '15 at 12:23

3 Answers3

1

You need to find a way to break up large amounts of data, and send it to the client, who then needs a way to re-assemble the data, and also know when such data is being sent.

A very simple approach would be to convert all the digits of the double to characters. Inefficient, but it gets the job done easily enough, as shown below. The reason this is preferable is because it lets you easily create your own "instruction set". For example, you could reserve the character '!' as "the letter following ! denotes a special instruction", so when the client sees the sequence "!d", it knows the following 32 bytes of data represent a double, and to re-assemble it.

If you just send the raw bytes, it becomes more convoluted when you want to create escape codes or op codes to signal special circumstances to the client.

Code Listing


#include <stdio.h>

#define BUF_LEN (32)
typedef union {
    float f;
    struct {
        unsigned int mantissa : 23;
        unsigned int exponent : 8;
        unsigned int sign : 1;
    } parts;
} double_cast;

int main(void)
{
    double_cast d1;
    d1.f = 0.15625;
    printf("sign = %x\n",d1.parts.sign);
    printf("exponent = %x\n",d1.parts.exponent);
    printf("mantissa = %x\n",d1.parts.mantissa);

    char buf[BUF_LEN+1] = { 0 };
    snprintf(buf, BUF_LEN+1, "%01X%08X%023X", d1.parts.sign, d1.parts.exponent,
         d1.parts.mantissa);

    // Send over UART
    printf("Double as string: [%s]\n", buf);

    //UART_printf("!d%s", buf);    

    return 0;
}

Sample Output


sign = 0
exponent = 7c
mantissa = 200000
Double as string: [00000007C0000000000000000020000]

Credit for the code to break a double into a string goes to u/eran.

Community
  • 1
  • 1
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • 1
    Very nice solution. The only drawback I can see in your solution is bit-fields potability, other than that it is excellent solution. However our colleague might need procedure to retrieve double from string on the other side as well. – Krystian Sakowski Aug 15 '15 at 22:12
  • 1
    @KrystianSakowski Good point. In production, I wouldn't use this, but for what I assume is a quick-fix or homework problem, it should be adequate. I figured string parsing commands would be a touch easier than the more effective/difficult op-code scenario one would use in a real product. :) – Cloud Aug 15 '15 at 23:29
  • @Dogbert. On the Microcontroller I can only send Characters. No way for Srings – amitakCs Aug 16 '15 at 12:28
  • 1
    This string is represented as an array of characters so no worries. It will work just fine for you. – Krystian Sakowski Aug 16 '15 at 12:44
  • @amitakCs In C, a string is just a character array followed by the `NULL`/`'\0`' character. In your case, you can just send the characters one at a time with a loop. – Cloud Aug 16 '15 at 23:55
  • NO, it will not work. I know that a string is an array of characters followed by '\o'. I have already tried to send a string using UARTCharPut. Only the last character is transmitted. The function UARTCharPut can distinguish between characters and strings – amitakCs Aug 17 '15 at 08:24
  • @amitakCs If only the last character is transmitted, it sounds like a fault in your implementation of `UARTCharPut`. Also, you meant `'\0'`, not `'\o'`: there's a world of difference between the two. Did Krystian's approach end up working out for you? – Cloud Aug 17 '15 at 12:21
  • The function UARTCharPut is provided from texas instruments. So it normally works fine. So to transmitt a double, you should convert it into an array of Bytes. Each Byte can be saved as char, since a Byte is represented in c/c++ as char. Then you should send each Byte using UARTCharPut . – amitakCs Aug 22 '15 at 22:57
  • @dogbert Here is some description of the method UARTCharPut: //***************************************************************************** // //! Waits to send a character from the specified port. //! //! \param ui32Base is the base address of the UART port. //! \param ucData is the character to be transmitted. //! //! This function sends the character \e ucData to the transmit FIFO for the //! specified port. If there is no space available in the transmit FIFO, this //! function waits until there is space available before returning. //! //! \return None. – amitakCs Aug 24 '15 at 22:58
  • @dogbert Please read what I have written. I have never said that TI is incompentent. I only said that UARTCharPut is used for transmitting characters not Strings. TI is big company and I am a just a beginner. I never said that TI is incompetent. If you have already used UARTCharPut for transmitting a string at once without splitting it, then you must say it to me clearly. I will try to do it like you, so I can save time – amitakCs Aug 24 '15 at 23:03
0

Another solution (similar to the solution of Krystian) that works for me. I defined a function that has as parameters a double and an array of Bytes. The double must be converted to an array of Bytes. That´s why I defined an array of Bytes which has a size of 8 Bytes. Here some code:

unsigned char bytesArray[sizeof(double)];

unsigned char * doubleToBytes(double num,unsigned char bytes []){
    return memcpy(bytes,&num,sizeof(double));
 }

After getting the Bytes in the Array you can send data using the following loop:

for(i=0;i<sizeof(double);i++){
    UARTCharPut(UART1_BASE,(unsigned char)*(bytesArray+i));

}
amitakCs
  • 355
  • 9
  • 25
-1

Generally speaking you are facing here serialization problem and the best approach would be using specialized library for this purpose.

In a dirty but simple way you can solve it like that. You have to just properly assemble your data on the other side back to double.

typedef union _MyDouble {
    double d;
    unsigned char bytes[sizeof(double)];
} MyDouble;


MyDouble my_double;
my_double.d = 1.234;

for(i=0; i < sizeof(double); i++) {
    UARTCharPut(UART0_BASE, (char)my_double.bytes[i]).
}

The other thing is that if you are using UART you should encapsulate this union into some frame e.g. in order to successfully reassemble this on the other side.

 _____________ ________ __________ ___________ ________
|             |        |          |           |        |
| FRAME_BEGIN | LENGTH | MyDouble | FRAME_END | CRC-8? |
|_____________|________|__________|___________|________|

The next thing is that you should probably enforce byte alignment on this struct which is done by the compiler directives. It ensures that your struct has no padding bytes etc. and allocates minimum requires size. This is very popular in embedded applications use-cases where some binary object is going to be transmitted on the serial interface - which is exactly your case. Such a simple solution might work on specific hw+sw configuration but for sure it is not portable and good solution from professional point of view.

Krystian Sakowski
  • 1,613
  • 14
  • 20