Objectifs
- Comprendre qu’est ce qu’un pointeur
- Savoir manipuler les registres du µC & la mémoire
- Savoir utiliser les pointeurs scalaires
- Savoir utiliser les pointeurs et les tableaux
- Mise en pratique sur carte Arduino
Importance
- Notion de la valeur et l’adresse (Arduino Mega)
- Accès direct aux registres du µC
- Création des alias: Une adresse pour plusieurs variables
- Création des fonctions multi-retours
- Voir les pages 399-403 (Datasheet)
- Etc.
Comment déclarer un pointeur scalaire (valeur unique) ?
byte *p1_b; byte *p2_b;
int *p1_i; int *p2_i;
long *p1_l; long *p2_l;
float *p1_f; byte *p2_f;
Comment initialiser un pointeur ?
- Affectation d’une adresse mémoire constante OU bien
- L’adresse d’une variable de même type (Opérateur « & »)
- Un pointeur vide: NULL: p1_b=NULL;
Exemples
int *p; int valP;
p= &valP; // Adresse d'une variable
p= 0x00ff; // Adresse constante
Comment savoir la taille d’une variable ?
- => Anticiper la location mémoire et l’adressage
- Voir le programme
Opérations sur les pointeurs = Mêmes opérations sur les variables
byte *p_b;
int *p_i ;
double *p_d;
p_b=p_b+1; // Avance d'un octet en mémoire
p_i=p_i+1; // Avance de "2" octets en mémoire
p_d=p_d+1; // Avance de "8" octets en mémoire
p_d=p_d+10; // Avance de 8x10 octets en mémoire !!!!!
p_d=p_d+n; // Avance e 8xn octets
Les pointeurs et les tableaux
- tab ou tab[0] est un pointeur contant sur le premier élément du tableau
- Si je connais l’adresse du premier élément et son type je peux ensuite
- accéder à l’ensemble des éléments du tableau!
int tab[10], *ptab;
ptab=&tab[0]; // je pointe sur le premier élément
Exemple
for(int i=0;i<10;i++)
{
// Init 1
tab[i]=10;
// Equivalent à
*(ptab+i)=10; // Contenu de l'adresse ptab+i
}
Tableau & la mémoire (optimisation de la mémoire)
- byte tab[10]; // 10*1=10 octets
- int tab[10]; // 10*2=20 octets
- double tab[10] // 10*8=80 octets
- => Rapport de 1 à 8, il faut tenir en compte le type de données
- Avant d’effectuer la location mémoire.
Plusieurs tableaux ayant la même adresse
- =>Une seule initialisation est suffisante pour l’ensemble des tableaux
byte tab[10], *tab1, *tab2, *tab3;
tab1=&tab[0];
tab2=&tab[0];
tab3=tab;
Exemple 1: taille & utilisation
byte a, *pa;
unsigned char *MyPORTA;
word AddPORTA,Adda;
void setup()
{
// Init port série
Serial.begin(9600);
// Init pointeurs
pa=&a;
MyPORTA=&OCR3CH;
}
void loop()
{
// Affichage de la taille des variables
Serial.println("Tailles");
Serial.println(sizeof(a));
Serial.println(sizeof(PORTA));
Serial.println("----------");
// Init des valeurs des pointeurs
*pa=10; PORTA=40;
AddPORTA=MyPORTA; // Ou bien AdPORTA=MyPORTA;
Adda=(word)pa;
// Affichage des valeurs des variables
Serial.println("Valeurs");
Serial.println(a);
Serial.println(PORTA);
Serial.println("----------");
// Affichage des adresses
Serial.println("Adresses");
Serial.println(Adda);
Serial.println(AddPORTA);
Serial.println("----------");
// délai de la boucle
delay(2000);
}
Exemple 2: les tableaux
byte tab[10], *tab1, *tab2;
void setup()
{
// Init port série
Serial.begin(9600);
// Init pointeurs
tab1=&tab[0];
tab2=tab;
// Init tab
for(int i=0;i<10;i++)
tab[i]=i;
}
void loop()
{
// Affichage tab1
for (int i=0;i<10;i++)
{
Serial.print(*(tab1+i));
Serial.print(" ");
}
Serial.print("\n");
for (int i=0;i<10;i++)
{
Serial.print(*(tab2+i));
Serial.print(" ");
}
Serial.print("\n \n");
// Délai
delay(1000);
}