有一种简单的方法可以将数字转换为C中的十六进制ASCII字符吗?

时间:2010-09-09 14:02:04

标签: c embedded ascii hex

我正在为嵌入式设备开发C固件程序。我想通过串口发送一个十六进制字符值数组。有没有一种简单的方法将值转换为ASCII十六进制?

例如,如果数组包含0xFF,我想发送ASCII字符串“FF”,或者对于十六进制值0x3B我想发送“3B”。

这通常是如何完成的?

我已经有了串行发送功能,所以我可以这样做......

char msg[] = "Send this message";
SendString(msg);

并且SendString函数为传递的数组中的每个元素调用此函数:

// This function sends out a single character over the UART
int SendU( int c)
{
    while(U1STAbits.UTXBF);
    U1TXREG = c;
    return c;
}

我正在寻找一个允许我这样做的功能......

char HexArray[5] = {0x4D, 0xFF, 0xE3, 0xAA, 0xC4};
SendHexArray(HexArray);

//Output "4D, FF, E3, AA, C4"

5 个答案:

答案 0 :(得分:17)

使用sprintf将数字写入字符串,然后使用现有的SendString函数通过UART发送该数字。当然,您可以一次执行此一个数字:

char num_str[3];
sprintf( num_str, "%02X", 0xFF );
SendString(num_str);

%02Xprintf函数族的format string,它表示将元素填充为0,直到宽度为2,并将元素格式化为十六进制数。

02部分确保当您要打印0x0F时,您会在输出流中获得0F而非F。如果您使用小写x,则会获得小写字符(例如ff而不是FF)。

答案 1 :(得分:10)

汇编语言时代8位微观的经典技巧是将nybble的转换分为两个部分。值为0到9,值为10到15.然后简单算术保存16字节查找表。

void SendDigit(int c) {
    c &= 0x0f;
    c += (c <= 9) ? '0' : 'A'-10;
    SendU(c);
}

void SendArray(const unsigned char *msg, size_t len) {
    while (len--) {
        unsigned char c = *msg++;
        SendDigit(c>>4);
        SendDigit(c);
    }
}

有几个附注是有序的。首先,这是有效的,因为数字和字母在ASCII中都是连续的跨度。如果你不幸想要EBCDIC,这仍然有效,因为字母'A'到'F'也是连续的(但字母表的其余部分分为三个跨度)。

其次,我改变了SendArray()的签名。我的版本小心地使缓冲区无符号,这通常在计划将字节提升为更大的整数类型以进行算术时更安全。如果它们被签名,那么像nibble[(*msg)>>4]这样的代码可能会尝试在数组中使用负索引,结果将完全无用。

最后,我添加了一个长度参数。对于一般的二进制转储,您可能没有任何有意义的字节值用作结束标记。为此,计数更有效。

编辑修正了一个错误:对于超过10的数字,算术为c + 'A' - 10,而不是c + 'A'。感谢Brooks Moses抓住了它。

答案 2 :(得分:7)

我从数组查找开始。

char *asciihex[] = {
    "00", "01", "02", ..., "0F",
    "10", "11", "12", ..., "1F",
    ...,
    "F0", "F1", "F2", ..., "FF"
};

然后简单地查一查......

SendString(asciihex[val]);

修改

纳入Dysaster的小点思想:

void SendString(const char *msg) {
    static const char nibble[] = {'0', '1', '2', ..., 'F'};
    while (*msg) {
        /* cast to unsigned char before bit operations (thanks RBerteig) */
        SendU(nibble[(((unsigned char)*msg)&0xf0)>>4]); /* mask 4 top bits too, in case CHAR_BIT > 8 */
        SendU(nibble[((unsigned char)*msg)&0x0f]);
        msg++;
    }
}

答案 3 :(得分:2)

sprintf会这样做。

sprintf (dest, "%X", src);

答案 4 :(得分:0)

如果您的编译器支持,您可以使用itoa。否则,我会像在Nathan的&amp;中那样使用sprintf。马克的答案。如果支持itoa并且性能是一个问题,请尝试一些测试以确定哪个更快(过去的经验让我期望itoa更快,但是YMMV)。