Programmation C pdf support de cours et travaux pratiques


Télécharger Programmation C pdf support de cours et travaux pratiques

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


SOMMAIRE

  1. Spécification d’une base de numération pour une valeur numérique. 3
  2. Affectation d’une valeur à une variable. 3
  3. Les types des données du C et la déclaration des variables et constantes. 4

3.1.  Variables scalaires. 4

3.1.1.  type booléen. 4

3.1.2.  type octet 4

3.1.3.  type réel 5

3.1.4.  Pointeurs, signification des symboles  * et & placés devant une variable. 6

3.2.  Tableaux, chaînes de caractères. 6

3.2.1.  Tableaux, allocation statique en mémoire  adresse. 6

3.2.2.  Chaînes de caractères. 7

3.2.3.  Tableaux, allocation dynamique en mémoire. 8

3.3.  Structures et Unions, énumérations. 8

3.3.1.  Structures et unions. 8

3.3.2.  Union. 9

3.3.3.  Enumération. 9

3.4.  Définition de noms de types par l’utilisateur : typedef 9

3.5.  Constantes. 10

3.6.  Variables locales et variables globales. 10

  1. Expressions / opérateurs. 10

4.1.  Règles d’évaluation de l’expression. 10

4.2.  Opérateurs arithmétiques +, -, *, /, %, ++, -- 11

4.3.  logique binaire sur mots (bits à  bits de même rang)  &  , | , ~. 11

4.4.  logique booléenne &&  , ||  , ! , comparaisons  == , < , >, >= , <=. 12

  1. Structures de contrôle du déroulement en séquence. 13

5.1.  Boucles while, do while, for 13

5.1.1.  While (tant que) 13

5.1.2.  Do While (faire tant que) 14

5.1.3.  Boucle de répétition  For 15

5.2.  Branchements conditionnels if , else. 17

5.3.  Switch - Case (faire - selon le cas) 18

5.4.  Branchements inconditionnels. 18

  1. Fonctions. 19

6.1.  Introduction. 19

6.2.  Fonction non typée. 19

6.2.1.  définition ou implémentation ou encore écriture de la fonction. 19

6.2.2.  exemple de fonction sans paramètre : 19

6.2.3.  exemples de fonction avec paramètres : 20

6.3.  Fonction  typée. 21

6.4.  Arguments passés par valeur, par adresse, ou par référence. 22

6.5.  La fonction main. 23

6.6.  Fonction d’interruption. 23

  1. Programme en langage C. 24
  2. Exemple 1 de programme en langage C PIC 16F84. 25
  3. Exemple 2 de programme en langage C PIC 16F84. 26

1.  Spécification d’une base de numération pour une valeur numérique

  • Hexadecimal  :     0xvaleur    exemple :    0x2F
  • Binaire  :  0bvaleur   exemple :  0b10011010
  • Octal  :  0valeur  exemple :  0763
  • Décimal :  valeur  exemple :   129

Code ASCII  :  ‘caractère’  exemple :   ‘A’ pour le code ASCII de A

2.  Affectation d’une valeur à une variable

En C, on utilise le symbole = comme symbole d’affectation.

Exemple d’affectation :  y = 27 ; //  27 ®  y

Ceci permet de donner la valeur 27 à la variable y. Prenons le cas d’une variable y de type octet.

L’octet est situé en mémoire des données à une adresse qui a été attribuée par le compilateur. Soit Ptr_y cette adresse. La séquence des instructions générées par le compilateur PIC sera  :

 movlw  D’27’

 movwf  Ptr_y ; 27 en décimal est placée à l’adresse de la variable

Remarques :

    x=y ;  et     y=x ;  n’ont pas la même signification.

x=0x3F ; a un sens  ( x prend la valeur 0x3F  ) alors que 0x3F = x ; n’en a pas .

x=x+1; //  x+1 ®  x  a un sens : incrémenter x 

x=x-10; //  x-10®  x  a un sens : enlever 10 à la valeur de  x 

Exemple de permutation lors d’un tri des éléments d’un tableau :

if(tab[j]<tab[i])

  {

  temp=tab[i];//  tab[i] ®temp

  tab[i]=tab[j];// tab[j]® tab[i]

  tab[j]=temp; //  temp ® tab[j]

  }

Attention :

Il n’est pas possible d’affecter des grandeurs de type différents mais il existe des fonctions de changement de type.

Exemple :

  char i ; 

  float x=12.35;

  i=(char)x; // correct donne 12

mais

i=x ; est incorrect

Remarque : Il est possible de combiner affectation et opération.

Exemple d’affectation précédée d’une addition  :

unsigned char x; x est une variable octet

x + = 6; //équivaut à : x = x + 6 ;

3.  Les types des données du C et la déclaration des variables et constantes

3.1.  Variables scalaires

3.1.1.  type booléen

Tous les compilateurs C ne proposent pas ce type de déclaration. Dans le cas du compilateur PIC C LITE il est possible de déclarer des variables booléennes à l’aide du mot réservé bit.

Dans le cas le plus courant les compilateurs utilisent pour des valeurs booléennes un octet. Les états "vrai" et "faux" sont représentés respectivement par une valeur non nulle et nulle.

Exemples de déclaration de variables de type bit :

bit init_flag;

Le compilateur loge en mémoire vive disponible ce bit. On ne se préoccupe pas de son adresse d’implantation en mémoire des données.



On utilise alors le mot static  et le symbole @ si l’on doit imposer l’adresse de la variable.

static bit RA3 @ 5*8+3;

RA3 est le bit situé au rang 3 de l’octet d’adresse 5.

3.1.2.    type octet

Il est possible de déclarer des variables octets à l’aide du mot char ou des mots unsigned char.

  • char    : plage de variation :  -128  ,  127  pour 1 octet avec bit de signe. 
  • unsigned   char  : plage de variation :  0  ,  255 pour 1 octet sans bit de signe.

Pourquoi ce mot réservé et non pas le mot byte qui semble plus approprié ? A  cause de l’utilisation des octets pour coder les caractères mais il faut remarquer que ce n’est pas le seul cas d’utilisation.

Exemples de déclaration de variables de type char :

char NombreImpulsions;

char compt0,compt1;

Le compilateur se charge de réserver une place à une adresse en mémoire vive pour les octets.

Dans les programmes nous ne nous préoccuperons généralement pas de l’adresse d’implantation de l’octet dans la mémoire des données.

Remarque : en langage C la valeur d’adresse est accessible en écrivant &compt0 par exemple qui se lit adresse de la valeur compt0. 

On souhaite parfois imposer l’adresse d’implantation . On utilise alors le mot static et le symbole @..

static unsigned char PORTA @ 0x05;

Le compilateur doit implanter à l’adresse  H’05’ en mémoire vive l’octet de nom PORTA. type entier

Le mot int permet de déclarer des entiers sur plus d’un octet .

  int  : plage de variation sur 16 bits  : -32768  ,  32767  ( valeurs)

  unsigned int  : plage de variation sur 16 bits  :  0  ,  65535   ( valeurs)

Exemple de déclaration de variables de type int :

int x,y,z;

Le compilateur se charge de réserver une place à des adresses consécutives en mémoire vive pour ces doubles octets.

Dans les programmes nous ne nous préoccuperons généralement pas de l’adresse  de début d’implantation des variables.

3.1.3.  type réel

Dans le cas du compilateur PIC C LITE il est possible de déclarer des variables réelles sur 24 bits et 32 bits à l’aide des mots réservés float et double.

Un nombre réel est rangé en mémoire sous la forme :

    avec 0 =< mantisse < 1

Variable

Bit de signe

Exposant+127

Mantisse

  Float

1 bit

8 bits

15 bits

L’exposant est codé en excès de 127. Ainsi 0 est représenté par 127.

Les bornes extrêmes d’un réel de type float sont ainsi  :

    ( valeurs les plus proches de 0 )

  et   ( valeurs les plus éloignées de 0 )

On trouve sur 24 bits : le bit de signe  suivi des 8 bits d’exposant +127 et enfin les 15 autres bits de  la mantisse.

Exemples :

  B  F  8  0  0  0  représente la valeur –1

1011 1111 1000 0000 0000 0000

( bit de signe : 1  puis  bits d’exposant : 011 1111 1 qui correspondent à l’exposant + 127 ici 0 + 127

 et enfin la mantisse 000 0000 0000)

3F 80 00 représente la valeur 1 (seul le bit de signe change par rapport à -1)

40 00 00 représente la valeur 2  (  100  0000 0 correspond à l’exposant + 128 ici 1 + 127)

3F 00 00 représente la valeur 0.5

3E 80 00 représente la valeur 0.25

etc.

Le compilateur se charge de réserver une place à une adresse en mémoire vive pour les variables de type float, double.

Dans les programmes nous ne nous préoccuperons généralement pas de l’adresse d’implantation de ces variables.

3.1.4.  Pointeurs, signification des symboles  * et & placés devant une variable

On appelle pointeur  l’adresse de début d’implantation en mémoire d’une variable.

La déclaration d’un pointeur contient l’information du type de variable pointée afin de pouvoir tenir compte de règles d’incrémentation et de décrémentation des pointeurs.
Le nom du pointeur est précédé du symbole  *

Souvent, on fera précéder les noms de pointeurs de Ptr ou de la lettre p  pour bien les différencier des noms de variables.

  int  *Ptrx;   //Ptrx est un pointeur sur une variable de type int.

Attention, le symbole * est utilisé en C dans ce contexte ( déclaration ) pour indiquer que Ptrx est le nom d’une adresse alors que dans d’autres contextes il aura une autre signification ( cas d’une expression arithmétique : symbole de la multiplication ).

Remarque concernant l’arithmétique des pointeurs :

  Ptrx++ ; 

Incrémente la valeur de Ptrx de 2 dans ce cas d’un pointeur sur un entier car un entier occupe 2 places en mémoire (2 octets).

Si Ptrx est le nom de l’adresse d’une variable, son contenu est désigné par * Ptrx.

Si x est le nom d’une variable, son adresse (pointeur sur le premier octet)

est désignée par &x.

Dans ce contexte, l' opérateur & est appelé opérateur d'adressage.

Ainsi dans le cas d’un entier x sur 2 octets :

3.2.  Tableaux, chaînes de caractères

3.2.1. 

Tableaux, allocation statique en mémoire  adresse

//déclarations d'un tableau de 3 entiers,.

int tab1[3];

temp=tab1[i];//  tab1[i] ®temp

Remarques:

  • Le premier élément du tableau est situé à l’indice 0.
  • i doit être compris entre 0 et 2 inclus.
  • Chaque entier occupe 2 emplacements en mémoire
  • Le nom, ici tab1, du tableau est le pointeur constant
    sur le premier élément du tableau.
  • Le nom du tableau est l’adresse du premier élément du tableau.

//déclarations d'un tableau de 6 octets avec initialisation, allocation statique en mémoire.



unsigned char tab_seg[]={0x3F,0x06,91,79,102,109};

3.2.2.  Chaînes de caractères

Une chaîne de caractères est tout simplement un tableau de code ASCII de caractères terminé par la valeur 0.

Remarques:

  • Le message est encadré par "  "
  • Un code ASCII d’un seul caractère est noté entre  ‘  ’

Exemple de déclaration avec initialisation :

  char message1 [ ] = "bonjour";

3.2.3.  Tableaux, allocation dynamique en mémoire

Lorsque les programmes manipulent des données mobilisant beaucoup d’espace mémoire ( cas d’images par exemple), ces données ne sont placées en mémoire que lorsqu’on les utilise puis l’espace mémoire est libéré.

 Le Compilateur PIC C LITE ne propose pas ce type d’allocation.

 char *PtrImage ;

 PtrImage =new char[1000000];  // allocation dynamique en mémoire de 1000 0000 d’ octets.

 delete PtxImage ; // libère l’espace alloué

3.3.  Structures et Unions, énumérations

3.3.1.  Structures et unions

Le mots réservé  struct permet de déclarer des variables composées de plusieurs champs placés en mémoire à des adresses consécutives.

Exemples :

struct struct_complexe

  {

  double m_reel;

  double m_imaginaire;

  }im1,im2;

struct struct_etudiant

  {

  char m_nom[10];

  int m_note[5]; 

  } etudiant1, etudiant2, etudiant3;

On accède au champ d’une variable structurée en faisant suivre le nom de la variable du nom du champ ( on dit aussi le membre de la variable ).

Exemples :

  im1.m_reel=2.3;

  im1.m_imaginaire=5;

  etudiant1.m_nom[]= "Toto";

Déclaration d’une structure composée de 8 bits à partir de l’adresse 0x6. Le champ B0 est le bit de rang 0 de PORTB et le champ B7 est le bit de rang 7 de PORTB :

struct {

unsigned   B0 : 1; // bit de rang 0

unsigned   : 6; // bits de rang 1 à 6 inutilisés

unsigned   B7 : 1; // bit de rang 7

}  PORTB  @0x6;

  On pourra écrire : if ( PORTB.B0) pour tester l’état du bit de rang 0 de port B.

3.3.2.  Union

Le mot réservé   union permet de déclarer des variables de différents types et tailles, variables qui  se recouvrent en mémoire.

union struct_16bits {

unsigned   int  DoubleOctet;

unsigned   char Octet[2]; 

}  x1,x2,x3;

3.3.3.  Enumération

Le mot réservé  enum  permet de déclarer des noms dont les états possibles sont définis par énumération.

Exemple 1 :

enum {rouge,vert,orange} couleur_feu;

La variable de nom couleur_feu peut se voir affecter les valeurs rouge (0) , vert (1) , orange (2) . 

Exemple 2 :

enum {PB ,OK} EtatMachine;

3.4.  Définition de noms de types par l’utilisateur : typedef

Le mot réservé  typedef  permet de déclarer des noms de type par l’utilisateur.

//exemple de définition du nouveau nom de type « byte » :

typedef unsigned char byte ;

On pourra alors écrire :

byte x;

Souvent, on fera précéder les noms de type de t_  pour bien les différencier des noms de variables.

//définition de t_complexe

typedef struct stuct_complexe

  {

    double m_reelle;

    double m_imaginaire;

  }

  t_complexe;

On pourra alors écrire :

t_complexe x; puis x. m_reelle=0.5 ; . m_imaginaire=2.5 ;

//définition de t_booleen

typedef   enum

  {  faux ,vrai}

   t_booleen;

On pourra alors écrire :

t_booleen  etat_moteur;

Déclaration d’un type d’une structure composée de 8 bits du rang 0 au rang 7d’un octet.

typedef struct    {    unsigned  pompe:1, evacuation:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;  }  t_bitv;    

On pourra alors écrire :

t_bitv  actionneurs;

actionneurs.pompe=1;

3.5.  Constantes

Le mot réservé  const  permet de déclarer des noms de valeurs constantes par l’utilisateur.

Exemple :

const   unsigned char   VERSION = 3;

 

On ne peut pas affecter une constante.

VERSION =5;  provoque un message d’erreur lors de la compilation.

3.6.  Variables locales et variables globales

  En langage C tout nom de variable doit être déclaré.

  Une variable est globale si elle est déclarée en début de programme. Elle est alors connue dans tout le programme.

Une variable est locale si elle est déclarée à l'intérieure d'une fonction. Elle est alors connue seulement dans le corps de la fonction.

4.  Expressions / opérateurs

4.1.  Règles d’évaluation de l’expression 

Les calculs se font en tenant compte de l’ordre de priorité que peut modifier l’utilisation de parenthèses.

Si les opérateurs sont de même ordre de priorité l' évaluation progresse de gauche à droite et s'arrête dès qu'on peut conclure.

4.2.  Opérateurs arithmétiques +, -, *, /, %, ++, --

  • Opérateurs portant sur deux opérandes  +  -  *  / %
    • L'opérateur % donne le reste de la division entière (modulo).
    • La division de deux entiers donne un quotient entier.

Exemple d’instructions :


// variables de type int

unite=x%10;

dizaine=(x/10)%10;

centaine=x/100;

// variables de type double

module = sqrt (x*x+y*y)  // sqrt fonction racine carré

  • Dans l'ordre de priorité d’exécution, on aura :

   *  et  / , %

   puis +  et  -

  • Opérateurs portant sur  un seul opérande

 i++ pour incrémentation de i   ainsi  i++ ;  donne le même résultat que  i = i+1 ;

     i - -  pour décrémentation de i  ainsi  i - - ;  donne le même résultat que i = i -1 ;

 ++ ou – placé devant le nom de la variable indique que l’incrémentation ou la décrémentation doit être faite de avant les autres opérations.



4.3.  logique binaire sur mots (bits à  bits de même rang)  &  , | , ~ 

  • Ces opérateurs ne s'appliquent qu'aux types octets (en général naturel : unsigned ), agissent bit à bit sur la représentation interne en base 2.
  • Dans l'ordre de priorité d’exécution, on aura :

  ~  Complément à 1  (permet de changer les états des bits)

  <<  Décalage à gauche  (permet de multiplier par 2, 4, ......)

  >>  Décalage à droite  (permet de diviser par 2, 4, ..........)

  &  Et logique   (permet de mettre des bits à 0)

  I  Ou logique  (permet de mettre des bits à 1)

  ^  Ou exclusif 

(permet  de changer les états des bits, de déceler des changements d’états des bits)

Exemple 1 de décalage à droite:

unsigned char portb;

 portb=portb>>2;  après 2 décalages : 

Exemple 2 de mise à 1 du bit de rang 2 de portb:  ou bit à bit

portb=portb|0x04; 

Remarque : le compilateur PIC CLITE permet de manipuler des noms de bits.

Ainsi on peut écrire :   RB2=1 ;

Exemple 3 de mise à 1 du bit de rang 2 de portb:

  portb | = 0x04; 

Exemple 4 de mise à 0 du bit de rang 2 de portb:  et bit à bit

portb & = 0xFB; 

Remarque : le compilateur PIC CLITE permet de manipuler des noms de bits.

Ainsi on peut écrire :   RB2=0 ;

4.4.  logique booléenne  &&  , ||  , ! , comparaisons  == , < , >, >= , <=

  • Appliqués à des opérandes numériques, les opérateurs logiques produisent un résultat "booléen" : 1 (pour vrai) ou 0 (pour faux).
  • Dans l'ordre de priorité d’exécution, on aura :

  La négation  !

  Les comparaisons  <  <=  >=  >

  Les comparaisons  = = (identique)  ! =  (différent de)

  Le et logique  &&

  Le ou logique  II

  • Toute valeur différente de 0 est considéré comme  « vrai » en langage C.

Exemples d’utilisation des opérateurs logiques:

if( (PresenceVoiture == 1) && (NbreVoitures < NbreMax))

  {

  ouvrir_barriere();

  NbreVoitures++;

  }

Autre exemple d’utilisation :

  //t est-il le code ascii d’une lettre ?

if (((t>='a') && (t<='z')) || ((t>='A') && (t<='Z')))

{

  //cas d’une lettre

}

Cas particulier  d’utilisation d’une expression toujours vrai :  1>0 .

//pour une boucle sans fin

while(1>0) 

{//debut de boucle sans fin

//instructions dans la boucle

}//fin de boucle sans fin

Autre cas particulier  d’utilisation d’une expression toujours vrai : 1 .

while(1) {} pour une boucle sans fin sans instructions dans la boucle

5.  Structures de contrôle du déroulement en séquence

5.1.  Boucles while, do while, for

5.1.1.  While (tant que)

Tant qu’une condition est vrai faire  s’écrit en langage C :

  while(expression)

  {

  instructions; 

  } //while expression

Exemple  de test de PORTB supposé en entrée dans une commande de machine à laver :

  while(PORTB< 60 )

{

  chauffage() ; 

}

Exemple  d’attente que RB7 soit à 1 (RB7 supposé en entrée) dans le cas du test du LCD occupé (carte IUT2 + LCD).

  while(RB7==1){} //remarquer == pour la comparaison

 

Exemple  de test de fin de message :

  while(*message!=0) //Note:la fin d’un message est indiquée par la valeur 0

  {

  LCD_car(*message);

  message++;

  }

  Exemple  de boucle sans fin :

  while(1) // faire toujours

  { 

  PORTA=etat1; // état 1 du port A

  while(inter0==0){} //remarquer == pour la comparaison

  PORTA=etat2; // état 2 du port A

  while(inter1==0){}

  PORTA=etat3; // état 3 du port A

  while(inter2==0){} 

  }

5.1.2.  Do While (faire tant que)

Faire tant qu’une condition est vrai s’écrit en langage C :

do  

  {

  instructions; 

  }  //do expression

while (expression);

Exemple :

float milieu;

float a=0.0;

float b=7.0;

  do

  milieu=(a+b)/2;

  if(f(a)*(f(milieu))<0)

  b=milieu;

  else

    a=milieu;

     }

    while((b-a)>0.001);

Dans le cas de la figure la solution devra être recherchée entre a et milieu.

On aura alors un segment de recherche 2 fois plus petit que le segment précédent. On fixe comme condition d’arrêt une précision sur la valeur de la racine donc sur la largeur b-a


162