Annexe – Tutoriel sur les opérations arithmétiques courantes en électronique

Comme je l’ai dit lors de mon introduction pour ces tutoriels, la programmation de microcontrôleur nécessite de connaitre les opérations arithmétiques binaires. Celles-ci ne se comportent pas comme les opérations usuels d’addition et de soustraction.

Les opérations booléennes

Vous le savez déjà, le binaire est une base où chaque chiffre ne peut avoir que deux valeurs : 0 ou 1. Nous allons nous intéresser aux opérations que l’on peut effectuer sur un bit. Cette partie des mathématiques s’appelle l’algèbre de Boole.

La conjonction : le «et» logique

La conjonction est l’opération qui prend pour valeur la vérification de ses deux opérandes. En C, on utilise deux esperluettes [ccie]&&[/ccie] comme opérateur. Pour vous aider à mieux comprendre, voici la liste des 4 valeurs que peut prendre cette opération :

  • [ccie]0 && 0 = 0[/ccie]
  • [ccie]0 && 1 = 0[/ccie]
  • [ccie]1 && 0 = 0[/ccie]
  • [ccie]1 && 1 = 1[/ccie]

La disjonction : le «ou» logique

La disjonction se vérifie si au moins un de ses deux opérandes se vérifie. Le symbole que l’on utilisera ici est le tuyau, deux fois [cci]||[/cci] que l’on obtient en pressant [cci]Alt Gr[/cci] avec la touche [cci]6[/cci] sur un clavier français. Voici les valeurs :

  • [cci]0 || 0=0[/cci]
  • [cci]0 || 1=1[/cci]
  • [cci]1 || 0=1[/cci]
  • [cci]1 || 1=1[/cci]

La négation

La négation est une opération qui prend la valeur opposée à son unique opérande. En C, on utilise le point d’exclamation [cci]![/cci], qui va précéder l’opérande. En toute logique, ses valeurs possibles sont :

  • [cci]!0 = 1[/cci]
  • [cci]!1 = 0[/cci]

Ces 3 opérations sont la base de toute l’algèbre de Boole. Elles cumulent diverses propriétés mathématiques (idempotence, commutativité, distributivité, etc.). Pour plus d’informations, je vous suggère la page Wikipédia de l’algèbre de Boole.

Les opérations bit à bit

À part pour gérer des conditions, il est rare d’utiliser le booléen sous sa forme brute. On utilisera plutôt des entiers, de 8 ou 16 bits, auxquels on appliquera des opérations logiques dédiées.

L’affectation directe

Plutôt que d’écrire des opérations compliquées, il est parfois plus simple d’initialiser un entier avec sa valeur binaire ou hexadécimale. En C, on fera comme ceci :

  • [cci]int i = 0xFF; // les 8 premiers bits à 1[/cci]
  • [cci]int i = 0x0F; // les 4 premiers bits à 1[/cci]
  • [cci]int i = 0b10101010; // un bit sur deux[/cci]
  • [cci]int i = 0b10000001; // seulement le premier et le dernier bits[/cci]

La négation

L’opérateur de négation bit à bit n’est pas un point d’exclamation, mais le tilde [cci]~[/cci]. La négation bit à bit se contente de changer chaque valeur de bit par l’opposée. Le résultat final dépendra de la taille de l’entier (8 ou 16 bits). On ne travaille pour le moment qu’en 8 bits. Aussi, on aura les valeurs suivantes :

  • [cci] ~(0x0F) = 0xF0 [/cci]
  • [cci] ~(0b00000111) = 0xb11111000 [/cci]
  • [cci] ~(0b0000000) = 0xb11111111 = 0xFF = 255 [/cci]

Cette opération est parfois utilisée pour basculer une série de valeurs.

Le «et» bit à bit

On parcours deux nombres en même temps, bit par bit, et on réalise l’opération «et» logique vue plus haut. On utilise comme opérateur l’esperluette simple [ccie]&[/ccie]. Exemples :

  • [ccie] 0xF8 & 0x1F = 0b11111000 & 0b00011111 = 0b00011000 = 0x18  [/ccie]
  • [ccie] 0x3F & 0xAA = 0b00111111 & 0b10101010 = 0b00101010 = 0x2A [/ccie]
  • [ccie] 0x47 & 0x2E = 0b01000111 & 0b00101110 = 0b00000110 = 0x06 [/ccie]

Il faut s’habituer à ce genre d’opérations, car elles sont courantes.

Le «ou» bit à bit

Comme pour l’opération précédente, sauf qu’à chaque pair de bits, on utilise l’opération «ou» logique. L’opérateur ici est le tuyau simple [cci]|[/cci]. Reprenons les mêmes exemples :

  • [cci] 0xF8 | 0x1F = 0b11111000 | 0b00011111 = 0b11111111 = 0xFF  [/cci]
  • [cci] 0x3F | 0xAA = 0b00111111 | 0b10101010 = 0b10111111 = 0xBF [/cci]
  • [cci] 0x47 | 0x2E = 0b01000111 | 0b00101110 = 0b01101111 = 0x6F [/cci]

Le «ou» exclusif bit à bit

L’opération fonctionne de la même manière, sauf qu’ici, si dans une pair, les deux bits sont à 1, alors le résultat sera 0. L’opérateur utilisé est l’accent circonflexe [cci]^[/cci].

  • [cci] 0xF8 ^ 0x1F = 0b11111000 ^ 0b00011111 = 0b11100111 = 0xE7  [/cci]
  • [cci] 0x3F ^ 0xAA = 0b00111111 ^ 0b10101010 = 0b10010101 = 0x95 [/cci]
  • [cci] 0x47 ^ 0x2E = 0b01000111 ^ 0b00101110 = 0b01101001 = 0x69 [/cci]

Le décalage à gauche

Cette opération consiste à décaler l’ensemble des bits vers la gauche. Ce qui entre par la droite à pour valeur 0. Elle est très souvent utilisé. Ici on doit préciser un opérande, et un nombre de bits à décaler. L’opérateur sera le double chevron vers la gauche (signe inférieur) [ccie]<<[/ccie]. Tout ce qui dépasse la taille de l’entier est perdu (au delà de 8 bits ici).

  • [ccie] 0xF8 << 1 = 0b11111000 << 1 = 0b11110000 = 0xF0  [/ccie]
  • [ccie] 0x3F << 2 = 0b00111111 << 2 = 0b11111100 = 0xFC  [/ccie]
  • [ccie] 0x47 << 2 = 0b01000111 << 2 = 0b00011100 = 0x1C [/ccie]

Le décalage à droite

Cette opération fonctionne de façon similaire à celle-ci dessus, mais elle est beaucoup moins utilisée. On utilise le double chevron vers la droite (signe supérieur) [ccie]>>[/ccie].

  • [ccie] 0xF8 >> 1 = 0b11111000 >> 1 = 0b00111100 = 0x3C  [/ccie]
  • [ccie] 0x3F >> 2 = 0b00111111 >> 2 = 0b00001111 = 0x0F  [/ccie]
  • [ccie] 0x47 >> 2 = 0b01000111 >> 2 = 0b00010001 = 0x11 [/ccie]

Leur utilisation au travers du C

Maintenant que vous connaissez ces opérations, voici comment les utiliser et surtout pourquoi les utiliser.

Dans mes tutoriels AVR, vous trouverez souvent ces opérations sous forme abrégée ; voici les équivalence :

  • [cci]a  ^= b[/cci]  équivaut à [cci]a = a ^ b[/cci]
  • [ccie]a  &= b[/ccie]  équivaut à [ccie]a = a & b[/ccie]
  • [cci]a  |= b[/cci]  équivaut à [cci]a = a | b[/cci]
  • [ccie]a  <<= b[/ccie]  équivaut à [ccie]a = a << b[/ccie]
  • [ccie]a  >>= b[/ccie]  équivaut à [ccie]a = a >> b[/ccie]

Vous pourrez maintenant vous familiarisez à ce genre d’opérations :

  • [ccie]PINB & (1<<PINB1)[/ccie] : on vérifie que le registre entrée ait bien le bit numéro PINB1 d’actif. Cela équivaut à ne chercher que le bit qui nous intéresse dans le registre.
  • [ccie]PORTB ^= (1<<PORTB0)[/ccie] : on bascule l’état de la broche 0 du port B

Il vous faudra surement de l’entrainement pour réussir à déchiffrer le code. Mais une fois que vous aurez compris, vous ne pourrez plus vous passer de ce genre d’astuces !

Une réflexion au sujet de « Annexe – Tutoriel sur les opérations arithmétiques courantes en électronique »

  1. Merci pour cet article ma foi bien intéressant.
    Entre ça et ta suite d’articles sur les AVR, je n’ai plus vraiment d’excuses pour ne pas m’y mettre.

    En revanche cette ligne :
    0xF8 >> 1 = 0b11111000 >> 1 = 0b00111100 = 0x3C
    Ne devrait pas plutôt ressembler à ça ? :
    0xF8 >> 1 = 0b11111000 >> 1 = 0b01111100 = 0x7C

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*