Utiliser les PIC 16F et 18F/Exercices/Introduction au langage C
Exercice 1
modifierEnlever les parenthèses des expressions suivantes lorsqu'elles peuvent être retirées.
a = (25 * 12) + b;
if ((a>4) &&(b==18)) { }
((a>=6)&&(b<18))||(c!=18)
c = (a = (b+10));
Évaluer ces expressions pour a=6, b=18 et c=24.
a = 25 * 12 + b;
if (a>4 && b==18) { } // impossible d'enlever les parenthèses restantes
a>=6 && b<18 || c!=18
c = a = b+10;
Evaluation :
- a reçoit 318
- l’expression booléenne dans le if est vraie
- l’expression complète est vraie car c est différent de 18
- b+10 = 28 sera affecté à a puis à c
Exercice 2
modifierSi une variable p1 de type signed char (8 bits signés) est déclarée écrire les expressions en C permettant de :
- mettre à 1 le bit b2
- mettre à 1 le bit b3 et b6
- mettre à 0 le bit b0
- mettre à 0 le bit b4 et b5
- inverser le bit b3 (se fait facilement avec un ou exclusif)
- mettre à 1 le bit b2 et à 0 le bit b0
- mettre à 1 les bits b0 et b7 et à 0 les bits b3 et b4
signed char p1;
p1 = p1 | 0x04; // mettre à 1 le bit b2
p1 = p1 | 0x48; // mettre à 1 le bit b3 et b6
p1 = p1 & 0xFE; // mettre à 0 le bit b0
p1 = p1 & 0xCF; // mettre à 0 le bit b4 et b5
p1 = p1 ^ 0x08; // inverser le bit b3 (se fait facilement avec un ou exclusif)
p1 = p1 & 0xFE | 0x04 ; // mettre à 1 le bit b2 et à 0 le bit b0
p1 = p1 & 0xE7 | 0x81 ; // mettre à 1 les bits b0 et b7 et à 0 les bits b3 et b4
Exercice 3
modifierOn donne le sous-programme suivant (tiré d'un ancien projet inter-semestre) :
void conversion(char nb,char result[8]){
char i;
for(i=7;i>=0;i--)
if ((nb & (1<<i)) == (1<<i))
result[i]=1;
else result[i]=0;
}
dont l'objectif est de convertir du décimal en binaire.
1) Peut-on retirer des parenthèses dans l’expression booléenne du if ?
2) Peut-on écrire (nb & (1<<i)) au lieu de ((nb & (1<<i)) == (1<<i))?
3) Construire l’expression booléenne qui permettrait l'écriture
for(i=7;i>=0;i--) if (E.B.?????) result[i]=0;
else result[i]=1;
en donnant toujours le même le même résultat de conversion.
4) Modifier le programme pour qu’il fasse une conversion d'entier (16 bits) vers le binaire.
5) Est-ce que l'algorithme suivant donne le même résultat de conversion :
for(i=7;i>=;i--) {
result[i]=nb%(2);
nb = nb / 2;
}
1°)
void conversion(char nb,char result[8]){
char i;
// version avec le moins de parenthèses possibles
for(i=7;i>=0;i--)
if (nb & 1<<i == 1<<i)
result[i]=1;
else result[i]=0;
}
2°) Oui même si cette pratique est déconseillée. On peut même écrire : (nb & 1<<i). On ne peut pas retirer les dernières parenthèses car elles appartiennent au if.
3°) Ce que l’on demande est d'inverser l’expression booléenne. Une façon simple de procéder est :
for(i=7;i>=0;i--)
if (!(nb & (1<<i)) == (1<<i)) // ! est le complément logique
result[i]=0;
else result[i]=1;
Mais on peut aussi écrire :
for(i=7;i>=0;i--)
if (nb & 1<<i == 0x00) // ou 0 tout simplement
result[i]=0;
else result[i]=1;
ou encore
for(i=7;i>=0;i--)
if (nb & 1<<i != (1<<i)) // remplacer == par !=
result[i]=0;
else result[i]=1;
4°)
void conversion16(unsigned int nb,char result[8]){
char i;
for(i=15;i>=0;i--) // 15 au lieu de 7
if ((nb & (1<<i)) == (1<<i)) // ! est le complément logique
result[i]=1;
else result[i]=0;
}
5°) C'est la technique classique de changement de base : on calcule le reste et on divise par la nouvelle base (2 ici)
Exercice 4
modifierSoit une variable :
char nb;
Écrire les expressions permettant de calculer les centaines, les dizaines et les unité de cette variable.
unsigned char cent,diz,unit;
char nb;
cent = nb / 100; // division entière par défaut
diz = (nb / 10)%10;
unit = nb % 10;
Exercice 5
modifierDifférence entre && et & Évaluer les expressions :
- a & b
- a && b
pour a= 0xF0 et b=0x0F
En déduire les valeurs booléennes correspondantes (si ces expressions étaient utilisées dans un if par exemple). Construire des expressions booléennes sur les tests suivants
expression vraie si :
- le bit b6 est à 1
- le bit b3 est à 0
- le bit b2 est à 1 et le bit b4 est à 0
- le bit b2 est à 1 ou le bit b7 est à 0
- le bit b6 est l'inverse du bit b3 (sans utiliser de décalages)
- a & b est un calcul bit à bit :
a = 11110000 & b = 00001111 --------------- 00000000
- a && b se calcule en se demandant :
- est-ce qu'a est vrai ? oui car il est différent de 0
- est-ce que b est vrai ? oui car il est différent de 0
On fait donc un et logique entre deux valeurs vraies ce qui est vrai donc donne 00000001 (ou 1)
Les expressions maintenant :
// on suppose que les bits appartiennent à une variable p1
(p1 & 0x70) == 0x70 // le bit b6 est à 1
(p1 & 0x08) == 0x00 // le bit b3 est à 0
(p1 & 0x04) == 0x04 && (p1 & 0x10) == 0x00 // le bit b2 est à 1 et le bit b4 est à 0
(p1 & 0x04) == 0x04 || (p1 & 0x80) == 0x00 // le bit b2 est à 1 ou le bit b7 est à 0
(p1 & 0x40)== 0x40 && (p1 & 0x08)== 00 || (p1 & 0x40)==0x00 && (p1 & 0x08)==08 // le bit b6 est l'inverse du bit b3
Remarque : on a construit un ou exclusif dans la dernière ligne.
Exercice 6
modifierQuelle opération arithmétique est réalisée par un décalage ? Évaluer pour cela les expressions suivantes (avec a=12 et b=23) :
- a = a >> 1 (ou a >>= 1)
- a = a >> 2 (ou a >>= 2)
- b = b << 1 (ou b <<=1)
- b = b << 2 (ou b <<=2)
Généralisation.
Construire une vraie expression booléenne avec opérateur de décalage, & et ^ qui reprend le test de l'exercice précédent : le bit b6 est l'inverse du bit b3
- a = 6 car 12 = 00001100 donc (12 >> 1) = 00000110 = 6
- a = 3 car 12 = 00001100 donc (12 >> 2) = 00000011 = 3
- b = 46 car 23 = 00010111 donc (23 << 1) = 00101110 = 46
- b = 92 car 23 = 00010111 donc (23 << 2) = 01011100 = 92
On retient :
- un décalage vers la droite est équivalent à une division par 2. Quand vous avez une division par une puissance de 2 à faire, préférez le décalage à l'opération de division.
- un décalage vers la gauche est équivalent à une multiplication par 2. Quand vous avez une multiplication par une puissance de 2 à faire, préférez le décalage à l'opération de multiplication.
Construction de l’expression booléenne :
// on suppose que les bits appartiennent à une variable p1
//Utiliser un ou exclusif bit à bit en C
(p1 & 0x40)>>6 ^ (p1 & 0x08)>>3 // le bit b6 est l'inverse du bit b3
Le principe de la dernière ligne est de décaler les bits testés au poids faible et de faire un ou exclusif qui donne un résultat vrai si et seulement si les deux valeurs sont différentes.
Exercice 7
modifierSoit le programme suivant :
#include <stdio.h>
main() {
int n=10,p=5,q=10,r;
r= n == (p = q);
printf("A : n = %d p = %d q= %d r = %d\n",n,p,q,r);
n = p = q = 5;
n += p += q;
printf("B : n = %d p = %d q= %d\n",n,p,q);
q = n++<p || p++ != 3;
printf("C : n = %d p = %d q= %d\n",n,p,q);
q = ++n == 3 && ++p == 3;
printf("D : n = %d p = %d q= %d\n",n,p,q);
return 0;
}
Que donnera-t-il comme affichage sur l'écran ?