Programmation C++

Architecture d’un processeur

Architecture von Neumann

Le mathématicien John von Neumann a élaboré cette architecture en juin 1945. Elle utilise une structure de stockage unique pour conserver à la fois les instructions et les données.

Architecture Harvard

L’architecture de type Harvard est une conception des processeurs qui sépare physiquement la mémoire de données et la mémoire programme. L’accès à chacune des deux mémoires s’effectue via deux bus distincts.

Les Bus

Un bus informatique est un dispositif de transmission de données partagé. Dans un processeur Par exemple dans un ordinateur, il interconnecte le processeur, la mémoire centrale et les contrôleurs de périphériques.

Le bus de données est l’ensemble des conducteurs électriques chargé du transfert en parallèle des données et des instructions des programmes.

Le bus d'adresse permet de désigner à chaque instant la case mémoire et/ou le périphérique auquel le contrôleur veut faire appel

Le bus de contrôle permet d'effectuer des requêtes sur le bus et de contrôler le type de l'opération

Exercice : analyse de l’ATMEGA328P (Arduino Uno)

Combien de bits contient le bus de données ?

Entourer sur le diagramme ci-dessus l’unité arithmétique et logique

Repérer sur le diagramme ci-dessus la mémoire où est stocké le programme

Repérer sur le diagramme ci-dessus la mémoire où sont stockées les données.

Quel est le type architectural de ce processeur AVR ?

Sachant que le bus d’adresse compte 16 bits, on représente cette mémoire par le composant suivant :

On souhaite sauvegarder les valeurs 32, 20, 52, 33 et 300 aux adresses 0, 1, 2, 3, 4. Compléter le tableau représentant l’organisation de cette mémoire 

  • Quelle est la valeur de l’adresse maximum M ?

Les types des variables en C++

Les variables sont utilisées pour stocker temporairement une valeur ou un état à l'intérieur d'un programme. En C++ elles doivent être déclarées avant l'initialisation. Lors de la déclaration, on peut l'initialiser ou non :

1
int Variable1;
2
int Variable2 = 0;     // Initialisation

L'opérateur = réalise une affectation. Dans l'exemple ci-dessus Variable2 est affectée à la valeur 0.

Lors de la déclaration, le type de variable doit être spécifié. Il existe différents types de variables identifiés par un mot-clé dont les principaux sont :

Le tableau montre les différents type et l’espace qu’ils occupent dépend de l’architecture (8, 16, 32, ou 64 bits). Ici pour une architecture 64 bits :

Types

Nombre d’octet

bool

4

Deux états possibles : True/False

char

1

-127 <N < +127.

unsigned char

1

0 < N < 255

byte

1

0 < N < 255

int

4

−2 147 483 648 <N< 2 147 483 647

unsigned int

4

0 < N < 4 294 967 295

long

8

unsigned long

8

float

4

double

8

Le tableau montre les différents type et l’espace qu’ils occupent pour une carte arduino UNO (processeur ATMEGA328P  de 8 bits) :

Types

Nombre de bits

boolean

8 bits

Deux états possibles : True/False

char

8 bits

-127 <N < +127.

unsigned char

8 bits

0 < N < 255

byte

8 bits

0 < N < 255

int

16 bits

-32 768 < N < 32767

unsigned int

16 bits

0 < N < 65535

word

16 bit

0 < N < 65535

long

32 bits

-2 147 483 648 < N < 2 147 483 647

unsigned long

32 bits

0 < N < 4 294 967 295

float

16 bits

-3,4028235 E+38 < N < +3,4028235 E+38

double

16 bits

idem

Le programmeur en pratique utilisera principalement int, float et char et si les données sont plus étendues il tentera d'autre types plus étendus.

Les constantes

Il peut être utile de déclarer des constantes pour améliorer la lisibilité et l'évolutivité d'un programme.

1
const int LED = 3 // La LED est sur la broche 3

Cette déclaration garantit que la variable LED ne changera pas de valeur.

Les structures de contrôle :

Les structures de contrôle sont des blocs d'instructions qui s'exécutent en fonction du respect d'un certain nombre de conditions. En C++ le if réalise un test sur une variable ou le résultat d'une opération. Si ce test est vérifié on exécute un code particulier sinon on passe au code suivant. En C++, le if s'écrit :

1
if(Variable> 50) // Test ? si variable > 50 
2
{    // alors on fait le 
3
    //  Traitement entre accolades
4
}

Dans l'exemple ci-dessus, le traitement est effectué si la variable est supérieure à 50. Les accolades peuvent être omises. Si c'est le cas seule l'instruction qui suivra sera exécutée de manière conditionnelle. L'exemple suivant montre des écritures identiques :

Pour tester deux variables il existe en C++ un nombre important d'opérateurs de comparaison:

  • x == y : x est égale à y

  • x != y : x n'est pas égal à y

  • x < y  :x est inférieur à y

  • x > y  : x est supérieur à y

  • x <= y  : x est inférieur ou égal à y

  • x >= y : x est supérieur ou égal à y

la combinaison if/else est également possible : elle permet la programmation de deux traitements différents selon un test :

1
if(Variable>50)
2
{
3
  //Traitement 1
4
}
5
else
6
{
7
  //Traitment 2
8
}

l est possible de rajouter autant de branches que l'on veut de cette manière.

1
if(Variable>50)
2
{
3
  //Traitement 1
4
}
5
else if(Variable>100)
6
{
7
  //Traitment 2
8
}
9
else
10
{
11
  // Traitement 3
12
}

Attention : == et = !

Ne pas confondre l'opérateur == qui compare si deux variables sont identiques et l'opérateur = d'affectation.

x=4 ; // la nouvelle valeur de x est 4 (NB : en Pascal : x  := 4 ;)

if (x==4) ; // Test si x est égal à 4

Boucles

La boucle while permet d'exécuter des instructions jusqu'à ce qu'une certaine expression (à l'intérieur de la parenthèse) devienne fausse. Autrement dit, tant que le test est vérifié, on répète les instructions entre accolade :

La boucle while permet d'exécuter des instructions jusqu'à ce qu'une certaine expression (à l'intérieur de la parenthèse) devienne fausse. Autrement dit, tant que le test est vérifié, on répète les instructions entre accolade :

1
while(Var < 50)//
2
{
3
  // Traitement
4
}

La boucle for

Les tableaux

Wikipedia sur les tableaux :" Les tableaux sont des structures de données constituées d'un certain nombre d'éléments de même type. On peut accéder directement à un élément du tableau en indiquant son indice entre crochets (indice de 0 à nombre_d_éléments-1)."

Synthaxe :

Sémantique

identificateur est donc un tableau de taille éléments de type type. taille est obligatoirement une valeur constante. La taille du tableau est donc figée une fois pour toute et ne peut pas être modifiée en cours d'exécution.

Pour désigner la i-ième case de tableau, on écrit

identificateur[i]

où i est un entier quelconque. Les cases sont numérotées à partir de 0 : les valeurs possibles de i vont donc de 0 à taille-1.

Les fonctions

Une fonction (également désignée sous le nom de procédure ou de sous-routine) est un bloc d'instructions que l'on peut appeler à tout endroit du programme. La bibliothèque Arduino est constituée d'un certain nombre de fonctions, par exemple analogRead(), digitalWrite() ou delay(). Il est possible de déclarer ses propres fonctions par exemple :

Tout ce qui se trouve entre accolades fait parti de la fonction clignote. Pour exécuter cette fonction, il suffit de taper la commande clignote();

Paramètres d'entrée

On peut faire intervenir un ou des paramètres en entrée dans une fonction :

La fonction clignote comporte 2 paramètres d'entrée : broche et vitesse. Le types des paramètres d'entrée doivent être définis, ici se sont des int.

Dans ce cas, on peut moduler leurs valeurs depuis la commande qui l'appelle :

Paramètres de sortie

On peut faire intervenir un paramètres en sortie également dans une fonction :

La fonction addition comporte 2 paramètres d'entrée a et b qui sont des entiers (int). r représente le résultat de la fonction addition. Sa valeur est retournée par la fonction.

L'utilisation dans un programme peut être ainsi :

1
int s = addition(3,2); 

Le type void en C et en C++ est l'équivalent de l'ensemble vide. Lorsqu'une fonction ne renvoie aucun argument (pas de return) alors on déclare un type void comme paramètre de sortie, pour dire qu'elle ne renvoie rien. C'est le cas des fonction loop et setup() :

Portée d'une variable (globale ou locale)

On appelle variable globale, une variable qui peut être vue dans toutes les fonctions du programme. Les variables locales elles, ne sont visibles que dans la fonction où elles sont déclarées. Dans l'environnement Arduino, toutes variables déclarées en dehors des fonctions (loop (), setup(), …) sont des variables globales.

1
int MaVariableGlobale;  // Toutes les variables voient  MaVariable
2
3
void setup()
4
{
5
  // ...
6
}
7
void loop()
8
{
9
  int i;    // i n'est visible que dans la fonction loop
10
  float f;  // f n'est visible que dans la fonction loop
11
  // ...
12
13
  for (int j = 0; j <100; j++){
14
  // j n'est visible que dans la boucle for
15
  }
16
}

Passage par référence

Lorsque l'on souhaite modifier une valeur d'une variable en entrée :

1
/////////////////////////////////////////////////////
2
// Cette fonction met la valeur de n a 0
3
void annule(int &n)
4
{
5
    n=0;
6
}
7

Lors de son appel la variable entre parenthèse sera =0.