我有以下功能:
uint32_t PrintValue(uint32_t *addr_to_dump, uint32 value);
基本上是内存转储的值的内容。现在我有一个包含9个char元素的数组。
uint8_t array_8b[9];
此处收到的值来自二进制文件,其十六进制值为“ACDB5823”,即4字节。我通过UDP消息发送它作为字符串ACDB5823,它是8字节。每个字符1个字节。
在我使用的嵌入式设备中,UART将此值作为uint8_t值接收。我用这些值填充数组。
如何从8字节字符串字符串中取回原始的4字节(以便它适合uint32_t值)? 我确实试过了
strtol(update_word_array, NULL, 16)
将char数组中的第9个值设为'\ 0',但我最终使用PrintValue函数得到ffff ff7f?
现在我使用PrintValue函数在内存转储中获取ACDB5823。
我对这里的转换感到有点困惑。有什么好资源吗?
答案 0 :(得分:-1)
#include <stdio.h>
unsigned char start[16];
unsigned char send[16];
unsigned char recv[16];
unsigned char end[16];
void send_somewhere ( void )
{
unsigned int ra;
for(ra=0;ra<16;ra++) recv[ra]=send[ra];
}
static unsigned char to_hex ( unsigned char x )
{
if(x>9) return(x+0x37);
return(x+0x30);
}
static unsigned char from_hex ( unsigned char x )
{
if(x>0x39) return((x-0x37)&0xF);
return((x-0x30)&0xF);
}
int main ( void )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
unsigned int rd;
start[0]=0xAC;
start[1]=0xDB;
start[2]=0x58;
start[3]=0x23;
for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
rb=0;
for(ra=0;ra<4;ra++)
{
send[rb++]=to_hex((start[ra]>>4)&0xF);
send[rb++]=to_hex((start[ra]>>0)&0xF);
}
for(ra=0;ra<8;ra++) printf("[%02X]",send[ra]); printf("\n");
send[9]=0; printf("%s\n",send);
send_somewhere();
for(ra=0;ra<8;ra++) printf("[%02X]",recv[ra]); printf("\n");
rb=0;
for(ra=0;ra<8;ra+=2)
{
rc=0;
rc=from_hex(recv[ra+0]);
rc<<=4;
rc|=from_hex(recv[ra+1]);
end[rb++]=rc;
}
for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
//if you just need any arbitrary ASCII for some reason even though
//UDP doesnt require it in any way.
rb=0;
for(ra=0;ra<4;ra++)
{
send[rb++]=0x40+((start[ra]>>4)&0xF);
send[rb++]=0x40+((start[ra]>>0)&0xF);
}
for(ra=0;ra<8;ra++) printf("[%02X]",send[ra]); printf("\n");
send[9]=0; printf("%s\n",send);
send_somewhere();
for(ra=0;ra<8;ra++) printf("[%02X]",recv[ra]); printf("\n");
rb=0;
for(ra=0;ra<8;ra+=2)
{
rc=recv[ra+0]&0xF;
rc<<=4;
rc|=recv[ra+1]&0xF;
end[rb++]=rc;
}
for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
return(0);
}
制造
[AC][DB][58][23]
ACDB5823
[ACDB5823]
[ACDB5823]
ACDB5823
[AC][DB][58][23]
或其他方式
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned char start[16];
char send[16];
char recv[16];
unsigned char end[16];
unsigned char temp[16];
void send_somewhere ( void )
{
unsigned int ra;
for(ra=0;ra<8;ra++) recv[ra]=send[ra];
}
int main ( void )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
unsigned int rd;
start[0]=0xAC;
start[1]=0xDB;
start[2]=0x58;
start[3]=0x23;
for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
//endianless and no alignment problems
rc=0;
ra=0;
rc|=start[ra++]; rc<<=8;
rc|=start[ra++]; rc<<=8;
rc|=start[ra++]; rc<<=8;
rc|=start[ra++]; //rc<<=8;
printf("%08X\n",rc);
sprintf(send,"%08X",rc);
printf("[%s]\n",send);
send_somewhere();
recv[9]=0;
printf("[%s]\n",recv);
rc=strtoul(recv,NULL,16);
printf("%08X\n",rc);
//endianless and no alighment problems
ra=4;
end[--ra]=rc&0xFF; rc>>=8;
end[--ra]=rc&0xFF; rc>>=8;
end[--ra]=rc&0xFF; rc>>=8;
end[--ra]=rc&0xFF; //rc>>=8;
for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
//or another way that might use less code, maybe more, but doesnt
//use 32 bit variables.
sprintf(send,"%02X%02X%02X%02X",start[0],start[1],start[2],start[3]);
printf("[%s]\n",send);
send_somewhere();
recv[9]=0;
printf("[%s]\n",recv);
//then choose whatever solution, C library solutions are just so bloated
for(ra=0;ra<8;ra++)
{
temp[ra]=strtoul(&recv[7-ra],NULL,16);
recv[7-ra]=0;
}
for(ra=0;ra<8;ra++) printf("[%02X]",temp[ra]); printf("\n");
for(ra=0;ra<8;ra+=2)
{
rc=temp[7-ra];
rc<<=4;
rc|=temp[6-ra];
end[ra>>1]=rc;
}
for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
return(0);
}
制造
[AC][DB][58][23]
ACDB5823
[ACDB5823]
[ACDB5823]
ACDB5823
[AC][DB][58][23]
[ACDB5823]
[ACDB5823]
[03][02][08][05][0B][0D][0C][0A]
[AC][DB][58][23]
指出,在您尝试实现某些内容并通过UDP发送之前很久,找出如何构建和解析UDP数据包的两端。可以在任何带有编译器的机器上执行此操作,不必是目标嵌入式系统。
调用库函数可能看起来更简单,但是根据资源紧张你的嵌入式系统,你可以通过强制它来节省大量的代码空间和/或执行时间,即使它看起来像是更多的代码行。
像这样做指针游戏
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int *x;
unsigned char start[16];
int main ( void )
{
unsigned int ra;
start[0]=0xAC;
start[1]=0xDB;
start[2]=0x58;
start[3]=0x23;
for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
x=(unsigned int *)&start[0];
printf("%08X\n",x[0]);
return(0);
}
导致endian问题,对齐问题和可移植性问题。基本上它可能最初工作,但随着时间的推移,代码是一个滴答作响的定时炸弹。像这样的习惯最终会咬你,咬一口(主要的代码重写取决于习惯使用的范围和范围)(跨编译域的指向结构更糟)。我建议不要这样做。
如果您尝试理解上面的代码而不是尝试使用它,那就更好了。只不过是基本位操作和ASCII表知识。谷歌ASCII表并查看其中一个图像结果。
转换为ASCII,您可以使用16深度查找表并简化更多内容。可能是最干净的解决方案。在recv端,如图所示,很容易将ASCII转换回半字节,然后组合半字节。八进制在两端都会容易得多,但需要更长的时间。