2015-10-26 7 views
2

Моя цель - реализовать функции для записи сигналов стандартной кадры CAN. Стандарт может кадр содержит следующие сигналы:Бит-начинка при использовании оператора битового поля

  • ID: 11 битых
  • RTR: 1bit
  • reserved_0: 1bit
  • reserved_1: 1bit
  • АП: 4bit
  • данных: 8 байт

Это мое представление к кадру 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; 

И прописывать функции являются следующим:

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); 

} 

В главном я попытался дать значение сигналов и печатать их, но, к сожалению, кажется, что вещи биты вставляются.

Это главное:

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; 
} 

В результате получается следующее:

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

чем проблема, по вашему мнению, и у вас есть какие-либо идеи, чтобы решить эту проблему?

+0

Используйте «пакет» прагму вашего компилятора и убедитесь, что битовые добавить до кратен 8, по крайней мере, и предпочтительно 32 или 64. –

ответ

0

Ваше решение не переносится.

Вы не можете надежно использовать битовые поля для своей цели: фактический макет для полей в памяти определяется реализацией и обычно зависит от упорядочения байтов целевой архитектуры.

Если макет правильный с вашей комбинацией компилятора/архитектуры, вы уверены в расположении битов в действии? Вы определяете 18 бит перед массивом tabData: для выравнивания tabData должно быть установлено не менее 6 битов заполнения, что дает структуру длиной в 11 байт, где, по-видимому, предполагается, что она составляет всего 10 байт.

0

Ваш общий размер данных битового поля составляет 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; 

В случае битовых полей,

struct 
{ 
    data_type [member_name] : width; 
}; 

размера «тип_данного» заданы с элементом данных битового поля используются в качестве граничного рассмотрения.

В вашем случае id_8_10 (3 бита), id_4_7 (4 бита) и id_0_3 (4 бита) содержат до 11 бит, которые превышают 8 бит. Следовательно, id_0_3 (4 бита) выделяются во втором байте. Первый байт содержит только id_8_10 (3 бита) и id_4_7 (4 бит) = 7 бит + 1 бит не используется.

Использование 'int' или 'unsigned int' поможет.

Примечание :: На основании вашей основной(), Byte 1, как ожидается, будет 1110,0111, не
Байт 1: ..... // результат должен быть Байт 1: 0010,0111 < - как указано Вами ,

+0

Да, вы правы. Байт 1 должен быть 1110.0111. Ваше решение кажется хорошим решением, я попробую. – fedi

+0

Это решение не будет работать, потому что если мы используем unsigned int header [2]: 18 для заголовка, как вы упомянули, у нас будет 32-18 = 14-разрядная начинка (при условии, что int - 16 бит), чего не ожидается. – fedi

+0

Согласен. На самом деле, метод битового поля полезен при сериализации/дезасериализации данных заголовка только тогда, когда общий размер битового поля является целым кратным разумно выбранного типа данных. В противном случае, общий способ маскировки и сдвига полезен для сериализации/де-сериализации данных заголовка. – cm161

0

я решил реализовать свою собственную функцию:

/*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; 
} 
} 

Ваши замечания приветствуются