🕒 : 3 h maximum
Prérequis:
- cours Raspberry Pi
- Avoir fait RPI_0 et disposer d’un Raspberry PI OS64 avec ssh
- TP RPI_0 et RPI_1 effectués
- cours langage C , Année 1 de la formation
- cours libgpiod
- cours SIGINT ctrl c
- cours présentation de la sonde SALEAE vu en co enseignement Physique/Info
But:
- Mettre en oeuvre un code pilotant les GPIO en langage C, pour les projets
- Pull up, pull down
- interruption SIGINT
Répertoire du travail:
~/Works/RPI_3
Installation sur RPI (normalement déjà fait)
sudo apt update
sudo apt install gpiod libgpiod-dev libgpiod-doc
Sortie GPIO17 et LED ROUGE
on reprend le même montage, on ne change pas une équipe qui gagne!

répertoire: blink , code: blink.c
#include <stdio.h>
#include <unistd.h>
#include <gpiod.h>
int main() {
const char *chipname = "gpiochip0";
int led_pin = 17; // BCM17
int delay_ms = 500; // 0.5 seconde
// Configuration minimale
struct gpiod_chip *chip = gpiod_chip_open_by_name(chipname);
struct gpiod_line *led = gpiod_chip_get_line(chip, led_pin);
gpiod_line_request_output(led, "led_blink", 0);
printf("Clignotement LED GPIO17 (Ctrl+C pour arrêter)\n");
// Boucle principale simplifiée
while (1) {
gpiod_line_set_value(led, 1); // Allumer
usleep(delay_ms * 1000);
gpiod_line_set_value(led, 0); // Éteindre
usleep(delay_ms * 1000);
}
// Nettoyage (jamais atteint à cause de la boucle infinie)
gpiod_line_release(led);
gpiod_chip_close(chip);
return 0;
}
Saisir le code et compiler et tester
attention : -lgpiod est l’option correcte pour lier (linker) votre programme C avec la bibliothèque libgpiod.
gcc -o blink blink.c -lgpiod
Utlisation du debugger gdb
gcc -o blink blink.c -lgpiod -g
A quoi sert -g ?
bruno@rpi364:~/Works/RPI_2/langageC/blink $ gcc blink.c -o blink -lgpiod -g
bruno@rpi364:~/Works/RPI_2/langageC/blink $ gdb blink
GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from blink...
(gdb) l
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <gpiod.h>
4
5 int main() {
6 const char *chipname = "gpiochip0";
7 int led_pin = 17; // BCM17
8 int delay_ms = 500; // 0.5 seconde
9
10 // Configuration minimale
(gdb)
[albert] 0:bash 1:bash 2:bash 3:bash 4:bash
Proposer un moyen avec gdb de voir s’allumer la led , et s’éteindre sous votre contrôle et vérifier les structures concernant ce programme.
On va rajouter une LED sur
LED qui alterne
Répertoire: alterne , code: alterne.c
Présentation:
on va garder la led rouge qui est sur GPIO17, on va ajouter une LED Verte sur GPIO22 avec sa résistance en série !
Proposer un schéma
Proposer un code
Vous devez savoir réaliser cela . La solution est donnée si besoin
Solution: alterne.c
#include <gpiod.h>
#include <unistd.h>
#include <stdio.h>
#define GPIO_LED1 17 // BCM17 (broche physique 11)
#define GPIO_LED2 22 // BCM22 (broche physique 15)
#define CHIPNAME "gpiochip0"
#define DELAY_MS 500 // 0.5 seconde
int main() {
// 1. Initialisation
struct gpiod_chip *chip = gpiod_chip_open_by_name(CHIPNAME);
struct gpiod_line *led1 = gpiod_chip_get_line(chip, GPIO_LED1);
struct gpiod_line *led2 = gpiod_chip_get_line(chip, GPIO_LED2);
// Configuration en sortie
gpiod_line_request_output(led1, "LED1", 0); // Éteinte au départ
gpiod_line_request_output(led2, "LED2", 1); // Allumée au départ
// 2. Boucle d'alternance
printf("Alternance GPIO17/GPIO22 (Ctrl+C pour arrêter)\n");
while (1) {
gpiod_line_set_value(led1, 1); // LED1 ON
gpiod_line_set_value(led2, 0); // LED2 OFF
usleep(DELAY_MS * 1000);
gpiod_line_set_value(led1, 0); // LED1 OFF
gpiod_line_set_value(led2, 1); // LED2 ON
usleep(DELAY_MS * 1000);
}
// 3. Nettoyage (inaccessible ici à cause de la boucle infinie)
gpiod_line_release(led1);
gpiod_line_release(led2);
gpiod_chip_close(chip);
return 0;
}
Saisir , compiler tester le code
Expliquez comment utiliser GDB pour contrôler l’allumage et l’extinction des LED
Donner les commandes qui permettent de réaliser des sorties
Entrée avec ILS
Montage 2
GPIO27 en entrée , GPIO17 en sortie

Répertoire: ils_led , code: ils_led.c
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h> // pour usleep()
#define GPIO_CHIP "gpiochip0" // Nom du contrôleur GPIO
#define GPIO_INPUT 27 // GPIO27 en entrée (ILS)
#define GPIO_OUTPUT 17 // GPIO17 en sortie
#define DELAY_MS 50 // Délai de lecture (en ms)
int main() {
struct gpiod_chip *chip;
struct gpiod_line *input_line, *output_line;
int input_state;
// 1. Initialisation du GPIO
chip = gpiod_chip_open_by_name(GPIO_CHIP);
if (!chip) {
perror("Erreur d'ouverture du chip GPIO");
return EXIT_FAILURE;
}
// 2. Configuration des broches
input_line = gpiod_chip_get_line(chip, GPIO_INPUT);
output_line = gpiod_chip_get_line(chip, GPIO_OUTPUT);
if (!input_line || !output_line) {
perror("Erreur de configuration des broches");
gpiod_chip_close(chip);
return EXIT_FAILURE;
}
// GPIO27 en entrée (avec résistance de rappel externe au +3.3V)
gpiod_line_request_input(input_line, "ils-input");
// GPIO17 en sortie
gpiod_line_request_output(output_line, "led-output", 0);
printf("Démarrage de la copie GPIO%d → GPIO%d (CTRL+C pour arrêter)\n", GPIO_INPUT, GPIO_OUTPUT);
// 3. Boucle principale
while (1) {
// Lecture de l'état de l'ILS (0=ouvert, 1=fermé)
input_state = gpiod_line_get_value(input_line);
// Copie vers la sortie
gpiod_line_set_value(output_line, input_state);
// Petite pause pour éviter la surcharge CPU
usleep(DELAY_MS * 1000);
}
// 4. Nettoyage (jamais atteint ici à cause de la boucle infinie)
gpiod_line_release(input_line);
gpiod_line_release(output_line);
gpiod_chip_close(chip);
return EXIT_SUCCESS;
}
Saisir le code le compiler et le tester
Proposer un moyen avec gdb de surveiller GPIO27 et de contrôler GPIO17
Avec Monia proposer un organigramme et son PL
Résistance de rappel interne
on va garder le même montage mais on va le simplifier en ajoutant un peu de code.
on supprime la résistance externe et on laisse l’ILS .
Comme déjà étudié précédemment .
Justifier comment on peut supprimer cette résistance externe.
comment faire si on la supprime.
Code C proposé , ils_led_sr.c
besoin de sigint en C
répertoire: ilsredsrc , code : ils_led_sr.c
#include <gpiod.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#define GPIO_CHIP "gpiochip0"
#define GPIO_ILS 27 // GPIO27 en entrée (ILS au +3.3V)
#define GPIO_SORTIE 17 // GPIO17 en sortie
#define DELAY_MS 50 // Délai de lecture
volatile sig_atomic_t stop = 0;
/* interruption SIGINT ctrl c */
void handle_sigint(int sig) {
printf("\nInterception CTRL+C\n"); // Debug visible
stop = 1;
}
int main() {
struct gpiod_chip *chip;
struct gpiod_line *ils, *sortie;
struct gpiod_line_request_config cfg_ils = {
.consumer = "ILS",
.request_type = GPIOD_LINE_REQUEST_DIRECTION_INPUT,
.flags = GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN // Pull-down interne
};
// 1. Initialisation GPIO
chip = gpiod_chip_open_by_name(GPIO_CHIP);
if (!chip) {
perror("Erreur ouverture chip GPIO");
return EXIT_FAILURE;
}
// 2. Configuration entrée (ILS) avec pull-down
ils = gpiod_chip_get_line(chip, GPIO_ILS);
if (!ils || gpiod_line_request(ils, &cfg_ils, 0)) {
perror("Erreur configuration ILS");
gpiod_chip_close(chip);
return EXIT_FAILURE;
}
// 3. Configuration sortie
sortie = gpiod_chip_get_line(chip, GPIO_SORTIE);
if (!sortie || gpiod_line_request_output(sortie, "sortie", 0)) {
perror("Erreur configuration sortie");
gpiod_line_release(ils);
gpiod_chip_close(chip);
return EXIT_FAILURE;
}
// 4. Gestion CTRL+C
signal(SIGINT, handle_sigint);
printf("Monitoring ILS sur GPIO%d → Sortie GPIO%d\n", GPIO_ILS, GPIO_SORTIE);
printf("Schéma : ILS(+3.3V) → GPIO%d | Pull-down interne activé\n", GPIO_ILS);
// 5. Boucle principale
while (!stop) {
int etat = gpiod_line_get_value(ils);
gpiod_line_set_value(sortie, etat);
usleep(DELAY_MS * 1000);
}
// 6. Nettoyage
gpiod_line_release(ils);
gpiod_line_release(sortie);
gpiod_chip_close(chip);
printf("\nArrêt propre\n");
return EXIT_SUCCESS;
}
Donner la commande qui a permis de résoudre le fait d’avoir enlevé la resistance externe
En quoi ce code est amélioré hormis la modification avec la résistance en moins.
Avec GDB Surveiller la réaction au ctrl c , expliquer
sous gdb , quand on fait ctrl c (^c), c’est gdb qui répond !! et pas notre code!
donc il faut dire a gdb de ne pas réagir a ctrl c , avec la commande
handle SIGINT nostop noprint pass
ce qui nous permettra ensuite de mettre un point d’arrêt ligne 16 pour s’arrêter dans la fonction void handle_sigint(int sig)
interruption provoquée par le ctrl c (SIGINT)
Expliquer avec gdb
Avec Monia donner les organigrammes et les PL
On va utiliser la sonde numérique SALEAE
on va utiliser la sonde SALEAE pour relever les signaux GPIO27 et GPIO17
ch0: GPIO17
ch1: GPIO27
ne pas oublier de brancher la masse (GND)
Code blink gpio17.c (avec ctrl c)
/********************************/
/* Blink GPIO17 Libgpiod 1.6 */
/********************************/
#include <gpiod.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
struct gpiod_line *led_line = NULL; /* Déclaré global pour le gestionnaire de signal */
/* Gère Ctrl+C pour éteindre la LED et libérer les GPIO */
void signal_handler(int signo)
{
if (signo == SIGINT) {
printf("\nExtinction et nettoyage...\n");
if (led_line) {
gpiod_line_set_value(led_line, 0); /* Éteint la LED */
gpiod_line_release(led_line); /* Libère la ligne */
}
exit(EXIT_SUCCESS);
}
}
/*************************************************************************/
int main()
{
const char *chipname = "gpiochip0";
const int led_pin = 17; /* GPIO17, broche physique 11 */
/* 1. OUVERTURE du chip */
struct gpiod_chip *chip = gpiod_chip_open_by_name(chipname);
if (!chip)
{
perror("Erreur ouverture chip");
return EXIT_FAILURE;
}
/* 2. CONFIGURATION de la ligne en SORTIE */
led_line = gpiod_chip_get_line(chip, led_pin);
if (!led_line)
{
perror("Erreur obtention ligne");
gpiod_chip_close(chip);
return EXIT_FAILURE;
}
/* Valeur initiale = 0 (LED éteinte au démarrage) */
if (gpiod_line_request_output(led_line, "blink_app", 0) < 0)
{
perror("Erreur configuration sortie");
gpiod_chip_close(chip);
return EXIT_FAILURE;
}
signal(SIGINT, signal_handler); /* Capture signal Ctrl+C */
printf("LED clignotante (GPIO%d). Ctrl+C pour arrêter.\n", led_pin);
/* 3. UTILISATION : Boucle de lecture/écriture */
while (1)
{
gpiod_line_set_value(led_line, 1); /* Allume */
printf("État: ON\n");
sleep(1);
gpiod_line_set_value(led_line, 0); /* Éteint */
printf("État: OFF\n");
sleep(1);
}
/* 4. NETTOYAGE (en principe jamais atteint à cause de la boucle infinie)
Le gestionnaire de signal `signal_handler` s'en charge.
gpiod_chip_close(chip); // Serait à faire ici si pas de boucle infinie */
return EXIT_SUCCESS;
}


