GPIO
Le STM32F412ZG possède jusqu’à 114 entrées et sorties de type
GPIO (General Purpose Input/Output) regroupées sur 7 ports (A
, B
, C
, D
,
E
, F
, G
et H
). Les ports A
à G
possèdent 16 entrées/sorties et le
port H
n’en possède que 2.
Le STM32F412ZG fonctionne en 3.3V et les broches des GPIOs configurées en sortie donnent soit 0V, soit 3.3V. Les broches configurées en entrées sont capables de supporter des tensions jusqu’à 5V. On dit que ces broches sont “5V tolerant” et c’est très pratique pour lire des signaux provenant de périphériques qui fonctionnent avec 5V.
La figure ci-dessous illustre les composants et le fonctionnement d’une broche GPIO tolérante à 5V :
Les broches du GPIO peuvent également être configurées pour lire des tensions analogiques, mais nous n’utilisons pas cette fonctionnalité dans ce cours. Pour plus d’information à ce sujet, référez-vous à la documentation du microcontrôleur STM32F412ZG.
Utilisation avec Mbed OS
Pour configurer et programmer les broches du GPIO avec Mbed OS, nous
utilisons principalement les classes DigitalIn
et DigitalOut
. Notez que Mbed OS est programmé en C++ et offre une interface orientée objet.
Note
Dans Mbed OS, il y a aussi la classe DigitalInOut
qui
permet de lire et d’écrire sur une broche et la classe PwmOut
qui permet
de contrôler une broche en PWM, mais nous ne les utiliserons pas ici.
DigitalOut
Pour utiliser une broche en sortie, il suffit de créer une instance de la classe
DigitalOut
. Par exemple :
DigitalOut led(PE_0);
Avec Mbed OS, vous n’avez pas besoin de spécifier le port de la
broche séparément. L’argument PE_0
signifie que la broche est située sur le
port E
et que son numéro est 0. Vous n’avez pas non plus besoin de vous
soucier de la configuration du “clock” (rcc) du GPIO; le constructeur de la
classe DigitalOut
le fait automatiquement.
Le code ci-dessous est celui du constructeur de DigitalOut
et on voit qu’il
initialise l’attribut gpio
à la ligne 9 et qu’ensuite, il appelle la fonction
gpio_init_out
à la ligne 11:
https://github.com/ARMmbed/mbed-os/blob/mbed-os-6.9.0/drivers/include/drivers/DigitalOut.h | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Le type gpio_t
est spécifique à une cible donnée. Pour les microcontrôleurs
de STM, il est défini comme suit :
https://github.com/ARMmbed/mbed-os/blob/mbed-os-6.9.0/targets/TARGET_STM/gpio_object.h | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
La fonction gpio_init_out
est dans la partie “HAL” (Hardware Abstraction
Layer) de Mbed OS :
https://github.com/ARMmbed/mbed-os/blob/mbed-os-6.9.0/hal/source/mbed_gpio.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
- A la ligne 3,
gpio_init_out
appellegpio_init_out_ex
avec la valeur0
. - A la ligne 8,
gpio_init_out_ex
appelle_gpio_init_out
- A la ligne 16,
_gpio_init_out
appellegpio_init
- Ensuite
_gpio_init_out
configure le port en sortie.
La fonction gpio_init
est, elle aussi, dépendante de la cible. Pour notre
microcontrôleur, elle est définie comme suit :
https://github.com/ARMmbed/mbed-os/blob/mbed-os-6.9.0/targets/TARGET_STM/gpio_api.c | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
À la ligne 11, on voit la commande pour activer le clock du GPIO.
On observe donc une différence importante entre la programmation en C avec une librairie de bas niveau de type STM32CubeF4 où le programmeur doit gérer le hardware avec peu d’abstraction et un système comme Mbed OS en C++ où le travail est fait pour nous dans le code de la classe. De plus, avec une telle approche, on s’assure également que l’état d’un objet est en tout temps cohérent.
Si vous souhaitez configurer la valeur initiale de la broche de sortie (et c’est très recommandé de le faire), vous pouvez passer un deuxième argument au constructeur. Par exemple :
DigitalOut led(PE_0, 1);
Vous pouvez ensuite manipuler la broche en sortie avec la méthode write()
. Par
exemple :
led.write(0);
ou
led.write(1);
Note
Écrire un 1
sur une broche à laquelle est connecté une LED
ne signifie pas forcément que la LED va s’allumer car ca dépend de la
manière dont la LED est connectée au micro-contrôleur. La bonne pratique
consiste à utiliser des constantes à la place de des valeurs numériques. Le
premier travail pratique vous donne plus de détails sur cette pratique.
Mais comme Mbed OS profite des avantages de C++ pour simplifier l’interface, vous pouvez également manipuler les sorties avec une simple assignation :
led = 0; // same as led.write(0);
ou
led = 1; // same as led.write(1);
Cette fonctionnalité est possible grâce à la surcharge d’opérateurs en C++.
Les opérateurs surchargés sont les suivants :
DigitalOut &operator= (int value);
DigitalOut &operator= (DigitalOut &rhs);
operator int();
Les deux premiers opérateurs sont des surcharges de l’opérateur d’affectation et
permettent d’assigner un entier ou la valeur d’un autre objet de type
DigitalOut
à l’objet courant. Le troisième opérateur (operator int()
) permet
de consulter la valeur du DigitalOut
en tant qu’entier.
Ces opérateurs permettent de facilement inverser la valeur de la broche en
utilisant l’opérateur logique “NOT” (!
) :
led = !led;
Notez que dans l’exemple ci-dessus, l’opérateur !
agit sur des entiers et non
sur des objets de type DigitalOut
.
Note
En Java, l’opérateur logique !
ne peut être utilisé qu’avec
un opérande de type boolean
. En C/C++, cet opérateur est également défini
pour un opérande de type
entier.
Pour plus d’information concernant la classe DigitalOut
, consultez la
documentation de Mbed OS.
DigitalIn
Pour utiliser une broche en entrée, nous créons une instance de la classe
DigitalIn
. Par exemple :
DigitalIn button(PA_0);
Normalement, nous configurons une broche d’entrée en spécifiant une résistance de pull-up ou de pull-down :
DigitalIn button(PA_0, PullDown);
Pour lire l’état de la broche, on peut utiliser la méthode read()
:
int state = button.read();
ou alors, utiliser la surcharge de operator int()
:
int state = button;
DigitalIn
, consultez la
documentation de Mbed OS.