Utiliser les PIC 16F et 18F/Introduction au langage C
Il existe un livre complet sur le langage C dans la Wikiversité. Il est pas question donc de réintroduire ici les structures de contrôles et autres fondamentaux du langage C, mais seulement de s'intéresser particulièrement aux opérateurs, aux masques et autres choses peu utilisées en programmation C standard. Le fait que l’on cible une petite architecture aura en effet quelques conséquences que l’on se propose d'examiner.
Les opérateurs du langage C
modifierLes opérateurs du language C sont classés par priorités. L'intérêt d'un tel classement est d’éviter de mettre trop de parenthèses dans les expressions qui utilisent ces opérateurs.
Le problème des parenthèses
modifierIl y a tellement d'opérateurs que l'apprentissage des priorités de ceux-ci est long. Pour éviter de se reporter à d'autres documents, on rappelle le tableau de priorité des opérateurs du C :
Catégorie d'opérateurs
|
Opérateurs
|
Associativité
|
fonction, tableau, membre de structure, pointeur sur un membre de structure | ( ) [ ] . -> | Gauche → Droite |
opérateurs unaires | - ++ -- ! ~
* & sizeof (type) |
Droite ->Gauche |
multiplication, division, modulo | * / % | Gauche → Droite |
addition, soustraction | + - | Gauche → Droite |
décalage | << >> | Gauche → Droite |
opérateurs relationnels | < <= > >= | Gauche → Droite |
opérateurs de comparaison | == != | Gauche → Droite |
et binaire | & | Gauche → Droite |
ou exclusif binaire | ^ | Gauche → Droite |
ou binaire | ǀ | Gauche → Droite |
et logique | && | Gauche → Droite |
ou logique | ǁ | Gauche → Droite |
opérateur conditionnel | ? : | Droite → Gauche |
opérateurs d'affectation | = += -= *= /= %=
&= ^= |= <<= >>= |
Droite → Gauche |
opérateur virgule | , | Gauche → Droite |
La priorité des opérateurs va décroissante lorsqu'on se déplace du haut du tableau vers le bas du tableau. Quand les opérateurs ont même priorité, c’est la colonne de droite sur l’associativité qui est utilisée.
Une expression ne doit comporter ni trop ni trop peu de parenthèses sous peine de devenir illisible. Tout est donc affaire de dosage et c’est cet apprentissage qui est long. Il faut garder à l'esprit le fait que la taille du programme généré ne dépend pas du nombre de parenthèses.
Eliminer les parenthèses
modifierEliminer les parenthèses consiste à isoler une partie de l’expression entre parenthèses et à regarder si l'autre partie de l’expression est moins prioritaire. Si c’est le cas, les parenthèses peuvent être retirées. Si ce n’est pas le cas on ne les retire pas. Lorsque les opérateurs ont même priorité on utilise l’associativité.
Un moyen simple d'apprendre à utiliser les parenthèses est de commencer à écrire des expressions avec trop de parenthèses. Quand vous en aurez marre vous commencerez à vous intéresser au problème et à éliminer les parenthèses au fur et à mesure de votre apprentissage.
Interprétation d'une expression
modifierVous ne serez pas l'auteur de tous les programmes C que vous lirez. Ainsi, parfois, votre problème ne sera pas de savoir si on peut retirer les parenthèses, mais de savoir simplement que fait l’expression. Ce problème est intimement lié à celui d'éliminer les parenthèses.
Travail sur les bits individuels en C
modifierLorsqu'on programme en C sur une petite architecture comme le PIC 16F/18F, on est très souvent amené à faire des tests sur les bits individuels de certains registres. On peut aussi être amené à être plus actif en positionnant certains bits individuels à 1 ou à 0.
Positionner un bit particulier en C
modifierLe principe de base est d’utiliser des masques.
On appelle masque une valeur définie qui va servir à l'aide d'un opérateur ou ou un opérateur et à positionner des bits individuels.
Les opérations logiques effectuées sont des opérations bit à bit :
- & et logique bit à bit en C pour positionner un ou plusieurs 0 ;
- | ou logique bit à bit en C pour positionner un ou plusieurs 1.
Les masques seront exprimés en hexadécimal. Ce n’est pas obligatoire car certains compilateurs offrent la possibilité d'écrire en binaire, mais si l’on veut être portable, il vaut mieux utiliser l'hexadécimal.
Utisation de masques
modifierComme déjà évoqué, le principe de base est d’utiliser un OU pour positionner à 1 et ET pour positionner à 0.
Un schéma de principe sera peut-être plus parlant :
Les masques sont donnés en rouge en binaire et en hexadécimal. Les X dans le registre représentent des valeurs que l’on ne connait pas. Remarquez que les X sont restés des X (ce qui signifie qu’ils n'ont pas changé) sauf pour un seul bit.
- Pour positionner un ou plusieurs bits à 1 on écrit un ou plusieurs des 1 aux places concernées et on complète par des 0. Ceci formera le masque binaire qu’il faudra transformer en hexadécimal et utiliser avec un opérateur OU.
- Pour positionner un ou plusieurs bits à 0 on écrit un ou plusieurs des 0 aux places concernées et on complète par des 1. Ceci formera le masque binaire qu’il faudra transformer en hexadécimal et utiliser avec un opérateur ET.
Utilisation de macros
modifierIl existe plusieurs autres méthodes pour positionner les bits (http://www.microchipc.com/HiTechCFAQ/index.php)
1° méthode pour positionner bit à bit :
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
unsigned char x=0b0001;
bit_set(x,3); //now x=0b1001;
bit_clr(x,0); //now x=0b1000;*/
2° méthode pour positionner plusieurs bits
#define bits_on(var,mask) var |= mask
#define bits_off(var,mask) var &= ~0 ^ mask
unsigned char x=0b1010;
bits_on(x,0b0001); //now x=0b1011
bits_off(x,0b0011); //now x=0b1000 */
Tests de bits en C
modifierUtilisation des masques
modifierOn utilise encore des masques mais en général toujours avec l'opérateur ET.
On utilise et masque avec un 1 en face du bit que l’on veut tester. On construit ensuite une expression booléenne pour tester le résultat en le comparant à une valeur prédéfinie.
Cette valeur prédéfinie est égale au masque lorsqu'on cherche à savoir si c’est un 1 ou à 0 partout dans le cas contraire. Le test de gauche dans la figure ci-dessus peut donc s'écrire :
// unsigned char Reg;
if ((Reg & 0x40) == 0x40) { //E.B. vraie si bit B6 à 1
...
}
tandis que le test de droite s'écrit quant à lui :
// unsigned char Reg;
if ((Reg & 0x08) == 0x00) { //E.B. vraie si bit B3 à 0
...
}
Il n’est pas possible de supprimer les parenthèses dans les deux programmes ci-dessus.
Utilisation d'une macro
modifierLes tests d'un bit particulier en C peuvent aussi être réalisés de la manière suivante (http://www.microchipc.com/HiTechCFAQ/index.php)
x=0b1000; //decimal 8 or hexadecimal 0x8
if (testbit_on(x,3)) a(); else b(); //function a() gets executed
if (testbit_on(x,0)) a(); else b(); //function b() gets executed
if (!testbit_on(x,0)) b(); //function b() gets executed
#define testbit_on(data,bitno) ((data>>bitno)&0x01)
Les types C du PIC
modifierMalheureusement ces définitions sont dépendantes des compilateurs C utilisés. Les compilateurs C pour PIC sont classés dans la catégorie 16 bits, c'est-à-dire que le type "integer" est sur 16 bits.
Les types du C PIC sont :
- unsigned char a;//8 bits, 0 to 255
- signed char b; //8 bits, -128 to 127
- unsigned int c; //16 bits, 0 to 65535
- signed int d; //16 bits, -32768 to 32767
- long e; //32 bits, -2147483648 to 2147483647
- float f; //32 bits
Expression booléenne (PIC 16FXXX et autres)
modifierOn appellera expression booléenne (notée parfois E.B. dans la suite), une expression qui si elle était évaluée donnerait soit la valeur VRAI ou soit la valeur FAUX. Pour construire une expression booléenne, il suffit d’utiliser de manière récursive les opérateurs de comparaisons et les connecteurs logiques comme c’est expliqué un peu plus loin dans la section "Principe de construction d'une expression booléenne".
Nous expliquons souvent à nos étudiants que la syntaxe du si est :
if ( E.B. )
par exemple, où E.B. est le diminutif d'Expression Booléenne. Le problème est qu'en C, il est possible de remplacer l’expression booléenne par n’importe quelle expression.
On appellera fausse expression booléenne ou plus simplement expression toute expression qui évaluée donne plus de deux valeurs.
Nous allons examiner le passage d'une catégorie d'expression à une autre. Le language C est capable d'interpréter une expression comme expression booléenne ou inversement.
- expression vers expression booléenne : si vous remplacez une expression booléenne par une expression, le principe est qu'une évaluation de l’expression est exécutée et que si le résultat est nul on considère l’expression comme fausse et pour toute autre valeur, on considère l’expression comme vraie.
- expression booléenne vers expression : la première est évaluée, si elle est vraie elle est remplacée par un un, si elle est fausse elle est remplacée par un 0.
C'est très pratique, mais la confusion des deux peut conduire à des erreurs.
Voici comment on transforme une expression en expression booléenne à travers un exemple :
Fausse expression booléenne
|
Vraie expression booléenne
|
---|---|
char n=10;
while(n) {
.....;
n--; }
|
char n=10;
while(n!=0) {
..... ;
n--; }
|
Ces deux constructions marchent en C. Si on se rappelle que dans une parenthèse d'un while on a une Expression Bolléenne (E.B.), on a ici d'un côté n (qui est une expression) et de l'autre n!=0 (qui est une E.B.). La différence entre les deux est que pour n elle peut prendre toutes les valeurs entre -128 et +127 (si n est de type char) alors que n!=0 ne prendra que deux valeurs 0 ou 1.
Les compilateurs C ne font absolument pas la différence entre une expression booléenne et une expression. Ce que nous avons fait dans cette section est donc un peu artificiel mais nous semble important pour relire les programmes écrits par d'autres.
Le problème du langage C est que l'oubli d'un & ou d'un | conduit en général à une fausse expression booléenne (c'est-à-dire à une expression tout court) ce qui est tout à fait autorisé. Par exemple écrire a & b au lieu de a && b.
Principe de construction d'une expression booléenne
modifierToutes les expressions du langage C sont construites à partir de briques de bases. La brique de base de l’expression booléenne est la comparaison.
Quand vous écrivez "a > 5", que vous ayez mis ou pas une valeur dans la variable a ne changera rien à la chose, cette expression est toujours soit vraie (= 1 dans ce cas) soit fausse (= 0 dans ce cas).
Si vous associez les briques de bases avec les opérateurs logiques : && et || et ! vous obtenez encore une expression booléenne.
a<7 && b!=67 est une expression booléenne identique à (a<7) && (b!=67) mais sans les parenthèses.
Voir aussi
modifier
Faites ces exercices : Introduction au langage C. |