【问题标题】:Data received from BLE unable to convert from hex to string (Nordic)从 BLE 接收的数据无法从十六进制转换为字符串(北欧)
【发布时间】:2017-11-05 04:39:36
【问题描述】:

在 ble_app_template 的 on_ble_evt(ble_evt_t*) 函数中,我添加了“BLE_GATTS_EVT_WRITE”的案例。其中有以下代码:

    case BLE_GATTS_EVT_WRITE:
    { 
        ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        SEGGER_RTT_printf(0, "Length = %d \n", p_evt_write->len);
        int n;
        char* buf2 = "";    
        char* buf3 = "";    
        count += p_evt_write->len;
        for(n=0; n<p_evt_write->len; n++)
        {
                   SEGGER_RTT_printf(0, "Received[%d] : %X \n", n, p_evt_write->data[n]);
                   SEGGER_RTT_printf(0, "Received[%d] : %d \n", n, p_evt_write->data[n]);
                   if(n>0){                                                     
                       sprintf(buf2, "%s", ((char*)p_evt_write->data[n]));    
                       strcat(buf3, buf2);
                   }                                                    
                   else{                                                
                       sprintf(buf2, "%s", ((char*)p_evt_write->data[n]));   
                       strcpy(buf3, buf2);
                   }
                   SEGGER_RTT_printf(0, "buf2 string: %s \n", buf2);
                   SEGGER_RTT_printf(0, "buf2 hex: %X \n", buf2[0]);
                   SEGGER_RTT_printf(0, "buf3 in string: %s \n", buf3);
                   SEGGER_RTT_printf(0, "count: %d \n", count);
        }
   }

我从存储在 p_evt_write->data[n] 中的 BLE 接收十六进制值。我想将所有这些接收到的十六进制值连接成一个字符串,将其存储在“buf2”中。

但是,我在 sprintf 行收到错误。当我在 sprintf 中输入“%X”时,这些值不会转换为字符串,因为 buf2/buf3 字符串不会打印任何内容。当前代码

sprintf(buf2, "%s", ((char*)p_evt_write->data[n]));

返回错误“错误:从不同大小的整数转换为指针 [-Werror=int-to-pointer-cast]”。如果我删除了 (char*) 类型转换,它会返回错误“错误:格式“%s”需要“char *”类型的参数。

我看到 p_evt_write->data[n] 其中 data 被声明为

uint8_t                     data[1];

我目前正在使用 Nordic 的 nRF51DK 与 Eclipse IDE 和 SEGGER RTT JLink 进行调试。所有打印都打印到 SEGGER RTT。 (printf不行,用SEGGER_RTT_printf代替打印)

如何成功地将所有十六进制值连接在一起形成一个字符串?谢谢。

【问题讨论】:

    标签: c string hex bluetooth-lowenergy nrf51


    【解决方案1】:

    要追加到缓冲区,您可以使用以下内容:

    size_t total_len = 0;
    uint8_t buf = NULL;
    
    while (receive()) {
        size_t len = p_evt_write->len;
        buf = realloc(buf, total_len + len);
        memcpy(buf + total_len, p_evt_write->data, len);
        total_len += len;
    }
    

    要将uint8_t 的数组转换为以 NUL 结尾的字符串,请分配足够的空间,复制字节并附加 NUL。

    char* s = malloc(total_len + 1);
    memcpy(s, buf, total_len);
    s[total_len] = 0;
    

    当然,如果 buf 的任何元素是 NUL (0),您将看到一个截断的字符串。没有办法解决这个问题(不摆脱 NUL)。


    请注意,-&gt;data 不包含“十六进制值”。十六进制是数字的文本表示。你没有十六进制;你有数字。这很好,因为这意味着不需要转换。您只需要复制字节并添加 NUL。

    请注意,您遇到的具体错误是因为您将uint8_t(一个数字)转换为char*(一个指针)。这是没有意义的。您可能会选择(char*)(&amp;(p_evt_write-&gt;data[n])),但这也行不通,因为%s 不只是期望一个指向字符的指针,而是指向以 NUL 字符结尾的序列的第一个字符的指针。

    【讨论】:

    • 您好,BLE 一次只能发送 20 个字节,但我发送的数据超过 20 个字节。如何将所有接收到的数据连接在一起?从您的代码中, buf2 将仅存储它接收到的当前 20 个字节。我创建了一个新变量 'char* buf3 = ""; ' 将所有接收到的字节存储在 'strcat(buf3, buf2);' 中。但是,当我打印 buf3 字符串时,那里什么都没有。
    • 这很有用。还有一个问题,当我打印 buf 字符串时,它似乎最多打印 429 个字符。但是total_len显示它是708,这意味着总共有708个字符,但buf字符串只有429个。malloc的大小有限制吗?还是有其他原因?我需要将所有字符都放在一个字符串中。谢谢。
    • 答案已经涵盖了。 "当然,如果 buf 的任何元素是 NUL (0),您将看到一个截断的字符串。没有办法解决这个问题(不去掉 NUL)。 " 如果您的数据可以包含 NUL,那么将您的数据转换为字符串是没有意义的,所以不要这样做!
    • 但截至字符 430 为止,数据不包含任何 NULL 值。NULL 仅位于数据末尾 700+ 个字符处。
    • 你的意思是如果数据包含一个字符'0'(零),它被认为是NULL?因为我的数据中确实包含零,并且即使其中包含 0,字符串也能够连接数据,直到 429 个字符突然停止并且随后不再连接。但是字符 428-430 都不是零。
    【解决方案2】:

    假设您想要获取您收到的数据的十六进制表示形式的字符串,请尝试这样的操作...

        ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        char* buf2 = malloc((p_evt_write->len * 2) + 1);
        memset(buf2, 0, (p_evt_write->len * 2) + 1);
        for(int n=0; n<p_evt_write->len; n++)
        {
            char buf3[10];
            sprintf(buf3, "%02X", (unsigned int)p_evt_write->data[n]);
            strcat(buf2, buf3);
        }
        SEGGER_RTT_printf(0, "buf2 string: %s \n", buf2);
        free(buf2);
    

    【讨论】:

    • 为什么是buf3[5]?它比uint8_t 支持的范围大(对于unsigned int 支持的范围太小)。
    • 深夜随机值选择为至少 3 的两个字符和一个 NULL,加上一些填充以防我忘记了一些边缘情况。 :-)
    猜你喜欢
    • 2010-10-18
    • 2012-09-16
    • 1970-01-01
    • 2019-04-26
    • 2017-05-30
    • 2018-09-14
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多