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.

L’unité arithmétique et logique (UAL ou ALU en anglais) ou unité de traitement : son rôle est d’effectuer les opérations de base ;
L’unité de contrôle, chargée du « déroulement » des opérations.
La mémoire contient à la fois les données et le programme qui indiquera à l’unité de contrôle quels sont les calculs à faire sur ces données. Celle-ci se décompose entre mémoire volatile (programmes et données en cours de fonctionnement) et mémoire permanente (programmes et données de base de la machine) ;
Les dispositifs d’entrée-sortie permettent de communiquer avec le monde extérieur.
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.

Avec deux bus distincts, l’architecture dite de Harvard permet de transférer simultanément les données et les instructions à exécuter. Ainsi, l’unité de traitement aura accès simultanément à l’instruction et aux données associées.
Cette architecture peut se montrer plus rapide à technologie identique que l'architecture de von Neumann ; le gain en performance s'obtient cependant au prix d'une complexité accrue de structure.
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 :

a0-15 : bus d’adresse
D0-7 : bus de donnée
EN, R/W : bus de contrôle
CLK : horloge
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 :
int Variable1;
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.
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 :
if(Variable> 50) // Test ? si variable > 50
{ // alors on fait le
// Traitement entre accolades
}
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 :
if(Variable>50)
{
//Traitement 1
}
else
{
//Traitment 2
}
l est possible de rajouter autant de branches que l'on veut de cette manière.
if(Variable>50)
{
//Traitement 1
}
else if(Variable>100)
{
//Traitment 2
}
else
{
// Traitement 3
}
/home/paul/NextcloudEdu/Progression STI2D/Site_web/alogo_if3.svg
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 :
while(Var < 50)//
{
// Traitement
}
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 :
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.
int MaVariableGlobale; // Toutes les variables voient MaVariable
void setup()
{
// ...
}
void loop()
{
int i; // i n'est visible que dans la fonction loop
float f; // f n'est visible que dans la fonction loop
// ...
for (int j = 0; j <100; j++){
// j n'est visible que dans la boucle for
}
}

Passage par référence
Lorsque l'on souhaite modifier une valeur d'une variable en entrée :
/////////////////////////////////////////////////////
// Cette fonction met la valeur de n a 0
void annule(int &n)
{
n=0;
}
Lors de son appel la variable entre parenthèse sera =0.