À 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. } |
Code arduino : | Sélectionner tout |
1 2 3 4 5 | digitalWrite(8, LOW); digitalWrite(9, HIGH); // ... digitalWrite(8, HIGH); digitalWrite(9, LOW); |
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);
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) |
Pour plus de détails Pico C SDK : hardware_gpio