IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Raspberry Pi Pico - Après le 'Hello World', apprendre à piloter simultanément plusieurs GPIO,
Un billet blog de f-leb

Le , par f-leb

0PARTAGES

Après avoir découvert la carte Raspberry Pi Pico et réalisé votre premier "Hello World !" (un blink, quoi !) avec le SDK C/C++ (voir le billet précédent), je vous propose de découvrir des fonctions plus avancées pour piloter simultanément plusieurs broches GPIO.

À titre de démonstration, je vous présenterai une petite application de pilotage d'un afficheur 7-segments à cathode commune :


Parenthèse... Arduino : avec le « langage Arduino », si l'on considère une broche configurée en sortie avec pinMode(pin, OUTPUT), vous passerez par un digitalWrite(pin, HIGH) ou digitalWrite(pin, LOW) pour mettre la broche (pin) respectivement à l'état haut ou à l'état bas. Mais si vous devez piloter plusieurs broches, vous ne pouvez le faire que séquentiellement, broche par broche, en multipliant les pinMode() et digitalWrite().
De façon plus astucieuse, vous parcourrez un tableau dans une boucle for, par exemple :
Code arduino : Sélectionner tout
1
2
3
4
5
6
int pins[] = {2, 3, 4, 5, 6, 7, 8, 9}; // tableau des broches 
// ... 
for (int i=0; i<8; i++) { 
  pinMode(pins[i], OUTPUT); // les broches du tableau configurées en sortie numérique... 
  digitalWrite(pins[i], HIGH); // ... initialement à l'état haut. 
}
Mais que se passe-t-il lorsque vous devez synchroniser deux signaux qui basculent d'état en écrivant :
Code arduino : Sélectionner tout
1
2
3
4
5
digitalWrite(8, LOW); 
digitalWrite(9, HIGH); 
// ... 
digitalWrite(8, HIGH); 
digitalWrite(9, LOW);
Quand la broche 8 passe à l'état haut, 9 doit passer à l'état bas... Mais dans des instructions séparées, il y aura une période de chevauchement (négligeable ?) où 8 et 9 sont tous les deux à l'état haut ! Cela n'a aucune importance en pratique si vous jouez avec des LED, mais en est-il pareil si vous manipulez les signaux de ponts pour contrôler des moteurs ?

Note : si l'API Arduino ne permet pas d'agir sur plusieurs broches simultanément, vous pouvez toujours le faire en attaquant directement les registres des ports d'E/S du microcontrôleur. Consultez le manuel pour l'ATmega328P de l'Arduino Uno.

... fin de la parenthèse.

Avec le SDK C/C++ de la Raspberry Pi Pico, vous pouvez agir simultanément sur plusieurs broches de la carte, en définissant un masque.
Sur la Raspberry Pi Pico, vous pouvez jouer avec 30 broches GPIO numérotées GP0 à GP29.
Le masque est donc une valeur entière définie sur 32 bits (uint32_t) où le bit 0 de poids faible concerne la broche GP0, le bit 1 pour la broche GP1, le bit 2 pour la broche GP2, etc. Tout simplement.

Si vous voulez par exemple attaquer les broches GP1, GP4 et GP8, on définira le masque :
Code C : Sélectionner tout
1
2
// broches GP1, GP4 et GP8 
uint32_t mask = (1 << 1) | (1 << 4) | (1 << 8);

Pour initialiser les broches, on écrira alors :
Code C : Sélectionner tout
gpio_init_mask(mask);

et pour les configurer toutes en sorties numériques :
Code C : Sélectionner tout
gpio_set_dir_out_masked(mask); // GP1, GP4 et GP8 = output

ou toutes en entrées numériques :
Code C : Sélectionner tout
gpio_set_dir_in_masked(mask); // GP1, GP4 et GP8 = input

En renseignant une valeur supplémentaire, on peut même choisir entre certaines broches configurées en entrées et d'autres en sorties :
Code C : Sélectionner tout
gpio_set_dir_masked(mask, value);
value est aussi un entier 32 bits, avec le bit de la broche à 0 (input) ou à 1 (output).

Pour des sorties numériques, vous pouvez mettre toutes les broches définies dans le masque à l'état haut (set) ou à l'état bas (clr) en une seule opération :
Code C : Sélectionner tout
1
2
gpio_set_mask(mask); // GP1, GP4 et GP8 à l'état haut  
gpio_clr_mask(mask); // GP1, GP4 et GP8 à l'état bas

Mais on peut aussi définir certaines broches à l'état haut et d'autres à l'état bas, toujours simultanément. Par exemple :
Code C : Sélectionner tout
1
2
3
4
5
6
uint32_t mask =  (1 << 1) | (1 << 4) | (1 << 8); // broches GP1, GP4 et GP8 
gpio_init_mask(mask); 
gpio_set_dir_out_masked(mask); // GP1, GP4 et GP8 = output 
  
uint32_t value = (1 << 1) | (1 << 4);   
gpio_put_masked(mask, value); // GP1 et GP4 à l'état haut, GP8 à l'état bas.

Ainsi, pour s'assurer que les états de deux signaux basculent simultanément, on écrira :
Code C : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint32_t mask =  (1 << 4) | (1 << 8); // broches GP4 et GP8 
gpio_init_mask(mask); 
gpio_set_dir_out_masked(mask); // GP4 et GP8 = output 
  
uint32_t state1 = (1 << 4); 
uint32_t state2 = (1 << 8); 
  
gpio_put_masked(mask, state1); // GP4=1, GP8=0 
  
// ...autre action 
  
gpio_put_masked(mask, state2); // GP4=0, GP8=1, les signaux sur GP4 et GP8 basculent simultanément 
  
// ...

______________________________
Dans l'exemple d'application ci-dessous, on montre comment piloter un afficheur 7-segments (à cathode commune) avec un compteur qui évolue entre 0 et 9 (voir photo du montage plus haut).

Les anodes des segments (7 segments + point décimal) sont reliées aux broches GP08 à GP15 (n'oubliez pas les résistances 330Ω) et seront donc pilotées simultanément grâce à gpio_put_masked.

Fichier source digit7seg.c :
Code C : Sélectionner tout
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/** 
 * Démonstration pilotage digit 7-segments 
 */ 
  
#include "pico/stdlib.h" 
  
int main() {     
    /* 
     * seg a  --> GP15 
     * seg b  --> GP14 
     * seg c  --> GP13 
     * seg d  --> GP12 
     * seg e  --> GP11 
     * seg f  --> GP10 
     * seg g  --> GP09 
     * seg dp --> GP08  
     */ 
  
    //                            abcdefgp 
    const uint8_t digit[] = {   0b11111100, // 0 
                                0b01100000, // 1 
                                0b11011010, // 2 
                                0b11110010, // 3 
                                0b01100110, // 4 
                                0b10110110, // 5 
                                0b10111110, // 6 
                                0b11100000, // 7 
                                0b11111110, // 8 
                                0b11110110  // 9 
                            };       
  
    const uint32_t mask = 0x0000FF00; // masque GP08 à GP15 
    gpio_init_mask(mask); // GPO8 à GP15 = I/O 
    gpio_set_dir_out_masked(mask); // GPIO8 à GPI15 = sorties 
  
    while (true) { 
        for (uint8_t counter=0; counter<10; counter++) { // compteur 0 à 9 
            uint32_t value = digit[counter] << 8; 
            gpio_put_masked(mask, value); 
            sleep_ms(1000); 
        } 
    } 
  
}

Fichier CMakeLists.txt :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cmake_minimum_required(VERSION 3.13) 
 
# initialize the SDK based on PICO_SDK_PATH 
# note: this must happen before project() 
include(pico_sdk_import.cmake) 
 
project(digit7seg C CXX ASM)  
 
set(CMAKE_C_STANDARD 11)   
set(CMAKE_CXX_STANDARD 17)  
 
# initialize the Raspberry Pi Pico SDK 
pico_sdk_init() 
 
# rest of your project 
add_executable(digit7seg 
    digit7seg.c 
) 
 
# Add pico_stdlib library which aggregates commonly used features 
target_link_libraries(digit7seg pico_stdlib) 
 
# create map/bin/hex/uf2 file in addition to ELF. 
pico_add_extra_outputs(digit7seg)
Voir le billet précédent pour la construction du projet.

Pour plus de détails Pico C SDK : hardware_gpio

Une erreur dans cette actualité ? Signalez-nous-la !