2016-02-10 2 views
0

Je suis à la recherche dans un fichier pilote de microcontrôleur et avait du mal à comprendre l'utilisation correcte des syndicats et les champs de bitsS'il vous plaît clarifier ma compréhension sur les champs de bits et des syndicats en C

typedef union 
{ 
    uint8 U;       //Unsigned 
    sint8 I;       //signed 
    Register_x_Bits B;    //Bit field access 
}u1; 

typedef struct _Register_x_Bits  //8 bit register size 
{ 
    uint8 Field1:1;     //endianness is maintained for all registers  
    uint8 Field2:1;     
    uint8 Field3:1;      
    uint8 Field4:1;     
    uint8 Field5:4;  
}Register_x_Bits; 


u1 reg; 

reg.U = ReadRegister();     // data is initially being read from the register 

//based on the previous data a bit value needs to be changed in particular location of the data 

reg.B.Field3 = 0; 

WriteRegister(reg.U); 

Et voici où j'ai du mal à comprendre

1) en changeant simplement la valeur du champ de bits reg.B.Field3, serait-il changer un seul bit particulier (champ 3 dans ce cas) ou faut-il effacer toutes les données précédentes dans le registre et le remplir avec de nouveaux reg.B.Field3

De nombreux didacticiels indiquent qu'il n'y aurait qu'un seul membre actif dans Unions

2) Puis-je modifier plusieurs champs binaires dans le même registre? Puis-je les changer par la même méthode ci-dessus et en gardant intact restant

reg.B.Field1 =0; 
reg.B.Field3 =1; 
reg.B.Field4 =1100; 

Edits enter image description here

Que toute la valeur de registre pour être 1111 0 1 0 1 et maintenant si je change Fields 1,3,4 serait-il affecter la valeur dans Fields 0,2?

+0

Vous devez définir 'Register_x_Bits' avant de l'utiliser dans une définition de l'union. Le code affiché ne doit pas être compilé. (Mais vous pouvez facilement inverser l'ordre de l'union et de la structure pour qu'elle compile.) –

+0

Vous ne pouvez pas insérer tout le décimal 1100 dans un champ de 4 bits. Aviez-vous en tête 6 la valeur? (1100% 16 est 12, ce que vous obtiendriez avec le code tel qu'il est écrit.) –

+0

Affecter à 'reg.B.Field3' ne changerait pas les autres bits de la structure' reg.B'. Cela affecterait les valeurs de 'reg.I' et' reg.U' - en pratique, un bit serait réinitialisé, mais quel bit est défini par l'implémentation (la plupart du comportement du champ de bits est défini par l'implémentation, donc vous devez regarder le le manuel de mise en œuvre - et demandez l'information si elle n'est pas déjà documentée dans les manuels que vous avez). –

Répondre

1

Bon d'abord vérifier le code ci-dessous

#include <stdio.h> 
typedef struct _BITS{ 
    unsigned char f1:1; 
    unsigned char f2:1; 
    unsigned char f3:1; 
    unsigned char f4:1; 
    unsigned char f5:4; 

}BITS; 
typedef union { 
    unsigned char a; 
    char b; 
    BITS c; 
}u1; 

int main(void) { 
    u1 reg; 
    reg.a = 255; 
    reg.c.f1 = 0; 
    //reg.c.f2 = 1; 
    printf("%d", reg.c.f1); 
    printf("%d", reg.c.f2); 
    return 0; 
} 

Pour mimer ReadRegister(), je l'ai écrit reg.a = 255. Alors maintenant, quand j'écris reg.c.f1 = 0 et s'il changeait tous les bits alors reg.c.f2 affichera 0 aussi. Mais ça n'arrive pas. Bitfield sont uniquement ciblés pour ce bit particulier, pas l'octet entier. Par conséquent Non, ce ne serait clair que le bit

Maintenant, si j'écris reg.a = 0 et reg.c.f1 = 255 et si elle se couchait tous les bits alors reg.c.f2 rapporterait 1, mais il ne sera pas. Par conséquent Non, vous ne pouvez pas régler tous les bits du champ de bits

Modifier Cependant, vous pouvez définir plusieurs bits dans la réponse de l'autre ways..See @ Sdao

Espoir qui répond à votre question

+0

J'ai ajouté une description de bit de registres dans ma question .. et si j'ai 'reg.a = 255' alors change'reg.c.f1 = 0' et' reg.c.f4 = 0' Mon «reg.a» changerait-il en «11110110» –

+0

Vous devez récapituler à nouveau le concept de «unions». Ici 2 points.1. Si vous changez le bit, l'autre bit ne changera pas. Si vous modifiez un bit à l'aide de bitfield, la valeur entière de l'octet est affectée. Parce que 1. Chaque bit est distinct des autres et 2. dans la mémoire 'union' est partagée et ici une seule variable est créée et partagée. Les changements faits par l'un seront reflétés dans l'autre. –

+0

S'il vous plaît sélectionner ma réponse si vous le trouvez utile. –

0

1: Vous pouvez modifier un champ individuellement sans affecter les autres
2: Vous pouvez modifier plusieurs champs en même temps.

Pour votre information: dans votre cas, la valeur peut être réglée sur chaque champ est [0: sizeof(unsigned char)] mais la valeur réelle que chaque champ peut recevoir dépend du nombre de bits, il est, donc soyez prudent

Supposons que vous avez N bits (s) champ, vous affectez M à ce champ puis la valeur réelle qui sera définie est: (M & (N^2 - 1))(N^2 - 1) est le masque.

Ex:

reg.B.Field1 = 10; // actual value: reg.B.Field1 = 0 (because 10 = b'0000 1010, Field1 is 1 bit field then the mask is `1^2 - 1 = 1 (b'1)`), 10 & 1 = 0) 
reg.B.Field3 = 7; // actual value: reg.B.Field3 = 1 (because 7 = b'0000 0111, Field3 is 1 bit field then the mask is `1^2 - 1 = 1 (b'1)`, 7 & 1 = 1) 
reg.B.Field4 = 24; // actual value: reg.B.Field4 = 8 (because 24 = b'0001 1000, Field4 is 4 bits field then the mask is `4^2 - 1 = 15 (b'1111)`, 24 & 15 = 8)