1

The main problem is that actually I have a uint8_t* data buffer. It an array and I only know Its size and Its pointer.

I want to sprintf the data from this pointer in a buffer like this :

void send_bin(uint8_t* binarypayload, uint8_t size, uint32_t mode)
{

    char buffer[256];
    sprintf(buffer, "AT+ZF=%s,%lu\r\n", binarypayload, mode);
    HAL_UART_Transmit(&husart1, (uint8_t*)buffer, strlen((char*) buffer), 1000);
}

But on my uart I can only see the binary value on my uart:

þTÞ­˜.

Where am I going wrong ?


Sorry I have forgotten to say that my datas is like :

uint8_t buffer[4] = {0x45, 0xAD, 0xEF, 0x5B};

And I want it to look like this on my uart :

AT+ZF=45ADEF5B,45

but I only have access to its pointer

Clément
  • 37
  • 5
  • 1
    What is the expected result supposed to look like? – UnholySheep Oct 07 '21 at 15:08
  • 2
    If it is binary, then it might contain zeros. And `%s` is for *zero* terminated *strings*. – Eugene Sh. Oct 07 '21 at 15:08
  • Also it might contain something that looks like `,` , so it is not clear how you expect the format to be parsed. – Eugene Sh. Oct 07 '21 at 15:09
  • I think you have completely misunderstood the format required. The `AT` commands are usually working with text data only. Your payload should be probably something like ascii-encoded hex string. – Eugene Sh. Oct 07 '21 at 15:18
  • 1
    @EugeneSh., or it may *not* contain 0 – tstanisl Oct 07 '21 at 15:18
  • 1
    So your edit proves my previous comment. Possible inexact duplicate: https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c – Eugene Sh. Oct 07 '21 at 15:22
  • @EugeneSh. But I only have access to the pointer hown can I do ? And the data are note separated by ":" – Clément Oct 07 '21 at 15:25

3 Answers3

2

You need to convert the binary data into a hexadecimal format. The easiest way, is to convert each byte individually:

void send_bin(uint8_t* binarypayload, uint8_t size, uint32_t mode)
{
    char buffer[256];
    strcpy(buffer, "AT+ZF=");
    for (int i = 0; i < size; i++) {
         sprintf(buffer + strlen(buffer), "%02x", binarypayload[i]);
    }
    sprintf(buffer + strlen(buffer), ",%lud\r\n", mode);
    HAL_UART_Transmit(&husart1, (uint8_t*)buffer, strlen(buffer), 1000);
}
Codo
  • 75,595
  • 17
  • 168
  • 206
  • `buffer + strlen(buffer)` ? Extremely inefficient. Better accumulate the return values of `sprintf`. Or even calculate based on `i` - because it will alway print 2 characters per `i`. – Eugene Sh. Oct 07 '21 at 15:28
  • Blocking UART is so slow that a few wasted CPU cycles don't really matter. The compact size is likely more beneficial. – Codo Oct 07 '21 at 15:31
  • `buffer + 2*i` is compact enough. Or `ret += sprintf(buffer + ret...` – Eugene Sh. Oct 07 '21 at 15:34
  • 1
    If size matters, base64 encoding only expands the output by about a factor of 4/3. Hex encoding doubles the size. – Andrew Henle Oct 07 '21 at 15:45
2

snprintf can convert the bytes into their hexadecimal format in a string, but it doesn't have the automatic ability to do that to an array of them. We can call it multiple times in a for loop to enable that ability though.

void send_bin(uint8_t* binarypayload, uint8_t size, uint32_t mode) {
  char buffer[256] = {};
  int offset = 0;

  int ret = snprintf(buffer + offset, sizeof(buffer) - offset,
                     "AT+ZF=");
  assert(ret == 6);
  offset += ret;

  for (int i = 0; i < size; i++) {
    ret = snprintf(buffer + offset, sizeof(buffer) - offset;
                   "%02X", binarypayload[i]);
    assert(ret == 2);
    offset += ret;
  }

  ret = snprintf(buffer + offset, sizeof(buffer) - offset,
                 "\r\n");
  assert(ret == 2);
  
  HAL_UART_Transmit(&husart1, (uint8_t*)buffer, strlen((char*) buffer), 1000);
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
0

sprintf on uC for this simple task is overkill. And it will not work if you decide to use RTOS in your project.

I would:

const char digits[] = "0123456789ABCDEF";

char *dumphex(char *buff, const void *data, size_t size)
{
    char *wrk = buff;
    const uint8_t *u8data = data;

    if(buff && data)
    {
        while(size--)
        {
            *wrk++ = digits[*u8data >> 4];
            *wrk++ = digits[*u8data & 0x0f];
        }
        *wrk = 0;
    }
    return buff;
}

or if you do not want to use lookup string

#define GETDIGIT(x) ((x) > 9 ? ((x) - 10) + 'A' : (x) + '0')

char *dumphex1(char *buff, const void *data, size_t size)
{
    char *wrk = buff;
    const uint8_t *u8data = data;

    if(buff && data)
    {
        while(size--)
        {
            *wrk++ = GETDIGIT(*u8data >> 4);
            *wrk++ = GETDIGIT(*u8data & 0x0f);
        }
        *wrk = 0;
    }
    return buff;
}
0___________
  • 60,014
  • 4
  • 34
  • 74