C -转换u16_array中的结构,其中每个uint16_t仅表示一个字节

jmp7cifd  于 2023-08-03  发布在  其他
关注(0)|答案(3)|浏览(185)

我在texas instruments C2000微控制器上有一个非常糟糕的案例,它只能表示uin16_t而不能表示uint8_t。现在我有了一个类似下面的结构体,其中每个uint16_t只代表一个字节的数据,它将被写入外部EEPROM:

typedef struct
{
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
} MCL_Struct_t;

MCL_Struct_t struc_write = {0};
MCL_Struct_t struc_read = {0};
uint16_t *struc_write_handle = ((uint16_t *)&struc_write);
uint16_t *struc_read_handle = ((uint16_t *)&struc_read);

struc_write.a = 0x11112222;
struc_write.b = 0x11113333;
struc_write.c = 0x11114444;
struc_write.d = 0x11115555;

//call eeprom write
EEPROM_writeTransaction(eepromAddr, struc_write_handle, sizeof(MCL_Struct_t));

//read back eeprom
EEPROM_readTransaction(eepromAddr, sizeof(MCL_Struct_t));

//copy to struc_read
memcpy(struc_read_handle, &SPI_DMA_Handle.pSPIRXDMA->pbuffer[0], sizeof(MCL_Struct_t));

字符串
由于SPI只能按字节传输,uint16_t数据被处理为一个字节,所以我只写了struct_write.a = 0x00110022等。
我如何使我的句柄按字节指向数据?

o0lyfsai

o0lyfsai1#

看起来EEPROM实现似乎是将单个字符视为8字节值,即使系统上的CHAR_BIT显然是16(函数签名很可能直接基于charunsigned char)。
在这种情况下,您不能直接编写整个结构,尽管这样做无论如何都是有问题的,因为可能存在填充字节(通常,不是在具体情况下)和字节顺序问题。因此,我建议显式地序列化,无论您在哪个架构上,您都可以获得定义良好的行为:

void serialize(uint32_t value, char buffer[])
{
// for little endian byte order:
    buffer[0] = value >>  0 & 0xff;
    buffer[1] = value >>  8 & 0xff;
    buffer[2] = value >> 16 & 0xff;
    buffer[3] = value >> 24 & 0xff;
//                       ^^
// revert order of shifts for big endian byte order
}

char* serialize_s(uint32_t value, size_t length, char buffer[])
{
    return length < 4 ? NULL : (serialize(value, buffer), buffer + 4);
}

uint32_t deserialize(char buffer[])
{
    uint32_t value
        = (uint32_t)(buffer[0] & 0xff) <<  0
        | (uint32_t)(buffer[1] & 0xff) <<  8
        | (uint32_t)(buffer[2] & 0xff) << 16
        | (uint32_t)(buffer[3] & 0xff) << 24;
    return value;
}

char* deserialize_s(uint32_t* value, size_t length, char buffer[])
{
    return !value || length < 4
        ? NULL : (*value = deserialize(buffer), buffer + 4);
}

char buffer[16];
serialize(struct_write.a, buffer +  0);
serialize(struct_write.b, buffer +  4);
serialize(struct_write.c, buffer +  8);
serialize(struct_write.d, buffer + 12);

// send buffer
// receive buffer

struct_write.a = deserialize(buffer +  0);
struct_write.b = deserialize(buffer +  4);
struct_write.c = deserialize(buffer +  8);
struct_write.d = deserialize(buffer + 12);

字符串

qojgxg4l

qojgxg4l2#

如果底层架构在物理上不能进行字节寻址,那么您就不太可能在本机进行寻址,尽管您的问题并不清楚情况是否如此。
如果你的微控制器可以按字节处理(据我所知,我相信应该是这样的),它将是一个简单的转换为char类型指针:

char* addr = (char*) &struct_write.a;
char lower_byte = *addr; 
char upper_byte = *(addr + 1);

字符串
否则,您可以使用shift操作来完成,但请记住,这将占用两倍的内存:

uint6_t lower_byte = struct_write.a & (0x00FF);
uint6_t upper_byte = (struct_write.a >> 16)  & (0x00FF);


我建议你进一步研究你的微控制器的架构,并检查指令集架构。

c9x0cxw0

c9x0cxw03#

这里我们有sizeof(char) = sizeof(uint16_t) = sizeof(int) = 1
char是一个字节,但一个字节是2个八位字节。
八位字节上不可能有指针。如果必须发送/接收八位字节,则必须通过转换函数来完成。

typedef union BiOctets {
    uint16_t  u16;    // 2 octets
    unsigned char uc; // also 2 octets
    struct {          // also 2 octets
        unsigned char  high : 8;
        unsigned char  low  : 8;  // cannot take address of low
    //Note: depending en endianess of C2000, may be high and low must be swapped
    };
} BiOctets;

// access to an octet in an array of bytes
unsigned char  BiOctetToOctet( BiOctets bi[], int index ) {
    if ( index & 1 )
        return  bi[index>>1].low;     // odd values is low part
    else
        return  bi[index>>1].high;    // even values is high part
} // notice that returns a byte where high octet is null, it's an octet

// insert an octet in array of bytes
void  OctetToBiOctet( BiOctets bi[], int index, unsigned char value ) {
    if ( index & 1 )
        bi[index>>1].low = value;
    else
        bi[index>>1].high = value;
} // notice that 'value' is supposed to have null high octet, it's an octet

// then these function must be used each time you have to deal with octets

字符串

相关问题