简体   繁体   English

使用位域运算符时的位填充

[英]Bit stuffing when using bitfield operator

My goal is to implement functions to write the signals of a standard CAN frame. 我的目标是实现写入标准CAN帧信号的功能。 A Standard CAN frame contains the following signals: 标准CAN帧包含以下信号:

  • ID: 11 bits ID:11位
  • rtr: 1bit rtr:1位
  • reserved_0: 1bit 预留_0:1位
  • reserved_1: 1bit 保留_1:1bit
  • dlc:4bit DLC:4位
  • data: 8 bytes 数据:8个字节

This is my representation to the CAN frame 这是我对CAN框架的表示

typedef union
{
unsigned char tab[10];
struct
{
    unsigned char id_8_10:3; //ID: bit 8==>10
    unsigned char id_4_7:4; //ID: bit 4==>7
    unsigned char id_0_3:4; //ID: bit 0==>3
    unsigned char rtr:1;
    unsigned char reserved0:1;
    unsigned char reserved1:1;
    unsigned char dlc:4;
    unsigned char tabData[8];
 }bBit;
}tCanFrame;

And the Write functions are the following: 写入功能如下:

void IL_Wr_id_8_10(unsigned char ubVal)
{
 ((tCanFrame*)(&tabFrame))->bBit.id_8_10 = (unsigned int)(ubVal);
}

void IL_Wr_id_4_7(unsigned char ubVal)
{
 ((tCanFrame*)(&tabFrame))->bBit.id_4_7 = (unsigned int)(ubVal);
}

void IL_Wr_id_0_3(unsigned char ubVal)
{
((tCanFrame*)(&tabFrame))->bBit.id_0_3 = (unsigned int)(ubVal);
}

void IL_Wr_rtr(unsigned char ubVal)
{
 ((tCanFrame*)(&tabFrame))->bBit.rtr =(ubVal);
}

void IL_Wr_reserved1(unsigned char ubVal)
{

 ((tCanFrame*)(&tabFrame))->bBit.reserved1 =(ubVal);

}

void IL_Wr_dlc(unsigned char ubVal)
{

 ((tCanFrame*)(&tabFrame))->bBit.dlc =(ubVal);

}

void IL_Wr_data(unsigned char* ubVal)
{

 memcpy(((tCanFrame*)(&tabFrame))->bBit.tabData,ubVal,8);

}

In the main i tried to give values to the signals and to print them, but unfortunately it seems that stuff bits are inserted. 在主要方面,我试图给信号值并打印它们,但不幸的是,似乎插入了填充位。

This is the main: 这是主要的:

int main()
{
 int i;
 IL_Wr_id_8_10(0x7);
 IL_Wr_id_4_7(0x00);
 IL_Wr_id_0_3(0x0F);
 IL_Wr_rtr(0x00);
 IL_Wr_reserved0(0x0);
 IL_Wr_reserved1(0xFF);
 IL_Wr_dlc(0x0F);
 IL_Wr_data(tableauDonnee);

 for (i=0;i<18;i++)
 {
    printf("Byte %i : %s \n",i,byte_to_binary(tabFrame[i]));
 }
 return 0;
}

The result is the following: 结果如下:

Byte 0 : 0000.0111 // the result should be Byte 0 : 1000.0111 
Byte 1 : 0100.1111 // the result should be Byte 1 : 1110.0111
....

What is the problem in your opinion and do you have any idea to solve this problem? 您认为问题出在哪里,您是否有解决此问题的想法?

Your solution is not portable. 您的解决方案不可移植。

You cannot reliably use bitfields for your purpose: the actual layout for the fields in memory is implementation defined and typically depends on the target architecture byte ordering. 您不能可靠地使用位域来实现其目的:内存中字段的实际布局是由实现定义的,并且通常取决于目标体系结构字节顺序。

If the layout happens to be correct with your compiler/architecture combination, are you sure about the actuel bit layout? 如果布局恰好与您的编译器/体系结构组合正确 ,那么您确定Actuel位布局吗? You define 18 bits before the tabData array: at least 6 padding bits will be inserted in order to align tabData on byte boundaries, yielding an 11 byte structure where you seem to assume it is only 10 bytes long. 您在tabData数组之前定义18位:将插入至少6个填充位,以使tabData在字节边界上对齐,从而产生一个11字节的结构,您似乎假设它只有10个字节长。

Your total size of bit field data is 18 bits hence, using 'int' or 'unsigned int' will work correctly to represent your header data. 您的位字段数据的总大小为18位,因此,使用'int'或'unsigned int'将正确表示您的标头数据。

typedef union
{
unsigned char tab[10];
struct
{
    int id_8_10:3; //ID: bit 8==>10
    int id_4_7:4; //ID: bit 4==>7
    int id_0_3:4; //ID: bit 0==>3
    int rtr:1;
    int reserved0:1;
    int reserved1:1;
    int char dlc:4;
    unsigned char tabData[8];
 }bBit;
}tCanFrame;

In case of bit fields, 如果是位字段,

struct
{
    data_type [member_name] : width;
};  

the size of the 'data_type' specified with bit field data member is used as boundary consideration. 由位字段数据成员指定的“ data_type”的大小用作边界注意事项。

In your case, id_8_10 (3 bits), id_4_7 (4 bits) and id_0_3 (4 bits) add up to 11 bits which exceeds 8 bits. 在您的情况下,id_8_10(3位),id_4_7(4位)和id_0_3(4位)加起来等于11位,超过8位。 Hence, id_0_3 (4 bits) are allocated in second byte. 因此,在第二个字节中分配了id_0_3(4位)。 The first byte only contains id_8_10 (3 bits) and id_4_7 (4 bits) = 7 bits + 1 bit unused. 第一个字节仅包含id_8_10(3位)和id_4_7(4位)= 7位+ 1位未使用。

Using 'int' or 'unsigned int' will help. 使用'int'或'unsigned int'将有所帮助。

NOTE::Based on your main(), Byte 1 is expected to be 1110.0111, not 注意::根据您的main(),字节1预计为1110.0111,而不是
Byte 1 : ..... // the result should be Byte 1 : 0010.0111 <-- as indicated by you. 字节1:..... //结果应为字节1:0010.0111 <-如您所指示。

I have opted to implement my own function: 我选择实现自己的功能:

/*function: copy_bits
 description: copy nbBitsToCopy bits from srcAdress to destAdress starting from a specific bit start_bit
 destAdress: destination address
 start_bit:the bit in the destination where to paste data
 srcAdress:source address
 nbBitsToCopy: Number of bit to copy from source
*/
void copy_bits(unsigned char* destAdress , unsigned char start_bit, unsigned char *srcAdress, unsigned char nbBitsToCopy)
{
unsigned int dest_Cursor_Byte;
unsigned int dest_Cursor_Bit;
unsigned int src_Cursor_Byte;
unsigned int src_Cursor_Bit;
unsigned int nbCopiedBits=0;

//Initialisation of cursors
dest_Cursor_Byte=start_bit/8;
dest_Cursor_Bit =start_bit%8;

src_Cursor_Byte=0;
src_Cursor_Bit=0;

while (nbCopiedBits<nbBitsToCopy)
{
    if (CHECK_BIT(srcAdress[src_Cursor_Byte],src_Cursor_Bit,1))
    {
        SET_BIT_VALUE(destAdress[dest_Cursor_Byte],dest_Cursor_Bit,1);
    }

    else
    {
        SET_BIT_VALUE(destAdress[dest_Cursor_Byte],dest_Cursor_Bit,0);
    }
    nbCopiedBits++;
    start_bit++;

    //Update cursors
    dest_Cursor_Byte=start_bit/8;
    dest_Cursor_Bit =start_bit%8;

    src_Cursor_Bit=nbCopiedBits%8;
    src_Cursor_Byte=nbCopiedBits/8;
 }
}

Your Remarks are welcome 欢迎您的评论

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在“位填充”之后区分位 - Discriminate bits after “bit stuffing” 使用带有unsigned char的bitfield时发出警告 - warning when using bitfield with unsigned char 获取位域中唯一位的数量 - Get number of sole bit in bitfield 是否使用联盟内的位域来解决32位`int`的定义明确的行为? - Is it well-defined behavior to address a 32-bit `int` using a bitfield inside a union? 原因:#1546-D:(ULP 15.1)检测到连续位域分配。 建议改用位掩码 - Reason for: #1546-D: (ULP 15.1) Detected consecutive bitfield assigns. Recommend using bit mask instead 位域联合便于位访问,意外行为 - Bitfield union for easy bit access, unexpected behavior 当底层位域类型在C中不是int时,lvalue.bitfield的类型 - Type of lvalue.bitfield when the underlying bitfield type is not int in C 在针对 64 位变量的文字 integer 上使用 NOT (~) 运算符时是否需要类型转换 - Is type casting needed when using NOT (~) operator on a literal integer against a 64bit variable 使用bitfield union替换位掩码时,是访问非活动成员,还是未定义? - When using bitfield union to replace bitmask, is accessing inactive member, okay or undefined? 将布尔数组的最后一个元素设置为位域中的最高位 - Set Last Element of boolean array to as Most Significant Bit within an Bitfield
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM