<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sdeparis</id>
	<title>projets-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sdeparis"/>
	<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Sdeparis"/>
	<updated>2026-05-14T03:00:11Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7175</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7175"/>
		<updated>2025-01-14T16:02:53Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|450px|Ordonnancement leds asynchrones ]]&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. &lt;br /&gt;
Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. &lt;br /&gt;
Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Afficheur 7 segments.mp4|500px|left]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7174</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7174"/>
		<updated>2025-01-14T16:01:53Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|450px|Ordonnancement leds asynchrones ]]&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. &lt;br /&gt;
Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. &lt;br /&gt;
Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Afficheur 7 segments.mp4|vignette]]&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Afficheur_7_segments.mp4&amp;diff=7173</id>
		<title>Fichier:Afficheur 7 segments.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Afficheur_7_segments.mp4&amp;diff=7173"/>
		<updated>2025-01-14T16:01:43Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;afficheur 7 segments&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7172</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7172"/>
		<updated>2025-01-14T15:59:33Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|450px|Ordonnancement leds asynchrones ]]&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. &lt;br /&gt;
Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. &lt;br /&gt;
Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7171</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7171"/>
		<updated>2025-01-14T15:58:38Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|450px|Ordonnancement leds asynchrones ]]&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7170</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7170"/>
		<updated>2025-01-14T15:57:39Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|300px|Ordonnancement leds asynchrones ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7169</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7169"/>
		<updated>2025-01-14T15:56:40Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
[[Fichier:Ordonnancement leds asynchrones .mp4|vignette|Ordonnancement leds asynchrones ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ordonnancement_leds_asynchrones_.mp4&amp;diff=7168</id>
		<title>Fichier:Ordonnancement leds asynchrones .mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ordonnancement_leds_asynchrones_.mp4&amp;diff=7168"/>
		<updated>2025-01-14T15:56:23Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ordonnancement leds asynchrones&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7167</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7167"/>
		<updated>2025-01-14T15:48:37Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Envois des données via le port SPI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;br /&gt;
&lt;br /&gt;
La communication fonctionne, quand on appuye sur une touche, c'est le bon caractère affiché sur minicom, le saut de ligne le changement de mode fonctionne bien.&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7166</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7166"/>
		<updated>2025-01-14T15:42:35Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Envois des données via le port SPI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
[[Fichier:Communication SPI.mp4|vignette|Communication SPI (minicom)]]&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Communication_SPI.mp4&amp;diff=7165</id>
		<title>Fichier:Communication SPI.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Communication_SPI.mp4&amp;diff=7165"/>
		<updated>2025-01-14T15:41:57Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Communication SPI&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7164</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7164"/>
		<updated>2025-01-14T15:36:21Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|vignette|Leds modes clavier]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7163</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7163"/>
		<updated>2025-01-14T15:35:25Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|800px|Leds modes clavier]]&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7162</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7162"/>
		<updated>2025-01-14T15:34:58Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|right|500px|Leds modes clavier]]&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Leds_modes_clavier.mp4&amp;diff=7161</id>
		<title>Fichier:Leds modes clavier.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Leds_modes_clavier.mp4&amp;diff=7161"/>
		<updated>2025-01-14T15:34:04Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : Sdeparis a téléversé une nouvelle version de Fichier:Leds modes clavier.mp4&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Leds modes clavier&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7160</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7160"/>
		<updated>2025-01-14T15:29:21Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|500px|Leds modes clavier]]&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7159</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7159"/>
		<updated>2025-01-14T15:28:13Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
[[Fichier:Leds modes clavier.mp4|vignette|Leds modes clavier]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Leds_modes_clavier.mp4&amp;diff=7158</id>
		<title>Fichier:Leds modes clavier.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Leds_modes_clavier.mp4&amp;diff=7158"/>
		<updated>2025-01-14T15:27:59Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Leds modes clavier&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7157</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7157"/>
		<updated>2025-01-14T15:21:13Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Envois des données via le port SPI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;br /&gt;
Utilisation du Picoshield qui jouera le rôle de la carte mère.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''update_lettreMemorise()''' : Cette fonction met à jour la lettre en attente d'être envoyée lors de l'interruption. Elle vérifie si une nouvelle touche est pressée et différente de la dernière lettre envoyée, et met à jour les variables correspondantes.&lt;br /&gt;
&lt;br /&gt;
'''testcom()''' : Cette fonction gère la communication SPI. Elle attend une commande SPI et envoie la lettre en attente si une nouvelle lettre est disponible.&lt;br /&gt;
&lt;br /&gt;
'''config_interrupt_PB1()''' : Cette fonction configure l'interruption sur la broche PB1. Elle met PB1 en entrée, active la résistance pull-up interne et configure les registres d'interruption.&lt;br /&gt;
&lt;br /&gt;
'''ISR(PCINT0_vect)''' : Cette fonction est la routine d'interruption pour l'interruption sur la broche PB1. Elle appelle la fonction &amp;lt;code&amp;gt;testcom()&amp;lt;/code&amp;gt; après un délai de 10 ms.&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7156</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7156"/>
		<updated>2025-01-14T15:16:07Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons développé les [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier fonctions] pour la matrice de boutons :&lt;br /&gt;
&lt;br /&gt;
# '''configuration_bouton()''' : Cette fonction configure les lignes comme entrées et les colonnes comme sorties pour le clavier. Elle active également les résistances pull-up internes pour les lignes.&lt;br /&gt;
# '''test_boutons()''' : retourne l'index du bouton pressé ou -1 si aucun bouton n'est pressé.&lt;br /&gt;
# '''lecture_touche()''' : Cette fonction lit la touche actuellement pressée sur le clavier. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et retourne le caractère correspondant à cet index.&lt;br /&gt;
# '''led_bouton_appuye()''' : Cette fonction allume les LED correspondant au bouton actuellement pressé. Elle utilise la fonction &amp;lt;code&amp;gt;test_boutons()&amp;lt;/code&amp;gt; pour obtenir l'index du bouton pressé et met à jour les valeurs PWM des LED en conséquence.&lt;br /&gt;
&lt;br /&gt;
Explication de test_boutons :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7155</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7155"/>
		<updated>2025-01-14T15:00:33Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs] :&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite créer des [https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/leds.c fonctions] qui permettent de contrôler les LED en définissant les couleurs et les intensités lumineuses souhaitées.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7154</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7154"/>
		<updated>2025-01-14T14:54:38Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;[https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c Tout d'abord on a commencé par codé les TLCs ]:&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7153</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7153"/>
		<updated>2025-01-14T14:52:35Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tout d'abord on a commencé par codé les TLCs : https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7152</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7152"/>
		<updated>2025-01-14T14:51:34Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tout d'abord on a commencé par codé les TLCs : https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7151</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7151"/>
		<updated>2025-01-14T14:48:38Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
Tout d'abord on a commencé par codé les TLCs : https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier/tlc5947.c&lt;br /&gt;
&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7150</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7150"/>
		<updated>2025-01-14T14:47:44Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
Tout d'abord on a commencé par codé les TLCs :&lt;br /&gt;
&lt;br /&gt;
# '''init_LED_Drivers(int nb)''' : Cette fonction initialise les pilotes LED en configurant les broches nécessaires comme sorties et en mettant la sortie LATCH à bas. En d'autres termes, elle prépare les pilotes LED pour qu'ils puissent recevoir des signaux de commande.&lt;br /&gt;
# '''set_LED_Drivers(int pwm[], int nb)''' : Cette fonction envoie les valeurs PWM (modulation de largeur d'impulsion) aux pilotes LED. Elle parcourt chaque canal et bit pour définir les sorties CLOCK et DATA en conséquence, puis bascule la sortie LATCH pour mettre à jour les LED avec les nouvelles valeurs PWM. En résumé, elle contrôle la luminosité des LED en fonction des valeurs PWM fournies.&lt;br /&gt;
&lt;br /&gt;
Ces fonctions permettent de gérer et de contrôler les LED en utilisant les pilotes TLC5947.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7149</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7149"/>
		<updated>2025-01-14T14:40:37Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |=&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | !&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7148</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7148"/>
		<updated>2025-01-14T14:37:32Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7147</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7147"/>
		<updated>2025-01-14T14:35:29Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7146</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7146"/>
		<updated>2025-01-14T14:34:17Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7145</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7145"/>
		<updated>2025-01-14T14:32:14Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/code/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7144</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7144"/>
		<updated>2025-01-14T14:31:50Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
PICO_Binome1/code/Ordonnanceur at main - lgrevin/PICO_Binome1 - Gitea: Git with a cup of tea&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7112</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7112"/>
		<updated>2025-01-10T15:15:37Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|250px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7111</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7111"/>
		<updated>2025-01-10T15:15:20Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|400px|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7110</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7110"/>
		<updated>2025-01-10T15:14:45Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7109</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7109"/>
		<updated>2025-01-10T15:14:27Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|vignette|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7108</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7108"/>
		<updated>2025-01-10T15:14:20Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|left|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7107</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7107"/>
		<updated>2025-01-10T15:13:56Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|vignette|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7106</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7106"/>
		<updated>2025-01-10T15:13:45Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|left|vignette|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7105</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7105"/>
		<updated>2025-01-10T15:13:18Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Brasure de la carte Clavier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
[[Fichier:Carte Clavier brasé.jpg|alt=Carte Clavier brasé|vignette|Carte Clavier brasé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_Clavier_bras%C3%A9.jpg&amp;diff=7104</id>
		<title>Fichier:Carte Clavier brasé.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_Clavier_bras%C3%A9.jpg&amp;diff=7104"/>
		<updated>2025-01-10T15:12:58Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte Clavier brasé&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7084</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7084"/>
		<updated>2025-01-06T14:57:19Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
Résumé :&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7083</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7083"/>
		<updated>2025-01-06T14:54:53Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Résumé de la logique de la fonction : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 Résumé de la logique de la fonction : &lt;br /&gt;
&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7082</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7082"/>
		<updated>2025-01-06T14:53:37Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Cette fonction teste chaque bouton dans la matrice pour vérifier si un bouton a été pressé.&lt;br /&gt;
&lt;br /&gt;
* '''Initialisation de &amp;lt;code&amp;gt;bouton&amp;lt;/code&amp;gt;''' :&lt;br /&gt;
** &amp;lt;code&amp;gt;int bouton=-1;&amp;lt;/code&amp;gt; initialise la variable qui enregistrera l'indice du bouton pressé. Si aucun bouton n'est pressé, cette valeur restera &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Boucle des colonnes (parcourir chaque colonne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne met à 0 la broche de la colonne courante. Cela active la colonne en la mettant à &amp;quot;0&amp;quot;, ce qui permet de tester si l'un des boutons dans cette colonne est pressé (dans une matrice, on active une colonne en mettant la broche à &amp;quot;0&amp;quot;).&lt;br /&gt;
* '''Boucle des lignes (parcourir chaque ligne)''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&amp;lt;/code&amp;gt;''' : Cette ligne vérifie l'état de la ligne correspondante. Si le bouton est pressé, la ligne devrait être mise à &amp;quot;0&amp;quot; (car une connexion au sol active le bouton dans une matrice de boutons).&lt;br /&gt;
** Si le test montre que la ligne correspondante est à &amp;quot;0&amp;quot;, cela signifie qu'un bouton est pressé. '''&amp;lt;code&amp;gt;bouton=c+l*NB_COLS;&amp;lt;/code&amp;gt;''' calcule l'indice du bouton pressé en fonction de la colonne (&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt;) et de la ligne (&amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''&amp;lt;code&amp;gt;break;&amp;lt;/code&amp;gt;''' : Si un bouton a été détecté dans cette colonne, on sort immédiatement de la boucle des lignes.&lt;br /&gt;
* '''Retour à l'état normal de la colonne''' :&lt;br /&gt;
** '''&amp;lt;code&amp;gt;*colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin);&amp;lt;/code&amp;gt;''' : Cette ligne remet à 1 la broche de la colonne courante pour revenir à l'état normal après avoir testé cette colonne.&lt;br /&gt;
* '''Retourner l'indice du bouton pressé''' :&lt;br /&gt;
** Si un bouton a été détecté, la fonction retourne l'indice du bouton pressé. Sinon, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Résumé de la logique de la fonction : ===&lt;br /&gt;
&lt;br /&gt;
* La fonction parcourt chaque colonne de la matrice de boutons, met la colonne à 0 (active la colonne) et vérifie chaque ligne pour voir si un bouton a été pressé (en vérifiant si la ligne est à 0).&lt;br /&gt;
* Dès qu'un bouton est détecté, l'indice du bouton est calculé et retourné.&lt;br /&gt;
* Si aucun bouton n'est pressé, la fonction retourne &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7081</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7081"/>
		<updated>2025-01-06T14:51:05Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;'''&amp;lt;code&amp;gt;lignes&amp;lt;/code&amp;gt;''' et '''&amp;lt;code&amp;gt;colonnes&amp;lt;/code&amp;gt;''' sont des tableaux de &amp;lt;code&amp;gt;couple&amp;lt;/code&amp;gt; qui représentent respectivement les lignes et les colonnes d'une matrice de boutons. Chaque entrée de ces tableaux contient :&lt;br /&gt;
&lt;br /&gt;
* Un pointeur vers un registre de port (par exemple, &amp;lt;code&amp;gt;PINB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PINC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PORTC&amp;lt;/code&amp;gt;, etc.).&lt;br /&gt;
* Le numéro de la broche spécifique à cet élément.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7080</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7080"/>
		<updated>2025-01-06T14:49:25Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7078</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7078"/>
		<updated>2025-01-06T14:48:07Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7076</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7076"/>
		<updated>2025-01-06T14:46:27Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7074</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7074"/>
		<updated>2025-01-06T14:43:41Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Programmation des leds et des boutons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    volatile uint8_t *port;&lt;br /&gt;
    int pin;&lt;br /&gt;
} couple;&lt;br /&gt;
&lt;br /&gt;
couple lignes[NB_LIGNES]={&lt;br /&gt;
    {&amp;amp;PINB,PB0},{&amp;amp;PINC,PC0},{&amp;amp;PINC,PC1},{&amp;amp;PINC,PC2}&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
couple colonnes[NB_COLS]={&lt;br /&gt;
    {&amp;amp;PORTC,PC3},{&amp;amp;PORTC,PC4},{&amp;amp;PORTC,PC5},{&amp;amp;PORTD,PD0},&lt;br /&gt;
    {&amp;amp;PORTD,PD1},{&amp;amp;PORTD,PD2},{&amp;amp;PORTD,PD3},{&amp;amp;PORTD,PD4}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int test_boutons(){&lt;br /&gt;
    int bouton=-1;&lt;br /&gt;
    for(int c=0;c&amp;lt;NB_COLS;c++){&lt;br /&gt;
        *colonnes[c].port &amp;amp;= ~(1&amp;lt;&amp;lt;colonnes[c].pin); // 0 sur la colonne courante&lt;br /&gt;
        for(int l=0;l&amp;lt;NB_LIGNES;l++){&lt;br /&gt;
            unsigned char test=(*lignes[l].port)&amp;amp;(1&amp;lt;&amp;lt;lignes[l].pin);&lt;br /&gt;
            if(test==0){ bouton=c+l*NB_COLS; break; }&lt;br /&gt;
        }&lt;br /&gt;
        *colonnes[c].port |= (1&amp;lt;&amp;lt;colonnes[c].pin); // retourn à 1 sur la colonne courante&lt;br /&gt;
        if(bouton&amp;gt;=0) break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return bouton;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7072</id>
		<title>SE4Binome2024-1</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-1&amp;diff=7072"/>
		<updated>2025-01-06T14:42:41Z</updated>

		<summary type="html">&lt;p&gt;Sdeparis : /* Code ordonnanceur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lien git : https://gitea.plil.fr/lgrevin/PICO_Binome1.git&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'un shield arduino =&lt;br /&gt;
Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.&lt;br /&gt;
&lt;br /&gt;
Ce bouclier est conçu pour connecter jusqu’à 5 périphériques SPI via des connecteurs IDC HE10 (8 broches), en intégrant des lignes spécifiques pour la réinitialisation et l’interruption de chaque périphérique, assurant ainsi un contrôle optimal.&lt;br /&gt;
&lt;br /&gt;
En plus des connexions SPI, le bouclier comprend également une mémoire, avec deux options de stockage possibles : une carte micro-SD via un connecteur Molex 10431 ou une puce mémoire AT45DB641E, laissant la flexibilité de choisir celle qui sera soudée selon les besoins. Un convertisseur de niveau (74LV125) est également intégré pour assurer la compatibilité de tension entre l’Arduino (5V) et les mémoires (3,3V), garantissant une communication stable entre les composants.&lt;br /&gt;
&lt;br /&gt;
== Schématique et Routage ==&lt;br /&gt;
[[Fichier:PicoShieldSchematic.pdf|left|450px|vignette|Schématique du PicoShield]]&lt;br /&gt;
[[Fichier:RoutagePicoShield.png|center|450px|vignette|Routage du PicoShield]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shield Brasé ==&lt;br /&gt;
[[Fichier:Shield fini.jpg|alt=Shield fini|236px|left|Shield fini]]&lt;br /&gt;
[[Fichier:Shield sur une carte Arduino.jpg|alt=Shield sur une carte Arduino|422px|Shield sur une carte Arduino]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vérification des Leds et de la Carte SD==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Test des Leds .mp4|vignette|600px|Test des Leds du Shield]]&lt;br /&gt;
&amp;lt;u&amp;gt;Code Arduino pour vérifier si les Leds fonctionnent :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/VerificationArduino/verif.c &lt;br /&gt;
&lt;br /&gt;
Nous avons écris un petit programme Arduino pour allumer les leds alternativement et donc vérifier leurs fonctionnement.    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vérification de la détection de la carte SD :&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier si la carte SD est bien détecté nous avons utilisé un programme exemple de l'arduino : &lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Verification_Shield_et_Arduino/SD.ino &lt;br /&gt;
&lt;br /&gt;
Nous avons rencontré des difficultés pour détecter la carte SD. Nous avons essayé plusieurs solutions, notamment en vérifiant l’horloge de notre Shield. &lt;br /&gt;
Pour cela, nous avons soudé des fils aux ports GND et SCK de la puce mémoire et envoyé un code SPI à l’Arduino pour analyser le signal à l’oscilloscope, &lt;br /&gt;
mais cela n’a pas permis d’identifier le problème. &lt;br /&gt;
Après avoir revérifié les soudures et repassé le fer à souder sur plusieurs connexions, nous avons finalement découvert qu’une résistance mal soudée était la source du problème.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:CarteSDdetecte.png|alt=Carte SD détectée|vignette|left|520px|Carte SD détectée]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code ordonnanceur =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais. Cela garantit que les processus critiques reçoivent les ressources nécessaires pour fonctionner sans interruption, optimisant la performance et la réactivité du système.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gestion des processus repose sur une structure qui définit chaque tâche du système. Cette structure inclut les informations nécessaires pour suivre l'état et le comportement des processus, comme indiqué ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Voici une fonction basique que nous utilisons pour faire clignoter une LED. On peut noter l'utilisation d'une fonction &amp;lt;code&amp;gt;delay&amp;lt;/code&amp;gt;, qui est liée à notre méthode pour endormir un processus, comme nous le verrons un peu plus tard.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void LED1() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        PORTD ^= (1 &amp;lt;&amp;lt; PD1);&lt;br /&gt;
        delay(REASON_DELAY,DELAY1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Notre scheduler a deux objectifs : d'abord, décrémenter le temps de sommeil des processus endormis, puis s'assurer que &amp;quot;taskIndex&amp;quot; pointe uniquement vers un processus qui n'est pas en sommeil.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Gestion de l'ordonnanceur&lt;br /&gt;
void scheduler() {&lt;br /&gt;
    for(int i=0; i&amp;lt;NB_PROCESS; i++){&lt;br /&gt;
        if (tableauProcess[i].state == SLEEP_STATE &amp;amp;&amp;amp; tableauProcess[i].reason == REASON_DELAY){&lt;br /&gt;
            if (PERIODE&amp;lt;tableauProcess[i].sleepTime)&lt;br /&gt;
                tableauProcess[i].sleepTime -= PERIODE;&lt;br /&gt;
            else&lt;br /&gt;
                tableauProcess[i].sleepTime = 0;&lt;br /&gt;
&lt;br /&gt;
            if(tableauProcess[i].sleepTime == 0){&lt;br /&gt;
                tableauProcess[i].state = AWAKE_STATE;&lt;br /&gt;
                tableauProcess[i].reason = NO_REASON;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    do {&lt;br /&gt;
        taskIndex++;&lt;br /&gt;
        if (taskIndex == NB_PROCESS) taskIndex = 0;&lt;br /&gt;
    } while (tableauProcess[taskIndex].state == SLEEP_STATE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;La fonction delay met le processus en pause pour une durée donnée. Elle désactive les interruptions (cli()), passe le processus en SLEEP_STATE, enregistre la raison et la durée, réinitialise le compteur de Timer1 (TCNT1 = 0), puis réactive les interruptions (sei()). Cela permet de gérer les délais avec précision.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void delay(uint16_t reason, uint16_t ms)&lt;br /&gt;
{&lt;br /&gt;
  cli(); //Désactive les interruptions&lt;br /&gt;
  tableauProcess[taskIndex].state = SLEEP_STATE;&lt;br /&gt;
  tableauProcess[taskIndex].reason = reason;&lt;br /&gt;
  tableauProcess[taskIndex].sleepTime = ms;&lt;br /&gt;
  TCNT1 = 0; //Valeur actuelle du compteur de Timer1&lt;br /&gt;
  sei(); //Réactive les interruptions&lt;br /&gt;
  TIMER1_COMPA_vect();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Au final, avec notre ordonnanceur, on peut faire tourner plusieurs processus simultanément. Cela nous a permis, par exemple, de faire clignoter les LEDs de manière asynchrone, en gérant indépendamment le temps de sommeil de chaque processus.&lt;br /&gt;
&lt;br /&gt;
Un problème qu'on a pu rencontrer, c'est que si tous les processus sont en état de sommeil, on se retrouve dans une boucle infinie où le temps de sommeil des processus ne se décrémente pas, ce qui bloque tout. Après avoir pris du temps pour comprendre ça, j'ai ajouté un processus IDLE qui ne fait rien. Grâce à lui, si tous les autres processus sont endormis, celui-là ne l'est pas, et cela empêche de rester bloqué dans une boucle infinie.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void IDLE(){&lt;br /&gt;
    while(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour complexifier cet ordonnanceur, nous avons ajouté une fonctionnalité en nous inspirant (très fortement) du cours : la lecture et l’écriture sur les ports séries. Par exemple, on peut lire des caractères (comme un chiffre) via le port série, et l’objectif est ensuite d’afficher ce caractère sur un afficheur 7 segments branché sur un des port HE10.&lt;br /&gt;
&lt;br /&gt;
https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme013.html et https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme014.html&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t spi_echange(uint8_t envoi){                  // Communication sur le bus SPI&lt;br /&gt;
    SPDR = envoi;                                        // Octet a envoyer&lt;br /&gt;
    while(!(SPSR &amp;amp; (1&amp;lt;&amp;lt;SPIF)));                          // Attente fin envoi (drapeau SPIF du statut)&lt;br /&gt;
    return SPDR;                                         // Octet reçu&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SevenSeg() {&lt;br /&gt;
    while (1) {&lt;br /&gt;
        spi_activer();&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
            spi_echange(valeur);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        spi_desactiver();&lt;br /&gt;
&lt;br /&gt;
        delay(REASON_DELAY, 100);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Ordonnanceur&lt;br /&gt;
&lt;br /&gt;
= Réalisation d'une carte clavier =&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;Nous avons choisi de faire une matrice de touche pour réaliser la carte clavier.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Cette matrice contient 8 colonnes et 4 lignes soit un total de 32 boutons. Nous avons également choisi d'ajouter des leds RGB, une sur chaque ligne et chaque colonne qui seront commandés par 2 controleurs de leds (TLC5947 [https://www.ti.com/lit/ds/symlink/tlc5947.pdf?ts=1733111467064&amp;amp;ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTLC5947]) à l'aide des TLC nous pouvons jouer sur l'intensités et les couleurs des leds. &lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Datasheet des LEDs RGB:&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
https://docs.rs-online.com/988a/0900766b80e2903e.pdf&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Consommation de la carte clavier==&lt;br /&gt;
&lt;br /&gt;
La Puissance totale maximale est de 5,55W. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Bilan de puissance (VCC = 5V)&lt;br /&gt;
!Composant&lt;br /&gt;
!Courant&lt;br /&gt;
!Puissance&lt;br /&gt;
|-&lt;br /&gt;
|12xLEDS RGB&lt;br /&gt;
|12x(30x3) mA&lt;br /&gt;
|5,4W&lt;br /&gt;
|-&lt;br /&gt;
|ATMega328p&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|LED d'alim&lt;br /&gt;
|15 mA&lt;br /&gt;
|75 mW&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAL'''&lt;br /&gt;
|'''1,11A'''&lt;br /&gt;
|'''5,55W'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schématique &amp;amp; Routage ==&lt;br /&gt;
[[Fichier:Carte Clavier Schématique.pdf|alt=Carte Clavier Schématique|left|450px|vignette|Carte Clavier Schématique]]&lt;br /&gt;
[[Fichier:Carte Clavier routé.png|center|450px|vignette|Carte Clavier routé]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brasure de la carte Clavier==&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation de la carte Clavier ==&lt;br /&gt;
&lt;br /&gt;
Nous voulions un clavier qui lorsqu'on appui sur un bouton on allume la led de la ligne et de la colonne correspondante. Par la suite nous avons aussi pensé à faire plusieurs mode possible pour un même clavier c'est à dire que selon le mode du clavier on a un clavier minuscule (par défault),  un avec les lettres majuscules et un dernier avec les chiffres et caractères spéciaux. Nous avons donc codé les modes par 2 boutons ( Alt et Maj ) et les modes sont représentés par des couleurs, le clavier par défaut est en bleu, le clavier lettre majuscule en rouge et le dernier en vert.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/lgrevin/PICO_Binome1/src/branch/main/Carte_clavier&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Clavier par default&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | a&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | b&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | c&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | d&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | e&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | f&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | g&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | h&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | i&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | j&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | k&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | l&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | m&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | n&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | o&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | p&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | r&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | s&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | t&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | u&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ,&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | v&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | w&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | x&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier lettre majuscule&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | A&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | B&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | C&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | D&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | E&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | F&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | G&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | H&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | I&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | J&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | K&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | L&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | M&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | N&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | O&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | P&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Q&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | R&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | S&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | T&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | U&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | .&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | V&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | W&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | X&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Y&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Z&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | Alt&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;lt;big&amp;gt;⇧&amp;lt;/big&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Clavier chiffre et caractère spéciaux&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;table-layout: fixed; width: 240px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 0&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 1&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 2&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 3&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 4&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 5&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 6&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ⌫&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 7&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 8&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | 9&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | (&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | )&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &amp;quot;&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ↵&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | +&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | *&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | /&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
|?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | &lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;height: 30px; width: 30px;&amp;quot; | ␣&lt;br /&gt;
! style=&amp;quot;height: 30px; width: 30px;&amp;quot; | '''Alt'''&lt;br /&gt;
|⇧&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Programmation des leds et des boutons ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; start=&amp;quot;129&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t functionAdress;  // Adresse de la fonction&lt;br /&gt;
    uint16_t stackPointer;    // Pointeur de pile&lt;br /&gt;
    bool state;               // État (actif ou en sommeil)&lt;br /&gt;
    uint16_t sleepTime;       // Temps restant en sommeil (ms)&lt;br /&gt;
    uint16_t reason;          // Raison de suspension&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;[[Fichier:Struct couples lignes et colonne.jpg|vignette|Struct couples lignes et colonnes]]&lt;br /&gt;
[[Fichier:Test boutons.jpg|vignette]]&lt;br /&gt;
&lt;br /&gt;
=== Envois des données via le port SPI ===&lt;/div&gt;</summary>
		<author><name>Sdeparis</name></author>
	</entry>
</feed>