begin process at 2008 09 06 19:30:44
1 237 931 membres
313 nouveaux aujourd'hui
14 314 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

OBTENIR L'ETAT DES BITS QUI COMPOSENT UN OCTET (CONVERSION XX->BINAIRE)


Information sur la source

Catégorie :Astuces Classé sous : bin, binaire, convertir, convertion, union Niveau : Débutant Date de création : 14/12/2005 Vu : 8 026

Note :
7,5 / 10 - par 2 personnes
7,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (21)
Ajouter un commentaire et/ou une note

Description

J'ai regardé très rapidement si la source n'existait pas et je ne l'ai pas trouvé.
Je précise que c'est une astuce que je viens d'apprendre en cours.
En utilisant "Les champs de bits" et une union, nous pouvons très simplement obtenir l'état des bits qui composent un octet... mais pourquoi pas un int en modifiant un peu le code.
Les champs de bits :
   Pour se qui ne connaisse pas, ils permettent de limiter la place occupé en mémoire d'une variable si tous ces bits ne sont pas utilisés.
   Pour représenter cela il suffit de mettre après le nom de la variable :nombre_bit
   Par exemple, int état:1;   //ici l'int ne fera pas 32bits mais qu'un seul, les valeurs max et min de etat seront donc -1 ou 0
union
   A la différence d'un struct, les éléments contenus dans une union sont contenu au même emplacement mémoire
   (La structure les met à la suite dans la mémoire)
   Je me doute que se n'ai pas très clair un exemple:
   struct _test{
       int a;
       unsigned char b;
   }
   Ici la structure occupera 5octets en mémoire (sizeof(int)=4octets et sizeof(char)=1octet)

   union _test2{
       int a;
       unsigned char b;
   }test2;
   Ici sizeof(test2)=4octet
   si
   test2.a=0xFDE8;     //valeur prise au hasard
   Alors
   b=0xE8;

Schéma de la mémoire:

  structure                 union
|-----------|           |-----------|
|           |           |           |
|     a     |           |   a et b  |
|           |           |           |
|-----------|           |-----------|
|     b     |
|-----------|

J’espère que c'est clair.
Revenons au but...créer une union entre un caractère et une structure et lire la structure pour avoir l'état des bits, regardez le code.

Les champs de bits ne sont pas toujours obligatoires.
Autre utilisation de l'union :
#include <stdio.h>

union _ip{
unsigned char membres[4]; //Les 4 membres qui compose une adresse IP
unsigned int adIp; //L'adresse IP au complet
}ip;

main()
{
printf("saisir une adresse ip en hexa :");
scanf("%x",&ip.adIp); //Saisie en hexa de l'adresse ip au complet

printf("l'adresse ip est : %03d.%03d.%03d.%03d\n"
,ip.membres[3],ip.membres[2],ip.membres[1],ip.membres[0]); //Attention a l'ordre,il est inversé
}

Source

  • #include <stdio.h>
  • typedef unsigned char uchar; //evite de récrire le tout
  • /*Ma structure qui contiendra l'etat de chacun des bit qui compose un char*/
  • typedef struct{
  • uchar b0:1; //Poid faible
  • uchar b1:1;
  • uchar b2:1;
  • uchar b3:1;
  • uchar b4:1;
  • uchar b5:1;
  • uchar b6:1;
  • uchar b7:1; //Poid fort
  • }octet;
  • /*Mon union qui me permet de superposer les variable 'valeur' et 'etat'*/
  • union _mot{
  • char valeur;
  • octet etat;
  • }mot;
  • /*Mon main qui me permet de tester*/
  • main()
  • {
  • printf("saisir une valeur (de -128 a +127):"); //Valeur max d'un char signé
  • scanf("%d",&mot.valeur);
  • printf("sizeof(octet) = %d\n",sizeof(octet)); //Montre l'interait des champ de bits 1 octet au lieu de 8
  • printf("sizeof(mot) = %d\n",sizeof(mot)); //Montre que l'union superpose bien les deux variables et ne les met pas à la suite
  • printf("Etat b0: %d\n",mot.etat.b0);
  • printf("Etat b1: %d\n",mot.etat.b1);
  • printf("Etat b2: %d\n",mot.etat.b2);
  • printf("Etat b3: %d\n",mot.etat.b3);
  • printf("Etat b4: %d\n",mot.etat.b4);
  • printf("Etat b5: %d\n",mot.etat.b5);
  • printf("Etat b6: %d\n",mot.etat.b6);
  • printf("Etat b7: %d\n",mot.etat.b7);
  • }
#include <stdio.h>

typedef unsigned char uchar;	//evite de récrire le tout

/*Ma structure qui contiendra l'etat de chacun des bit qui compose un char*/
typedef struct{
	uchar b0:1;		//Poid faible
	uchar b1:1;
	uchar b2:1;
	uchar b3:1;
	uchar b4:1;
	uchar b5:1;
	uchar b6:1;
	uchar b7:1;		//Poid fort
}octet;

/*Mon union qui me permet de superposer les variable 'valeur' et 'etat'*/
union _mot{
	char valeur;
	octet etat;
}mot;

/*Mon main qui me permet de tester*/
main()
{
	printf("saisir une valeur (de -128 a +127):");   //Valeur max d'un char signé
	scanf("%d",&mot.valeur);

	printf("sizeof(octet) = %d\n",sizeof(octet));    //Montre l'interait des champ de bits 1 octet au lieu de 8
	printf("sizeof(mot) = %d\n",sizeof(mot));        //Montre que l'union superpose bien les deux variables et ne les met pas à la suite

	printf("Etat b0: %d\n",mot.etat.b0);
	printf("Etat b1: %d\n",mot.etat.b1);
	printf("Etat b2: %d\n",mot.etat.b2);
	printf("Etat b3: %d\n",mot.etat.b3);
	printf("Etat b4: %d\n",mot.etat.b4);
	printf("Etat b5: %d\n",mot.etat.b5);
	printf("Etat b6: %d\n",mot.etat.b6);
	printf("Etat b7: %d\n",mot.etat.b7);
}
  • signaler à un administrateur
    Commentaire de TanKu le 14/12/2005 23:52:48

    Désolé pour le schéma de la mémoire je voulais que sa donne cela :

      structure.......union
    |-----------| |-----------|
    |...........| |...........|
    |.....a.....| |...a et b..|
    |...........| |...........|
    |-----------| |-----------|
    |.....b.....|
    |-----------|
    (j'ignore se que sa va donné....)

  • signaler à un administrateur
    Commentaire de ymca2003 le 15/12/2005 11:20:40

    Pour information, autre source en relation :
    http://www.cppfrance.com/code.aspx?ID=10065

  • signaler à un administrateur
    Commentaire de BruNews le 15/12/2005 11:44:28 administrateur CS

    Les bases du langage C sont à considérer comme acquises.
    struct, union etc... se trouvent dans les 1ers chapitres de tout bouquin correct.

  • signaler à un administrateur
    Commentaire de neria le 15/12/2005 13:11:23

    Pour obtenir l'état des bits, on peux aussi faire un masque. Par exemple pour obtenir l'état du bit 3 (en partant de la droite) il faut faire :
        variable & 4    
    Car 4 en binaire c'est 00000100b

    @+

  • signaler à un administrateur
    Commentaire de BruNews le 15/12/2005 13:18:46 administrateur CS

    C'est dans tous les cas ce que le compilo mettra en code, il n'y a aucun autre moyen car la plus petite entité adressable est l'octet, le bit est seulement manipulable.

  • signaler à un administrateur
    Commentaire de zeratul67 le 15/12/2005 20:40:57

    Une utilisation intéressante, lorsque vous ne maitrisez pas l'octet dont vous voulez manipuler les bits (que vous ne pouvez pas directement le déclarer comme étant un union):

    typedef struct
    {
    unsigned char bit0 : 1,
    bit1 : 1,
    bit2 : 1,
    bit3 : 1,
    bit4 : 1,
    bit5 : 1,
    bit6 : 1,
    bit7 : 1;
    } bit_field;

    #define Bit(octet) (*(volatile bit_field *) (&(octet)))

    SOURCE : http://anyedit.free.fr/

  • signaler à un administrateur
    Commentaire de CyberP le 19/12/2005 08:12:19

    pourquoi faire simple quand on peut faire compliqué hein ?
    personnelement j'ai beaucoup plus simple :

    int main() {
      unsigned char valeur;
      printf("saisir une valeur (de -128 à +127):");
      scanf("%d", &valeur);

      printf("Etat b0: %d\n", (valeur & 1) ? 1 : 0);
      printf("Etat b1: %d\n", (valeur & 2) ? 1 : 0);
      printf("Etat b2: %d\n", (valeur & 4) ? 1 : 0);
      printf("Etat b3: %d\n", (valeur & 8) ? 1 : 0);
      printf("Etat b4: %d\n", (valeur & 16) ? 1 : 0);
      printf("Etat b5: %d\n", (valeur & 32) ? 1 : 0);
      printf("Etat b6: %d\n", (valeur & 64) ? 1 : 0);
      printf("Etat b7: %d\n", (valeur & 128) ? 1 : 0);

      return 0;
    }

    comme tu expliques les struct et les unions, je vais aussi expliquer ce que je fais :

    c'est comme ce que dit neria plus haut (sauf qu'il s'agit du bit numéro 2, dans toutes les docs techniques tu trouveras que le premier bit est le numéro 0)
    si la valeur est 52 par exemple (ce qui fait 110100 en binaire)
    on fait par exemple 52 & 16 :
    00110100
    00010000  // ça c'est 16
    00010000  // ça c'est le résultat
    en effet, le & met un 1 là où les bits des deux nombres (des deux opérandes) sont tous les deux égaux à 1 et de même poids (au même rang), sinon il met 0

    donc 52 & 16 donne 16
    en fait le résultat ne peut être que 16 ou 0 (si on y réfléchit un peu), c'est-à-dire que si le résultat du & est 16, le bit numéro 4 (le bit le plus à droite est le numéro 0) sera égal à 1, sinon à 0
    donc je fais tout simplement (52 & 16) ? 1 : 0  ce qui fait que si 52 & 16 vaut 0, le résultat final sera 0, sinon le résultat final sera 1

    on pourrait aussi faire des décalages de bits pour ramener la valeur à 1
    ou même diviser par 16 tout simplement (un 0 donnerait toujours 0 et un 16 donnerait 1)
    le plus rapide reste le décalage de bits :
    (52 & 16) >> 4

  • signaler à un administrateur
    Commentaire de Arnaud16022 le 19/12/2005 12:20:23

    perso ce que je fais c'est de shifter le registre vers la droite jusqu'a ce que le bit qui m'intéresse soit de poids faible et en 2 masques c'est réglé

    char ORmask =(char)0xFE;
    char ANDmask=(char)0x01;
    bit=((octet>>num_bit|ORmask)&ANDmask;

  • signaler à un administrateur
    Commentaire de CyberP le 19/12/2005 16:45:11

    euh d'après moi ça fonctionne pas ce truc
    n'importe quel nombre où tu fais "or 0xFE" suivi de "and 0x01" sera nul parce que le or met le premier bit à 0 et le and ne garde que le premier bit
    (maintenant faudrait voir l'ordre de priorité des opérateurs, peut être que le or s'exécute avant le décalage de bits et là ça donnerait un truc encore plus buggé)

    il suffit de supprimer le or
    bit = (octet >> num) & 1

  • signaler à un administrateur
    Commentaire de VinceVG le 08/05/2006 17:07:03

    pourquoi faire simple quand on peut faire compliqué hein ?
    personnelement j'ai beaucoup plus simple :

    int main() {
      unsigned char valeur;
      printf("saisir une valeur (de -128 à +127):");
      scanf("%d", &valeur);

      printf("Etat b0: %d\n", (valeur & 1) ? 1 : 0);
      printf("Etat b1: %d\n", (valeur & 2) ? 1 : 0);
      printf("Etat b2: %d\n", (valeur & 4) ? 1 : 0);
      printf("Etat b3: %d\n", (valeur & 8) ? 1 : 0);
      printf("Etat b4: %d\n", (valeur & 16) ? 1 : 0);
      printf("Etat b5: %d\n", (valeur & 32) ? 1 : 0);
      printf("Etat b6: %d\n", (valeur & 64) ? 1 : 0);
      printf("Etat b7: %d\n", (valeur & 128) ? 1 : 0);

      return 0;
    }


    Je n'appel pas ça plus simple. En plus le code qu'a rapporté Zeratul est destiné à la programmation sur des µC, il est donc simple et Zen (je veux dire peux couteux en ressources). Il permet l'accés au bit des ports et registre quand le compilateur ne le permet pas.

  • signaler à un administrateur
    Commentaire de zeratul67 le 08/05/2006 18:00:08

    Pour information, j'ai fais quelques tests de compilation avec Visual Studio (VC++.NET 2003 v7.1.3088)

    Le grand classique avec masque : bit = variable & 8;
    donne en code machine :
    mov         eax,dword ptr [variable]
    and         eax,8
    mov         dword ptr [bit],eax

    Ma solution, qui est plus lisible dans le code source : bit = Bit(variable).bit3;
    mov         al,byte ptr [variable]
    shr         al,3
    and         al,1
    movzx       ecx,al
    mov         dword ptr [bit],ecx

    Le code résultant est plus volumineux, et ce sans raison que je comprenne. Conclusion : il vaut mieux utiliser un masque :(

    (en écriture de bit, les deux codes "Bit(variable).bit3 = 1;" et "variable |= 8;" donnent e même code machine, ce qui est bien plus logique).

    Je vous encourage à tester avec d'autres compilos ... (j'ai actuellement un soucis avec mon GCC, si j'y pense je vous communiquerai les résultats)

  • signaler à un administrateur
    Commentaire de VinceVG le 09/05/2006 10:07:15

    Voilà une intéressante démarche.

  • signaler à un administrateur
    Commentaire de Melodie_Nelson le 11/05/2006 11:37:35

    bonjour,
    je dois commander un LCD en parallèle à partir d'un LPC. il y'a donc 8 bits de Data à gérer ainsi que 3 bits d'instructions.
    et donc je commande mon paramètre Data en hexa, ke je dois donc ensuite transformer pour avoir l'état de mes 8 bits. si j'ai compris le truc, est-ce que c'est corect comme ça ?


    void  data (void) //transformer une valeur hexa en 8 bits pour DO à D7

    {
    typedef struct
    {
    unsigned char   LCD0 : 1,
    LCD1 : 1,
    LCD2 : 1,
    LCD3 : 1,
    LCD4 : 1,
    LCD5 : 1,
    LCD6 : 1,
    LCD7 : 1;
    } LCD_bit;

    #define Bit(octet) (*(volatile LCD_bit *) (&(octet)))


    }

    donc si j'ai compris ça doit être ça. et donc "octet" est ma variable data ?
    bon je suis assez septik en fait, j'ai peur de rien comprendre

  • signaler à un administrateur
    Commentaire de VinceVG le 12/05/2006 15:09:09

    Oui

  • signaler à un administrateur
    Commentaire de Melodie_Nelson le 15/05/2006 10:19:04

    A Oui ?  

    Mais oui quoi ?

  • signaler à un administrateur
    Commentaire de VinceVG le 15/05/2006 10:36:42

    est-ce que c'est corect comme ça ?

    oui

  • signaler à un administrateur
    Commentaire de Melodie_Nelson le 15/05/2006 15:31:56

    bien, merci mais je pense faire autrement finalement

    sinon j'ai une autre question, qui n'a rien à voir certes.

    c'est pour obtenir le nombre de caractère d'un mot. sachant que je n'ai pas les librairies telle stdio ou string.

    est-ce correct comme ça ??

    [code]
    int n=0;
    while(word[n]!=0)
    n++ ;  //n est donc le nombre de caractère de word
    [/code]

  • signaler à un administrateur
    Commentaire de BruNews le 15/05/2006 15:38:45 administrateur CS

    Va bon.

  • signaler à un administrateur
    Commentaire de Melodie_Nelson le 15/05/2006 16:00:33

    Merci.
    Pfffou, j'en chie.
    Tant qu'on y est j'ai une autre question ( enfin j'en ai des millions mais bon ).
    Euh, comment dire, donc je commande mon LCD à partir d'un LPC2138. Et je ne sais pas comment assigner mes 8 bits de data du LCD. Je vais les commander en hexa.
    Par ex : lcd_data(0x38)
    donc ensuite ma procédure lcd_data(infodata) doit transformer ce code hexa pour assigner les 8 bits.
    J'ai un peu du mal à expliquer parce que je ne comprends pas le problème.
    Voici en gros mon programme :

    union IO_PORT
    {
    u16 W;
    u32 DW;
    struct
    {
    u08 LSB;
    u08 MLSB;
    u08 MMSB;
    u08 MSB;
    } B2DW;
    //etc

    //l'afficheur est câblé sur les ports P0.16 à 23, ce qui correspond à B2DW.MMSB

    //et on trouve aussi ça dans le fichier LPC_io.h :
    #define IDE_PORT_L IO_IO1PIN->B2DW.MMSB


    //ensuite :

    void  init_aff(void)  /*faire l'init de l'afficheur*/
    {
    int i,j=0 ;
    for(i=0;i<3;i++)
    {
    lcd_data(0x38);
    delay(20000);
    }

    lcd_data (0x0C) ;
    delay(20000);

    //etc
    }

    void  lcd_data (char infodata)
    {

    IO0CLR = LCD_RS ; //mode instruction du LCD
    IO0CLR = LCD_RW ; //mode écriture du LCD

    IO0DIR = 0xFEFFB705; //  D0 à D7 en sortie

    IDE_PORT_L = infodata ;
    enable(80);  // validation pendant tant de ns
    }

    Où est le problème ? Pourquoi ça ne marche pas ?
    C'est peut-être un problème  au niveau du lcd, je respecte peut-ête mal les procédures d'envoie de données. Voici sa doc http://www.spezial.de/doc/cctech/cmc216-01.pdf
    Enfin je pense que c'est ma définition IDE_PORT_L qui n'est pas bonne.

  • signaler à un administrateur
    Commentaire de VinceVG le 16/05/2006 11:39:20

    On en chie tous le c est un anti language. Il doit rester réservé à des élus. On passe tellement de temps à apprendre à l'utiliser qu'aprés... une fois qu'on est dans le clan on refuse les autres outils avec dédain. je te dis ça j'ai commencer à programmer en hexa (et oui) puis en assembleur puis en basic (le vieu truc pourris) puis en gw basic. Et d'un coup j'ai commencé à respirer avec le pascal en enfin visual basic. Maintenant je suis punis et doit rétrograder au c.

    Pour ton pb : si tu envoies le mot (qqs sa base) sur le port, ça devrait marcher  sans pb. Ton compilateur s'en charge.Je ne connait pas le lpc2138 ni le compilateur que tu utilise mais bon je n'en connait pas pour lesquels ça ne marche pas.

    Ceci dit j'interviens aussi sur un autre forum, plus dédié à ce type d'utilisation du c. L'avantage c'est que la bas tout le monde est électronicien et donc tu auras des réponses rapides et pointus.

    Je te met l'adresse : http://forums.jelectronique.com/



  • signaler à un administrateur
    Commentaire de Melodie_Nelson le 17/05/2006 09:48:25

    OK,
    Mais en fait c'est bon j'ai réussi à régler ce problème. Mais j'en ai d'autres du coup maintenant.
    Je vais donc aller voir sur jelectronique, merci

Ajouter un commentaire

Pub



Appels d'offres

CalendriCode

Septembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
2930     

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS