This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Tiva TM4C123G UART transmission

Hello everybody, I am currently programming a Tiva C series, TM4C123GH6PM Evaluation Board from TI.

I need to send a relatively large amount of data to the virtual com of the PC. This board has an integrated virtual com feature (as soon as you plug the usb, and install the drivers, a virtual COM is generated).

I've configured the UART0 peripheral, and used the UARTprintf command, and it works properly.

But, as far as I know, this is only for strings/chars types. I need to send an array of 300 elements, made by 16-bit registers.

I've read about the UART, and the uDMA feature. I don't know if activating the DMA is necessary in this type of transfers, or if it's enough with a while loop. I've seen a lot of code-examples, and read the TI forum, but I'vve found nothing like what I need. In every example I saw, they just use the UART to echo what you sent from the PC.

Can anybody give me a hint on where to start?
I'm not asking for anybody to solve this for me, only perhaps to point me in the right direction.
Thanks a lot for taking the time to read this.
Kind regards

Martín

  • The UART doesn't care what you send. It will try to send anything you put into the transmit register.

    But the transmit register is small, and you have a limited number of data bits you can program the UART to send.

    So you would normally settle for "standard" 8N1 format, i.e. 8 data bits, no parity and one stop bit.

    So sending raw data?

    You either convert to ASCII:

    #define NELEM(a) (sizeof(a)/sizeof(*(a)))
    ...
    uint16_t array[400] = { ... };
    ...
    printf("start-uint16-array:\n");
    for (unsigned i = 0; i < NELEM(array); ++i) {
        printf("%u\n",array[i]);
    }
    printf("\n");
    

    Or you make up some fancy binary protocol, and then send the data as binary, and then convert all your binary data into 8-bit bytes that you send one-by-one. Using DMA or feeding multiple bytes at a time using a UART with FIFO or feeding a single byte at a time directly to the transmit register doesn't matter.

    Let's say that putc(int) will redirect to your UART.

    Then you could do:

    void send_u16(uint16_t n) {
        putc(n&0xff);
        putc((n >> 8) & 0xff);
    }
    void send_u32(uint32_t n) {
        putc(n&0xff);
        putc((n >> 8) & 0xff),
        putc((n >> 16) & 0xff);
        putc((n >> 24) & 0xff);
    }
    ...
    

    But it's normally way easier to go with ASCII and then use sscanf(), atoi() etc to restore to binary format on the receiving end. Then normal line breaks works well for framing of the data.

    Another issue here is that if you want to send floating point data, then the sending side and the receiving side might use different binary storage methods for the same number in which case it isn't enough to just split a float into four bytes or a double into 8 bytes. And strictly speaking - the same is true for int types too even if the huge majority of all of todays processors uses the traditional two-complement format for signed integers, and make them 8, 16, 32, 64 bit large so you "only" need to care about byte order - which is trivial to handle if you pre-define a transmission order instead of sending in "memcpy()" order.

  • Just an addendum - if writing binary data to the UART, then it's normally better to directly make use of the UART than using any "stdout redirection" because different CRTL have different behaviour when processing received some "non-text" characters. So the single character representing newline (\n) can be replaced with the sequence \r\n as in Carriage Return + Line Feed, in the output stream. When using fopen(), the last parameter allows specifying text or binary mode - but with "stdout" you don't do any file open.

  • And, of course, 'C' string functions expect NUL to indicate the end of the string - so you can't use them for any binary data handling!

  • Hello, Per. Thanks for your prompt response.
    I've managed to get the array transmition working.
    But I've got some doubts that arised from your explanations.

    Since the transmit register is small, and the UART can only send a limited number of data bits, does this mean that all the data HAS to be sent in an 8-bit byte format?

    If, for example, I've used the ADC to obtain an array of 50 samples of uint32_t type... let's say smth like this:

    uint32_t pui32ADC0Value[1];
    uint32_t Valoresleidos[50];

    ....(there's a while loop here that only takes 50 samples...)

    // Read ADC Value.
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
    // Assemble an array with 50 read values.
    ADCReadValues[i]= pui32ADC0Value[0]; i++;

    .....(and later I do...)

    for (unsigned j = 0; j < 50; ++j) { UARTprintf("%d\r;", ADCReadValues[j]); }

    Can I just transmit the uint32_t values through the UART?
    Will the data transmitted be OK?
    Or do I have to convert them to binary, split them into 8-bits, and send them one by one?
    Luckily, I don't have to transmit floating point, or strings. Only signed integers of 16 or 32 bits.

    Again, thanks for your support.
    Kind regards

    Martín

  • You have to split your 32-bit values into a sequence of 8-bit or smaller values.

    But printf() is one way of doing that - it converts the binary values into a sequence of one or more ASCII characters - and every ASCII character will fit, one at a time, in the 8-bit transmit register of the UART.

    Are you sure you want to use "\r" for your line endings? It isn't a very common use. "\n" or "\r\n" are way more used. And for systems using \r\n, the \n in the C code will normally be auto-converted into \r\n in the resulting output.

  • Per, thanks again. You've been most helpful.
    I'm still considering the use of "\r" or "\r\n". The thing is, I've got to pick up the data using a software. It's still to be seen which way is better for the software programmer.

    If I understand you correctly then... if I have a uint32_t data obtained by the ADC, and I use the UARTprintf() command, then the UART automatically converts the data to ASCII, and sends it in "8-bit packages"?

    Do I have to "re-ensamble" the data on the Rx side? I'm using hyperTerminal to monitor the serial port, and as far as I can tell, the data is arriving correctly.

    Regards.

    Martín