🕒 : 3 h maximum

Prérequis:

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)

/********************************/
/* 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;
}