我正在为嵌入式设备开发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"
答案 0 :(得分:17)
使用sprintf
将数字写入字符串,然后使用现有的SendString
函数通过UART发送该数字。当然,您可以一次执行此一个数字:
char num_str[3];
sprintf( num_str, "%02X", 0xFF );
SendString(num_str);
%02X
是printf
函数族的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)。