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

PIC*_*ain 3 c embedded hex ascii

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

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

这通常是怎么做的?

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

char msg[] = "Send this message";
SendString(msg);
Run Code Online (Sandbox Code Playgroud)

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

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

我正在寻找一个可以让我这样做的功能......

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

//Output "4D, FF, E3, AA, C4"
Run Code Online (Sandbox Code Playgroud)

Mar*_*iot 17

使用编号将数字写入字符串sprintf,然后使用现有SendString函数通过UART发送.当然,您可以一次执行以下操作:

char num_str[3];
sprintf( num_str, "%02X", 0xFF );
SendString(num_str);
Run Code Online (Sandbox Code Playgroud)

%02X是一个格式字符串printf函数系列,它说垫以0的元件直到宽度2和格式化元件作为十六进制数.

02部件确保当您想要打印时0x0F,0F而不仅仅是F在输出流中.如果您使用小写字母,x您将获得小写字符(例如,ff而不是FF).

  • 这很好,但检查链接映射,看看你是否仍然有空间在ROM中的其余应用程序,如果这是第一次调用任何庞大的stdio函数系列.即使您现在正在使用它们,请检查您的链接地图,看看更换它们是否可以节省下个月新功能的空间. (3认同)

RBe*_*eig 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


pmg*_*pmg 7

我将从数组查找开始.

char *asciihex[] = {
    "00", "01", "02", ..., "0F",
    "10", "11", "12", ..., "1F",
    ...,
    "F0", "F1", "F2", ..., "FF"
};
Run Code Online (Sandbox Code Playgroud)

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

SendString(asciihex[val]);
Run Code Online (Sandbox Code Playgroud)

编辑

结合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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 或者你可以通过半字节来节省空间.为0-9,af做一个数组,然后进行两次查找:(val >> 4)和(val&0xf).为您节省超过200个字节.:) (5认同)
  • 顺便说一句,如果`char`被签名,那么`(*msg)>> 4`可能是否定的... (2认同)