Cours C Pour Embarque
Cours C Pour Embarque
Cours C Pour Embarque
M.RAHMOUNE
Historique
ANSI/ISO
1988
(et 1999)
Le C est Le langage de développement le plus répandu dans les
entreprise (et ailleurs).
Bibliographie
…...
La gestion de la mémoire
Logique de
(28) 256 états
Logique de 2 états
insuffisante 1
0
logique binaire
La gestion de la mémoire
La mémoire d’un ordinateur
• La mémoire comporte trois zone d allocation
• Chaque zone sert a mémoriser trois types de variables
exécutable
Code
Cache Registres
(cmos) Unité
RAM Logique
(silicium)
Zone statique
Dynamique
(Stack/pile)
Mémoire
Mémoire
virtuelle Zone d ’allocation
(disque) mémoire
(Heap, tas)
Mémoire
Statique
La gestion de la mémoire
Segment N+2
Segment N+1
Sans segmentation
Segment N +
Offset de l ’objet
en mémoire Un adressage sur 64 bits
Segment N-1
= 64 Ko (65.536 octets
Généralité Sur Les Flux (Ou Flots)
Code C
Librairies
Code préprocesseurs
Fichier(s)) Objet
Fichier(s
Programme
{
printf(« hello to C word "); Une instruction se termine par ;
return 0; Bloc / Programme principale
}
Structure d’un programme C
• Programme C :
une ou plusieurs fonctions dont au moins une fonction main stockées
dans un ou plusieurs fichiers.
• Fonction :
• type et nom de la fonction suivis d'une liste d'arguments entre
parenthèses,
• instruction composée constituant le corps de la fonction.
• Instruction composée : délimitée par les caractères { et }
• Instruction simple : se termine par ;
• commentaire : encadre par les délimiteurs /*et */
• Instruction préprocesseur : commence par #
Les sources d'une application écrite en langage C peut être stocke dans un ou plusieurs
fichiers dont le suffixe ou l’extension .c
La compilation de ces sources s'effectue a l'aide de la commande cc. Sans autre
spéciation, cette commande enchaîne 3 étapes :
• appel au préprocesseur
• appel au compilateur,
• appel a l'éditeur de liens.
Généralité: Jeu de caractère utilisé en c
• caractères spéciaux :
! * + \ " <
# ( = | } >
% ) ~ ; ] /
^ - [ : , ?
enum signed
Structure d’un programme C
#include <stdio.h>
#define PI 3.14159
/* calcul de la surface d'un cercle */
main()
{
float rayon, surface;
float calcul(float rayon);
printf("Rayon = ? ") ;
scanf("%f", &rayon) ;
surface = calcul(rayon) ;
printf("Surface = %f\n", surface) ;
}
/* définition de fonction */
float calcul(float r)
{
/* définition de la variable locale */
float a ;
a = PI * r * r ;
return(a);
}
Opérateur Séquentiel
Exemple
int i;
float r;
double dble , d;
char *ptr;
char buffer[100];
d = (i = 1 , r = 2.718f , dble =
2.7182818);
r = (float)(ptr = buffer , i = 10);
Les types de base
• Le langage contient des types de base qui sont les entiers, les réels simple et
double précision et les caractères que l'on identifie a l'aide des mots-clés int, float,
double et char respectivement.
• Les mots-clés short et long permettent d'influer sur la taille mémoire des entiers et
des réels.
Les types de base
Syntaxe type
void Ensemble vide
pas de type
char caractère
short int entier cours
int entier
long int entier long
float réel simple précision
double réel double précision
long double réel de précision étendue
• La taille d'un entier par défaut est soit 2 soit 4 octets (dépend de la
machine). 4 octets est la taille la plus courante.
• La taille d'un entier court est en général 2 octets et celle d'un entier long 4
octets.
• La taille d'un entier court est inferieure ou égale a la taille d'un entier par
défaut qui est elle-même inferieure ou égale a celle d'un entier long.
char ≤ short int ≤ int ≤ long int
float ≤ double ≤ long double
• Les types short int et long int peuvent être abrégés en short et long.
• Les entiers sont signés par défaut, tandis que les caractères peuvent
l'être ou pas suivant le compilateur utilisé.
#include <stdio.h>
unsigned char mask;
long val;
main()
{
unsigned int indice;
float x;
double y;
char c;
...
return;
}
double f(double x)
{
unsigned short taille;
int i;
unsigned long temps;
double y;
...
return y;
Les constantes Littérales
Constantes entières
•Une constante entière peut s'écrire dans les systèmes décimal, octal ou
hexadécimal.
•Une constante entière préfixée :
du chiffre 0 est une constante octale,
des caractères 0x ou 0X est une constante hexadécimale.
•Une constante entière est par défaut de type int.
•Elle est de type long si elle est suffixée par les lettres l ou L et non signée
lorsqu'elle est suffixée par les lettres u ou U.
Exemple
base 10 22 56 1789 32765
22u 56L 29UL 1L
base 8 0643 0177 0644 0755
0177L 0222UL 0777u 0766ul
base 16 0xff 0Xabcd 0x80 0X1
0xffL 0X1uL 0X7fU 0x5fUL
Les constantes Littérales
Constantes réelles
Une constante réelle (ou constante en virgule flottante) est un nombre exprime
en base 10 contenant un point décimal et éventuellement un exposant sépare du
nombre par la lettre e ou E.
Exemples
0. 1. 0.2 1789.5629
50000. 0.000743 12.3 315.0066
2E-8 0.006e-3 1.66E+8 3.1415927
1.6021e-19f 6.0225e23F 2.718281 6.6262e-34
Les constantes Littérales
Constantes caractères
Une constante caractère est assimilée a un entier sur un octet dont la valeur
correspond au rang du caractère dans la table ASCII.
Une constante caractère est constituée soit :
d'un caractère entre apostrophes ;
d'une suite de deux caractères entre apostrophes dont le premier est
le caractère \. Ces caractères s'appellent des codes d'échappement ;
d'un mot de la forme '\nnn', nnn étant la valeur octale de l'entier
associe au caractère ;
d'un mot de la forme '\xnn', nn étant la valeur hexadécimale de
l'entier associe au caractère.
Les constantes Littérales
Constantes caractères
Les constantes Littérales
Exemples
Valeur entière associée
'A' ==> 65
'x' ==> 120
'3‘ ==> 51
'$' ==> 36
'' ==> 32
'\n' ==> 10
'\t' ==> 9
'\b' ==> 8
'\"' ==> 34
'\\' ==> 92
'\'' ==> 39
'\0' ==> 0
'\177' ==> 127
'\x0a' ==> 10
'\000' ==> 0
Les constantes Littérales
Constantes chaîne de caractères
•Une constante chaîne de caractères est une suite de caractères entre guillemets.
•En mémoire, cette suite de caractères se termine par le caractère ('\0').
•La valeur d'une chaîne de caractères est l'adresse du premier caractère de la
chaîne qui est donc du type pointeur de caractères (char ).
•Ne pas confondre "A" et 'A' qui n'ont pas du tout la même signification !
•Pour écrire une chaîne de caractères sur plusieurs lignes on peut :
soit terminer chaque ligne par \,
soit la découper en plusieurs constantes chaîne de caractères, le
compilateur effectuera automatiquement la concaténation.
exemple
char *chaine = "\
\n\
\t/----------------------------------------------\\\n\
\t| Pour écrire une chaîne sur plusieurs lignes, |\n\
\t| il suffit de terminer chaque ligne par \\ |\n\
\t\\---------------------------------------------/\n";
char *chaine = "écriture d'une chaîne de caractères "
"sur plusieurs lignes\n\n";
Opérateurs arithmétiques
• l'addition (+),
• la soustraction (-),
• la multiplication (*),
• la division (/),
• le reste de la division entière (%).
Leurs opérandes peuvent être des entiers ou des réels hormis ceux du dernier qui agit
uniquement sur des entiers.
Lorsque les types des deux opérandes sont différents, il y a conversion implicite dans
le type le plus fort suivant certaines règles.
Règle de conversion
• si l'un des opérandes est de type long double, convertir l'autre en long double,
• sinon, si l'un des opérandes est de type double, convertir l'autre en double,
• sinon, si l'un des opérandes est de type float, convertir l'autre en float,
• sinon, si l'un des opérandes est de type unsigned long int, convertir l'autre en unsigned
long int,
•sinon, si l'un des opérandes est de type long int et l'autre de type unsigned int, le
résultat dépend du fait qu'un long int puisse représenter ou non toutes les valeurs d'un
unsigned int ; si oui, convertir l'opérande de type unsigned int en long int ; si non,
convertir les deux opérandes en unsigned long int,
• sinon, si l'un des opérandes est de type long int, convertir l'autre en long int,
• sinon, si l'un des opérandes est de type unsigned int, convertir l'autre en unsigned int,
• operateurs relationnels :
inférieur à (<),
supérieure à (>),
• 2 operateurs de comparaison :
identique à (==),
différent de ( !=).
• 2 operateurs de conjonction :
le et logique (&&),
le ou logique (||).
•Le résultat de l'expression :
!expr1 est vrai si expr1 est fausse et faux si expr1 est vraie ;
expr1&&expr2 est vrai si les deux expressions expr1 et expr2 sont
vraies et faux sinon.
L'expression expr2 n'est évaluée que dans le cas ou l'expression expr1
est vraie ;
expr1||expr2 est vrai si l'une au moins des expressions expr1, expr2 est
vraie et faux sinon.
L'expression expr2 n'est évaluée que dans le cas ou l'expression expr1
est fausse.
Opérateurs logiques
Exemple
int i;
float f;
char c;
i = 7;
f = 5.5;
c = 'w';
Expressions
f>5
(i + f) <= 1
c == 119
c != 'w'
c >= 10*(i + f)
(i >= 6) && (c == 'w')
(i >= 6) || (c == 119)
(f < 11) && (i > 100)
f>5 ==> vrai (1)
(i + f) <= 1 ==> faux (0)
c == 119 ==> vrai (1)
c != 'w' ==> faux (0)
c >= 10*(i + f) ==> faux (0)
(i >= 6) && (c == 'w') ==> vrai (1)
(i >= 6) || (c == 119) ==> vrai (1)
(f < 11) && (i > 100) ==> faux (0)
Opérateurs de taille
Syntaxe
sizeof expression
sizeof (expression-de-type)
l'expression p + i
a pour valeur p + i*sizeof(t)
Opérateurs de taille
Exemples
int menu[1000];
typedef struct cel {
int valeur;
struct cel *ptr;
} Cel;
Exemples
int u;
int v;
int *pu;
int *pv;
typedef struct cel
{
int valeur;
struct cel *ptr;
} Cel;
Cel c1, *c2;
u=3;
pu = &u ;
v = *pu ;
pv = &v ;
c2 = &c1 ;
Opérateurs de manipulation de bits
int a, b, c, flag;
int Mask;
a = 0x6db7; |-0-|-0-|0110 1101|1011 0111|
b = 0xa726; |-0-|-0-|1010 0111|0010 0110|
Opérateurs de manipulation de bits
Le motif binaire du 1er opérande, qui doit être un entier, est décalé du nombre de
bits indique par le 2eme opérande.
Dans le cas d'un décalage a gauche les bits les plus a gauche sont perdus. Les
positions binaires rendues vacantes sont remplies par des 0.
Lors d'un décalage a droite les bits les plus a droite sont perdus. Si l'entier a
décaler est non signé les positions binaires rendues vacantes sont remplies par
des 0, s'il est signé le remplissage s'effectue à l'aide du bit de signé.
Opérateurs de décalage
Exemple
int etat;
int oct;
int ent;
int a;
a = 0x6db7; |-0-|-0-|0110 1101|1011 0111|
a = a << 6;
a = 0x6db7;
a = a >> 6;
ent = 0xf0000000;
ent = ent >> 10;
Opérateurs de décalage
+= -= *= /= %=
&= |= ^= <<= >>=
Syntaxe
expr1 ? expr2 : expr3
int i;
int indic;
int a, b;
int c;
...
indic = (i < 0) ? 0 : 100;
c += (a > 0 && a <= 10) ? ++a : a/b;
c = a > b ? a : b;
Les Variables
locale (dite également automatique) est visible dans le block d’instructions dans
lequel elle à été déclaré et ce, à partir de sa déclaration. Elle est allouée et initialisée.
Elle est nettoyée et libérée automatiquement, lorsqu’on sort du block d’instructions
Définitions
• Lorsqu ’on déclare un pointeur on indique le type des variables sur les quelles il
pointe
• L ’adresse d ’une variable peut être obtenue grâce à l ’opérateur & suivi
du nom de la variable
int i=5;
printf("valeur de i = " , i);
printf("adresse de i = ",&i);
Résultats d ’exécution:
valeur de i = 5
adresse de i = 0x0012FF78
int i=5;
adresse
int * pi; 0x05 0x0012FF78
Pi=&i; 0x00 0x0012FF79
i
printf("valeur de i %d ", i); 0x00 0x0012FF7A
printf("adresse de i %d ", &i); 0x00 0x0012FF7B
printf ("valeur de p %d ", p);
Résultats d ’exécution:
valeur de i = 5 0x78
adresse de i = 0x0012FF78 pi 0xFF
valeur de pi = 0x0012FF78 0x12
0x00
Les Pointeurs
Incompatibilité de types
int i=5;
char * pc;
pc=&i;
! Erreurs
int i=5;
char * pc;
pc= ( char *) &i;
Les Pointeurs
Opérateur d ’indirection (*)
• Cet opérateur permet d ’accéder à la valeur de la variable pointée
• Si p contient l adresse de la variable v alors *p désigne la variable v elle même
int i=5;
int * pi=&i;
printf("valeur de i %d ", i);
printf("adresse de i %d ", &i);
printf("valeur de p %d ", p);
printf ("valeur pointé par p %d ", *p);
Résultats d ’exécution:
valeur de i = 5
adresse de i = 0x0012FF78
adresse de pi = 0x0012FF78
valeur de *pi =5
Les Pointeurs
Pointeur Void
• Les pointeurs void sont un type particulier de pointeur
• Ils peuvent pointer sur une variable de n’importe quel type
• On ne peut pas utiliser l ’opérateur d’indirection * sur un pointeur void. Il faut
d ’abord le convertir en un pointeur d ’un type donné.
Résultats d ’exécution:
valeur de pi avant l ’addition = 0x0012FF78
valeur de pi après l ’addition = 0x0012FF80
42 46 47 48 49 50 51 52 53 54 58
pi-- pi++
pi-2 pi+2
pi
Les Tableaux et Les Pointeurs
char lignes[100];
int *p_entier;
double fonc();
Les déclarations précédentes permettent de définir respectivement :
- un vecteur de 100 caractères,
- un pointeur d'entier,
- une fonction retournant un réel double précision.
Ces constructeurs peuvent se combiner entre eux, permettant ainsi de définir des
objets encore plus complexes.
char *chaines[100];
int mat[100][40];
char **argv;
Constructeurs homogène
Résultats d ’exécution:
0 10 20 30 40 50 60
• L’instruction telle que tab=p aurait provoqué une erreur à la compilation
Erreur de compilation : cannot convert from ‘ int * ' to ‘ int [7]'
Affichage des Tableaux et Pointeurs
• Dans le cas d’un tableau ou de pointeur de caractère, l’affichage produit la
chaîne de caractère commençant à la première case du tableau ou à la case
d’adresse indiquée par le pointeur et finissant par la première case qui contient
le caractère \0 (fin de la chaîne) (code ASCII=0
ASCII=0).
• Dans les autres cas, l’affichage produira l’adresse de la première case du
tableau ou la valeur du pointeur (adresse contenue dans l’adresse )
• Pour obtenir l’affichage de la valeur d’un pointeur de caractère (c’est à dire
l’adresse qu’il contient) il faut le convertir en pointeur void avant
const int MAX=7; const int MAX=7;
int t[MAX]={1,2,3}; int *p; p=t; char t[MAX]= " ABCDEF " ; char *p; p=t;
printf( " t=%d ", t ); printf( " p %d ",p); prinf(" t= " ,t ); printf(" p " , p);
prinf("&t= %d" ,&t); printf("&p =%d,&p) ; printf("&t= ", ,&t ); printf("&p = ",&p) ;
printf( "*t= %d" ,*t); printf(" *p = %d" printf( "*t= " , *t ) ; printf( " *p = ", p) ;
,*p) ; Printf( " (void*) p = " ,(void *) p);
Résultats d ’exécution: Résultats d ’exécution:
t=0x0012FF54 p=0x0012FF54 t=ABCDEF p=ABCDEF
&t=0x0012FF54 p=0x0012FF50 &t=0x0012FF54 p=0x0012FF6C
*t=1 p=1 *t=A p=A
(void*) p=0x0012FF54
Allocation dynamique
Normalement, une variable est créée automatiquement lors de sa déclaration.
Cela est faisable parce que les variables à créer ainsi que leurs tailles sont
connues au moment de la compilation (c'est le but des déclarations). Par
exemple, une ligne comme :
int tableau[10000];
signale au compilateur qu'une variable tableau de 10000 entiers doit être créée.
Le programme s'en chargera donc automatiquement lors de l'exécution.
1er situation :
Mais supposons que le programme gère une liste de clients. On ne peut pas
savoir à l'avance combien de clients seront entrés, le compilateur ne peut donc pas
faire la réservation de l'espace mémoire automatiquement. C'est au programmeur de le
faire. Cette réservation de mémoire (appelée encore allocation) doit être faite pendant
l'exécution du programme. La différence avec la déclaration de tableau précédente,
c'est que le nombre de clients et donc la quantité de mémoire à allouer, est variable. Il
faut donc faire ce qu'on appelle une allocation dynamique de mémoire.
Allocation dynamique
2ème situation :
Supposant qu’un programme ait besoin d’afficher 100 objets graphiques différents et
que ces objets sont très volumineux ( en espace mémoire).
Supposant aussi qu’un instant donné, le programme n’a besoin d’afficher simultanément
et au maximum que 10 objets parmi 100.
Supposant que la taille de la mémoire permet au maximum le stockage simultané de 30
objets graphiques
Allouer les 100 objets de façon statique est impossible puisque l’espace mémoire est
insuffisant.
En revanche, déclarer dynamiquement 10 objets est tout à fait possible et le programme
pourra alors s’exécuter sans problème pour 100 objets à des instants différentes.
Technique en C
Il existe deux principales fonctions C permettant de demander de la mémoire
au système d'exploitation et de la lui restituer. Elles utilisent toutes les deux les
pointeurs, parce qu'une variable allouée dynamiquement n'a pas d'identificateur, étant
donné qu'elle n'est pas déclarée. Les pointeurs utilisés par ces fonctions C n'ont pas de
type. On les référence donc avec des pointeurs non typés. Leur syntaxe est la suivante :
Allocation dynamique
• La mémoire peut ainsi être partagée de manière plus efficaces entre plusieurs
programmes.
• L’allocation dynamique sert les autres programmes mais elle peut aussi servir
le programme lui-même
La fonction malloc
• malloc demande l'allocation d'un bloc de mémoire de size octets consécutifs dans la
zone de mémoire du tas. Elle attend donc comme paramètre la taille de la zone de
mémoire à allouer et renvoie un pointeur non typé (void *).
•Si l'allocation réussit, malloc retourne un pointeur sur le début du bloc alloué.
•Si la place disponible est insuffisante ou si size vaut 0, malloc retourne NULL.
if ( ptr == NULL) {
printf (Allocation mémoire impossible \n");
exit(1);}
else {printf(“continuer le programme”);}
• Les fonctions d'allocation dynamique retournent des pointeurs sur des void. Il faut donc
opérer des conversions de types explicites pour utiliser ces zones mémoire en fonction du
type des données qui y seront mémorisées. Lorsqu'on alloue une variable typée, on doit
faire un transtypage du pointeur renvoyé par malloc en pointeur de ce type de variable.
• Pour utiliser les fonctions malloc, vous faite appel à la librairie stdlib.h
#include <stdlib.h>
La fonction calloc
Syntaxe :
#include <stdlib.h>
void *calloc (size_t nelem, size_t elsize);
Description :
La fonction calloc réserve un bloc de taille nelem x elsize octets consécutifs. Le
bloc alloué est initialisé à 0.
Valeur retournée :
• Si succès, calloc retourne un pointeur sur le début du bloc alloué.
• Si échec, calloc retourne NULL s'il n'y a plus assez de place ou si nelem ou elsize valent 0.
• Pour que l’allocation dynamique soit utile et efficace, il est impératif de libérer l’espace
réservé avec malloc, calloc, realloc dès que le programme n’en a plus besoin.
• Cet espace pourrait alors être réutilisé soit par le programme lui-même soit par d’autre
programmes
enum [nom]
{
enumerateur1,
enumerateur2,
enumerateur3,
...
enumerateurn
};
Les Variables: enum
Les constantes figurant dans les énumérations ont une valeur entière
affectée de façon automatique par le compilateur en partant de 0 par
défaut et avec une progression de 1.
Les valeurs initiales peuvent être forcées lors de la définition.
et dans le 2e :
Les constructeurs hétérogènes permettent de définir des objets renfermant des entités
de nature différente. Il en existe 3 :
• les structures,
• les champs de bits,
• les unions.
Les structures permettent de regrouper des objets dont les types peuvent être
différents.
Les structures
Les structures permettent de regrouper des objets dont les types peuvent être différents.
Déclaration d’une structure
Struct Nom_Structure{ Champs
ou
type_champ1 Nom_Champ1; données membres
type_champ2 Nom_Champ2;
type_champ3 Nom_Champ3;
} [var1, var2, ..., varM ];
struct Personne
{ Les objets regroupés sont les
membres ou composantes de la
int Age;
structure qui les contient.
char Sexe;
};
Les structures
•Les structures sont un exemple de définition de nouveaux types.
• Lors de la définition d'une structure des objets peuvent être déclarés et seront du type
associe a celle-ci.
• Ils peuvent être déclares ultérieurement mais dans ce cas la structure devra
nécessairement avoir un nom et struct nom est le nom du type associe.
• La taille d'une structure est au moins égale a la somme des tailles de ses membres du
fait d'éventuels alignements mémoires. L'operateur sizeof permet d'en connaître la taille.
Exemple
struct
{
char c;
unsigned int i;
float tab[10];
char *p;
} a, b
Les structures
.
Nom_Variable Nom_Champ; Pierre.Age = 18; personne *pierre;
Nom_pointeur Nom_Champ; Pierre.Sexe = 'M'; Pierre -> Age=18
Pierre -> sexe=‘M’
Tableau de structures
Un champ de bits est un ensemble de bits contigus a l'intérieur d'un même mot.
Syntaxe
struct [ nom ]
{
unsigned int champ1 : longueur1;
unsigned int champ2 : longueur2;
...
unsigned int champn : longueurn;
};
Les structures
Champs de bits
L’unité usuelle de compte en informatique est l’octet en général. Cependant, dans
certains cas, on doit accéder à certains bits individuellement dans une donnée.
Pour cela, on dispose d’opérateurs sur les types d’entier, comme le décalage à gauche
ou à droite (<< , >>), le « et » , le « ou » et le « ou exclusif » logiques (&, |, ^).
Cependant, lorsqu’on doit faire de nombreux accès aux bits séparés d’une donnée,
cela devient trop long, et désagréable, de spécifier une opération logique chaque fois.
Les structures à champs de bits permettent de résoudre ce problème.
Une telle structure est semblable à toute autre, mais derrière le nom des champs du
type int ou unsigned, on précise un nombre de 1 à 16 indiquant la taille en bits du
champ. Voici un exemple simple :
struct champbits {
Cette structure occupe seize bits unsigned basbas : 4;
(4 fois 4) en mémoire, soit la taille unsigned bashaut : 4;
d’un entier usuel unsigned hautbas : 4;
int hauthaut : 4; };
Les champs de bits sont utilisés comme des entiers ordinaires ; lors d’une affectation,
les bits excédentaires sont supprimés, les bits manquants sont nuls. Par exemple, si
l’on écrit : champbits cb; int i = 30 // 30 == 0x1E
cb.bashaut = i; // met 0xF == 15 dans cb.bashaut
i = cb.bashaut; // maintenant i == 15
Les structures
Les champs de bits sont utilisés comme des entiers ordinaires ; lors d’une
affectation, les bits excédentaires sont supprimés, les bits manquants sont nuls. Par
exemple, si l’on écrit :
•Un champ peut ne pas avoir de nom. Sa longueur indique alors le nombre de bits que l'on
veut ignorer.
•Une longueur égale a 0 permet de forcer l'alignement sur le début du mot mémoire
suivant.
Les structures
Exemple
struct zone
{
unsigned int a: 8;
unsigned int : 0;
unsigned int b: 8;
unsigned int : 8;
unsigned int c: 16;
};
struct zone z1, *z2;
Remarques
• Les champs de bits sont évalués de gauche a droite sur certaines machines et de
droite a gauche sur d'autres. Ce type de données n'est donc pas portable.
Remarques
• A la définition d'une union est associe un nouveau type : union nom lorsque nom a
été précisé à la définition.
•L’union groupe des données, comme les structures, mais au lieu de se trouver
placées les unes derrière les autres en mémoire, elles se trouvent toutes à la même
adresse.
• Entrées / Sorties ?
• Difficilement utilisable hors de son environnement
• Critères de validation
• Temporelle
• Énergétique
• Empreinte mémoire
• …
Les systèmes embraqués
• Processeur
• Mémoire
• Périphériques
• Bus de communication
• Entrées / Sorties
Registres 'utilisateur‘
(le registre UCSRnA du micro. ATmega128)
• 8 / 16 / 32 bits
• À une adresse mémoire particulière
• Permettent de stocker les données sur lesquelles travailler (∼ variables)
• Sont utilisés par les instructions de calcul assembleurs
adresse physique
Bus (communication)
Microprocesseur
Bus (communication)
Généralités sur les Interruption
● Une interruption est un arrêt temporaire de l'exécution normale du
programme principal par le microprocesseur afin d'exécuter un autre
programme (appelé routine d'interruption ou programme d'interruption).
Ce programme d'interruption va permettre de gérer l'évènement
qui a provoqué cette interruption.
#include <avr/interrupt.h>
// 16-bit variables x et y
unsigned short x, y;
// interrupt change la value de x
ISR(XXX_vect) { x = 0x3333; }
int main() {
// valeur donnée de x
x = 0x1111;
// interruption global
sei();
// donne la valeur de x à y
y = x;
}
Interruptions : Exemple
clignoter une LED dans chaque demie seconde
Pour Arduino ou pour le MSP430
#include <avr/io.h> la librairie définition de constantes d’accès aisé aux entrées et sorties
#include <util/delay.h> ajoute des fonctions permettant de mettre une execution en pause,
comme _delay_ms qui prend en argument le nombre de seconde