[英]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帧包含以下信号:
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.