Cours:TPS 2103 tp3 : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
m (Groupe S2d)
(Indice de ligne)
 
(31 révisions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
[[Cours:TPs_2103|{{Rouge|<big>'''Retour à la liste des Tps'''</big>}}]]
+
[[Cours:CoursM2103|{{Rouge|<big>'''Fiche résumé'''</big>}}]]
 +
 
 +
[[Cours:TPs_2103|{{Bleu|<big>'''Retour à la liste des Tps'''</big>}}]]
  
 
[[Cours:TPS_2103_tp3_corrige|{{Vert|<big>'''Éléments de correction'''</big>}}]]
 
[[Cours:TPS_2103_tp3_corrige|{{Vert|<big>'''Éléments de correction'''</big>}}]]
  
[[Fichier:ArduinoPinout.png|600px|droite]]
+
[[Fichier:Arduino-nano-pinout.png|600px|droite]]
  
 
Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino).
 
Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino).
Ligne 9 : Ligne 11 :
 
<big>'''Pour ce TP, nous utilisons une carte arduino {{Rouge|sans le shieldinfo}}'''</big>
 
<big>'''Pour ce TP, nous utilisons une carte arduino {{Rouge|sans le shieldinfo}}'''</big>
  
={{Rouge|Matériel}}=
+
=Matériel=
  
 
Nous utiliserons :
 
Nous utiliserons :
*1 carte arduino UNO
+
*1 carte arduino NANO
 
*1 plaque à essais
 
*1 plaque à essais
*2 leds Rouge
+
*8 leds pour afficher une valeur
*2 leds verte
+
*2 leds verte/rouge pour le fonctionnement du digicode
*4 résistances 330Ω
+
*1 résistance de 330Ω par led
 
*1 clavier matriciel
 
*1 clavier matriciel
*1 buzzer (à insérer directement sur les connecteurs arduino)
+
*fils M-M
*5 fils M-M
+
*fils M-F
*7 fils M-F
 
  
={{Rouge|Informations lumineuses}}=
+
=Informations lumineuses=
  
 +
==Câblage==
 
Le digicode sera équipé de 2 voyants lumineux (rouge et vert).
 
Le digicode sera équipé de 2 voyants lumineux (rouge et vert).
  
On utilisera des résistances de 330Ω, et vous êtes libre de choisir un montage à anodes ou cathodes communes.
+
On utilisera des résistances de 330Ω, les leds seront connectées en cathodes communes.
 +
 
 +
{{Todo|Câbler sur une plaque à essais les leds :}}
 +
*les 2 leds pour le digicode
 +
**verte sur PC0
 +
**rouge sur PC1
 +
*8 leds pour afficher une valeur
 +
**PD0 à PD7
 +
**mettre les leds dans "l'ordre" des broches
 +
 
 +
 
 +
==Utilisation des 8 leds==
  
{{Todo|Câbler sur une plaque à essais les leds sur les pin PC0 (Rouge) et PC1 (Verte)}}
+
Nous utiliserons dans nos programmes [[Cours:CoursM2103#Fixed_width_integer_types|les types de variable dont la taille est explicitement donnée]]
  
{{Question|Vérifier le fonctionnement des leds :}}
+
Le {{Rouge|débogage}} d'un programme est fondamental, il existe différentes façons de le faire. Ici nous nous contenterons {{Rouge|d'utiliser des leds}} pour afficher des informations sur l'exécution du programme.
 +
 
 +
Principe :
  
 
<source lang=c>
 
<source lang=c>
 
#include <avr/io.h>
 
#include <avr/io.h>
 
#include <util/delay.h>
 
#include <util/delay.h>
 +
 +
void clignote()
 +
{
 +
    PORTD=0;
 +
    for (uint8_t i=0;i<5;i++)
 +
    {
 +
        PORTD ^= 0xFF;
 +
        _delay_ms(50);
 +
    }
 +
}
  
 
int main()
 
int main()
 
{
 
{
 
     // config des sorties
 
     // config des sorties
 +
    DDRD = 0xFF; // les 8  broches des leds en sortie
 +
 +
    // qques variables
 +
    uint8_t val1 = 0;
 +
    int8_t val2 = -1;
 +
    uint8_t val3 = 255;
 +
    uint16_t val4 = 256;
  
 
     while(1)
 
     while(1)
 
     {
 
     {
         //allumer R + attendre
+
         PORTD = val1;
          
+
        _delay_ms(2000);
         //allumer V + attendre
+
        clignote();
          
+
        PORTD = val2;
         //eteindre V + attendre
+
        _delay_ms(2000);
          
+
         clignote();
         //eteindre R + attendre
+
         PORTD = val3;
          
+
         _delay_ms(2000);
 +
         clignote();
 +
         PORTD = val4;
 +
         _delay_ms(2000);
 +
         for (int i=0;i<10;i++) clignote();
 
     }
 
     }
 
}
 
}
 
</source>
 
</source>
  
{{Aide|Astuce}}
+
{{Question|Indiquer l'affichage réalisé par chacune des lignes}} PORTD=valx
  
 +
Les nombres négatifs sont représentés pas la méthodes des compléments à deux : https://fr.wikipedia.org/wiki/Compl%C3%A9ment_%C3%A0_deux ]
  
Vous pourrez vous inspirer du programme suivant permettant de faire clignoter la led "13" de la carte Arduino Uno.
+
=Decodage d'un clavier=
<source lang=c>
 
#define led PB5
 
  
int main()
+
==Câblage==
{
 
  DDRB |= 1 << led;
 
  while(1)
 
  {
 
  PORTB |= 1 << led;
 
  delay(100);
 
  PORTB &= ~(1 << led);
 
  delay(100);
 
  }
 
}
 
</source>
 
{{finAide}}
 
  
={{Rouge|Decodage d'un clavier}}=
+
Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L0 à L3) et colonnes (C0 à C2) en vue de dessus :
 
 
=={{Bleu|Câblage}}==
 
 
 
Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L1 à L4) et colonnes (C1 à C3) en vue de dessus :
 
 
{|align="center" border="1" cellpadding="20" cellspacing="0"
 
{|align="center" border="1" cellpadding="20" cellspacing="0"
 
|-
 
|-
Ligne 88 : Ligne 107 :
 
{|align="center" border="1" cellpadding="3" cellspacing="0"
 
{|align="center" border="1" cellpadding="3" cellspacing="0"
 
|-
 
|-
| B0 || B1 || B2 || B3 || D4 || D5 || D6
+
| PC2 || PC3 || PC4 || PC5 || PB0 || PB1 || PB2
 
|-
 
|-
| L1 || L2 || L3 || L4 || C1 || C2 || C3
+
| L0 || L1 || L2 || L3 || C0 || C1 || C2
 
|}
 
|}
 
|-
 
|-
Ligne 99 : Ligne 118 :
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! L/C !! C1 !! C2 !! C3
+
! L/C !! C0 !! C1 !! C2
 
|-
 
|-
! L1 || 1 || 2 || 3
+
! L0 || 1 || 2 || 3
 
|-
 
|-
! L2 || 4 || 5 || 6
+
! L1 || 4 || 5 || 6
 
|-
 
|-
! L3 || 7 || 8 || 9
+
! L2 || 7 || 8 || 9
 
|-
 
|-
! L4 || * || 0 || #
+
! L3 || * || 0 || #
 
|}
 
|}
 
||
 
||
[[Fichier:ClavierMatriciel.png|450px]]
+
[[Fichier:ClavierMatricielPrincipe.png|200px]]
 
|}
 
|}
  
{{Todo|Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les {{Rouge|colonnes}} seront reliées sur le port {{Rouge|D}} et les {{Vert|lignes}} sur le port {{Vert|B}} (cf indications ci dessus)}}
+
{{Todo|Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les {{Rouge|colonnes}} seront reliées sur le port {{Rouge|B}} et les {{Vert|lignes}} sur le port {{Vert|C}} (cf indications ci dessus)}}
  
 
'''Remarque :'''  On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur.
 
'''Remarque :'''  On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur.
Ligne 146 : Ligne 165 :
 
*l'état des lignes dépend de l'appui sur un bouton :
 
*l'état des lignes dépend de l'appui sur un bouton :
 
**si {{Rouge|aucun bouton}} appuyé, les résistances de tirage donnent {{Rouge|un état 1}} sur les lignes
 
**si {{Rouge|aucun bouton}} appuyé, les résistances de tirage donnent {{Rouge|un état 1}} sur les lignes
**si on appui sur un bouton de {{Rouge|la ligne1}} (key 1/2/3), alors l'entrée ligne PB0 passe à {{Rouge|l'état 0}}.
+
**si on appui sur un bouton de {{Rouge|la ligne0}} (key 1/2/3), alors l'entrée ligne PC2 passe à {{Rouge|l'état 0}}.
 
**la valeur change suivant la ligne sur laquelle un bouton est appuyé
 
**la valeur change suivant la ligne sur laquelle un bouton est appuyé
*il suffit donc d'observer les 4 bits PB3..PB0 (que l'on note ici etat), et ainsi :
+
*il suffit donc d'observer les 4 bits PC5..PC2 (que l'on note ici etat), et ainsi :
**si etat = 1111 , pas de touche
+
**si PC5..PC2 = 1111 , pas de touche
**si etat = 1110 , au moins une touche parmi 1/2/3
+
**si PC5..PC2 = 1110 , au moins une touche parmi 1/2/3
**si etat = 1101 , au moins une touche parmi 4/5/6
+
**si PC5..PC2 = 1101 , au moins une touche parmi 4/5/6
 
**...
 
**...
  
 
+
==Indice de ligne==
=={{Bleu|Indice de ligne}}==
 
  
 
{{Question|Ecrire et tester le programme lecture_ligne() qui renvoie le numéro de ligne sur laquelle un bouton est appuyé}}
 
{{Question|Ecrire et tester le programme lecture_ligne() qui renvoie le numéro de ligne sur laquelle un bouton est appuyé}}
 
*La validation se fera en utilisant des leds connectées sur le port C :
 
*La validation se fera en utilisant des leds connectées sur le port C :
**On mettra 4 leds sur les broches PC3 à PC0
+
**On utilisera les 8 leds du PORTD pour afficher le résultat
**On visualisera un nombre n sur 4 bits en écrivant PORTC = n;
+
**par ex : PORTC = lecture_ligne();
  
 
<source lang=c>
 
<source lang=c>
 
int8_t lecture_ligne()
 
int8_t lecture_ligne()
 
{
 
{
   int8_t ch;
+
   int8_t etatEntrees;
   DDRD ?= .... ;    // commençons par lister les sorties sur le port D
+
   DDRB ?= .... ;    // commençons par lister les sorties sur le port B
   DDRB ?= .... ;    // puis les entrées sur le port B
+
   DDRC ?= .... ;    // puis les entrées sur le port C
   PORTD?=..... ;    // on place les sortie à l'état 0
+
   PORTB?=..... ;    // on place les sortie à l'état 0
   PORTB?= .... ;    // on active les résistances de pull-up sur les entrées
+
   PORTC?= .... ;    // on active les résistances de pull-up sur les entrées
  
   _delay_ms(1);        // un délais est nécessaire pour l'activation des pull-ups
+
   _delay_ms(1);        // un délai est nécessaire pour l'activation des pull-ups
  
   ch = PINB & ??; // on récupère ensuite l'état des entrées
+
   etatEntrees = PINC & ??; // on récupère ensuite l'état des entrées en cachant les bits non utiles
   switch (ch)
+
   switch (etatEntrees)
 
   {
 
   {
     case  : return 0; // aucune touche
+
     case  : return 0; // L0 (appui sur l'une des touches 1/2/3 )
 
     case  : return 1; // L1
 
     case  : return 1; // L1
 
     case  : return 2; // L2
 
     case  : return 2; // L2
 
     case  : return 3; // L3
 
     case  : return 3; // L3
    case  : return 4; // L4
+
     // si autre cas, pas de touches deux touches ou autre
     // si autre cas, deux touches ou autre
 
 
     default : return -1;
 
     default : return -1;
 
   }
 
   }
Ligne 193 : Ligne 210 :
  
  
=={{Bleu|Touche appuyée}}==
+
==Touche appuyée==
 
Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous :
 
Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous :
  
Ligne 200 : Ligne 217 :
 
| <source lang=c>
 
| <source lang=c>
 
int8_t touches[4][3] = { // tableau de char à 2 dimensions
 
int8_t touches[4][3] = { // tableau de char à 2 dimensions
   {1,,},
+
   {1,2,3},
   {...},
+
   {4,5,6},
   {...},
+
   {7,..},
 
   {,,11}
 
   {,,11}
 
};
 
};
Ligne 221 : Ligne 238 :
 
{
 
{
 
   ....
 
   ....
}
 
</source>
 
 
={{Rouge|Assemblons le tout}}=
 
 
Nous allons utiliser les 2 fonctions {{Rouge|getTouche()}} et {{Rouge|setEtatLed()}} pour réaliser un programme de digicode.
 
 
=={{Bleu|Cahier des charges}}==
 
 
Commençons pour définir les contraintes :
 
 
*On appuie sur la touche ON (touche '*') => la led rouge s'allume
 
*L'utilisateur doit alors saisir le code sur 4 chiffres
 
*On valide le code par la touche OK (touche '#')
 
*Si le code est bon la led verte s'allume pendant 10s, sinon la led rouge clignote pendant 10s
 
 
=={{Bleu|Codez !!}}==
 
 
Nous commençons par décrire le programme grâce à [http://fr.wikipedia.org/wiki/Organigramme_de_programmation l'algorigramme suivant :]
 
 
*initialiser i
 
*éteindre les leds
 
*si la touche apuyé est '*'
 
**allumer led rouge
 
**{{Rouge|répéter}}
 
***attendre plus de touches appuyées ( à l'aide d'un while(getTouche....); )
 
***{{Bleu|répéter}}
 
****lire clavier => touche    ( touche = getTouche(); !!! )
 
****{{Bleu|tant que touche<0}}
 
***si touche '*'
 
****réinitialiser i
 
***sinon
 
****sauvegarder touche dans un tableau
 
****incrémenter i
 
***{{Rouge|tant que i<4}}
 
**attendre plus de touches appuyés
 
**attendre appui sur touche
 
**si touche '#'
 
***vérifier le code
 
***si code valide
 
****allumer led verte pendant 10s
 
***sinon
 
****faire clignoter led rouge pendant 10s
 
 
 
Remarque : Utiliser un tableau pour mémoriser le code, ex :
 
 
<source lang=c> const int8_t code[4]={1,2,3,4};</source>
 
 
{{Question|Écrire le programme correspondant}}
 
 
=={{Bleu|Améliorations}}==
 
 
{{Todo|Il serait intéressant de proposer une procédure de changement du code.}}
 
 
 
{{Todo|Il est également intéressant de régler une durée maximum (4s) de saisie du code, en utilisant un timer.}}
 
 
={{Rouge|Buzzer}}=
 
 
=={{Bleu|Objectif}}==
 
Nous souhaitons utiliser le buzzer afin d'avoir une information sonore sur la touche du clavier appuyée.
 
 
Pour ce faire, chaque touche sera associée à une note de musique tel qu'indiqué dans le tableau suivant :
 
 
{| class="wikitable"
 
|-
 
! Touche || 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || * || #
 
|-
 
! Note || Do || Do# || Ré || Ré# || Mi || Fa || Fa# || Sol || Sol# || La || La# || Si
 
|-
 
! Fréquence (Hz) || 261,63 || 277,18 || 293,66 || 311,13 || 329,63 || 349,23 || 369,99 || 392 || 415,3 || 440 || 466,16 || 493,88
 
|-
 
! Période (µs)  || 3822  || 3608  || 3405  || 3214  || 3037  || 2863  || 2703  || 2551|| 2408  || 2273|| 2145  || 2025
 
|}
 
 
 
=={{Bleu|Programmons}}==
 
 
{{Question|Vous utiliserez le programme réalisé au tp précédent, et notamment la fonction {{Rouge|playnote(note,duree)}} pour jouer la note associée à chaque appui d'une touche}}
 
 
 
==Confinement 2020==
 
===Groupe S2d===
 
[https://jamboard.google.com/d/1hdVr_rijzIHJgFInHXutLj1upluVvkNezJuZOvchi1A/viewer Jamboard TP digicode]
 
====Clavier : lecture ligne (correction en C)====
 
<source lang=c>
 
#include <avr/io.h>
 
#include <util/delay.h>
 
 
#define ledR PC0
 
#define ledV PC1
 
 
int8_t lecture_ligne()
 
{
 
  int8_t ch;
 
  DDRD |= (1<<PD4)|(1<<PD5)|(1<<PD6) ;// commençons par lister les sorties sur le port D
 
  DDRB &=~( (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) ) ;    // puis les entrées sur le port B
 
  PORTD &=~( (1<<PD4)|(1<<PD5)|(1<<PD6) ) ;    // on place les sortie à l'état 0
 
  PORTB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) ;    // on active les résistances de pull-up sur les entrées
 
 
  _delay_ms(1);        // un délais est nécessaire pour l'activation des pull-ups
 
 
  ch = PINB & 0b00001111; // on récupère ensuite l'état des entrées
 
  switch (ch)
 
  {
 
    case  0b1111: return 0; // aucune touche
 
    case  0b1110: return 1; // L1
 
    case  0b1101: return 2; // L2
 
    case  0b1011: return 3; // L3
 
    case  0b0111: return 4; // L4
 
    // si autre cas, deux touches ou autre
 
    default : return -1;
 
  }
 
}
 
int main()
 
{
 
  int8_t ligne;
 
// setup
 
  DDRC |= (1<<ledR) | (1<<ledV);
 
// loop
 
  while(1)
 
  {
 
    ligne = lecture_ligne();
 
    switch(ligne) {
 
      case 0 :PORTC &=~ (1<<ledR);PORTC &=~ (1<<ledV);break;
 
      case 1 :PORTC |= (1<<ledR);PORTC &=~ (1<<ledV);break;
 
      case 2 :PORTC &=~ (1<<ledR);PORTC |= (1<<ledV);break;
 
      case 3 :PORTC |= (1<<ledR);PORTC |= (1<<ledV);break;
 
      default:PORTC &=~ (1<<ledR);PORTC &=~ (1<<ledV);break;
 
    }
 
    _delay_ms(100);
 
  }
 
}
 
</source>
 
====Correction Arduino====
 
<source lang=Arduino>
 
#include <avr/io.h>
 
#include <util/delay.h>
 
 
#define ledR PC0
 
#define ledV PC1
 
 
void setup() {
 
  DDRC |= (1<<ledR) | (1<<ledV);
 
  Serial.begin(9600);
 
}
 
 
int8_t lecture_ligne()
 
{
 
  int8_t ch;
 
  DDRD |= (1<<PD4)|(1<<PD5)|(1<<PD6) ;// commençons par lister les sorties sur le port D
 
  DDRB &=~( (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) ) ;    // puis les entrées sur le port B
 
  PORTD &=~( (1<<PD4)|(1<<PD5)|(1<<PD6) ) ;    // on place les sortie à l'état 0
 
  PORTB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3) ;    // on active les résistances de pull-up sur les entrées
 
 
  _delay_ms(1);        // un délais est nécessaire pour l'activation des pull-ups
 
 
  ch = PINB & 0b00001111; // on récupère ensuite l'état des entrées
 
  switch (ch)
 
  {
 
    case  0b1111: return 0; // aucune touche
 
    case  0b1110: return 1; // L1
 
    case  0b1101: return 2; // L2
 
    case  0b1011: return 3; // L3
 
    case  0b0111: return 4; // L4
 
    // si autre cas, deux touches ou autre
 
    default : return -1;
 
  }
 
}
 
 
void loop() {
 
  int8_t ligne,colonne,codeClavier;
 
  ligne=lecture_ligne();
 
  Serial.println(ligne);
 
  _delay_ms(100);
 
 
}
 
}
 
</source>
 
</source>

Version actuelle datée du 17 février 2023 à 16:20

Fiche résumé

Retour à la liste des Tps

Éléments de correction

Arduino-nano-pinout.png

Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino).

Pour ce TP, nous utilisons une carte arduino sans le shieldinfo

Matériel

Nous utiliserons :

  • 1 carte arduino NANO
  • 1 plaque à essais
  • 8 leds pour afficher une valeur
  • 2 leds verte/rouge pour le fonctionnement du digicode
  • 1 résistance de 330Ω par led
  • 1 clavier matriciel
  • fils M-M
  • fils M-F

Informations lumineuses

Câblage

Le digicode sera équipé de 2 voyants lumineux (rouge et vert).

On utilisera des résistances de 330Ω, les leds seront connectées en cathodes communes.

Todo.jpg Câbler sur une plaque à essais les leds :

  • les 2 leds pour le digicode
    • verte sur PC0
    • rouge sur PC1
  • 8 leds pour afficher une valeur
    • PD0 à PD7
    • mettre les leds dans "l'ordre" des broches


Utilisation des 8 leds

Nous utiliserons dans nos programmes les types de variable dont la taille est explicitement donnée

Le débogage d'un programme est fondamental, il existe différentes façons de le faire. Ici nous nous contenterons d'utiliser des leds pour afficher des informations sur l'exécution du programme.

Principe :
#include <avr/io.h>
#include <util/delay.h>

void clignote()
{
    PORTD=0;
    for (uint8_t i=0;i<5;i++)
    {
         PORTD ^= 0xFF;
         _delay_ms(50);
    }
}

int main()
{
    // config des sorties
    DDRD = 0xFF; // les 8  broches des leds en sortie

    // qques variables
    uint8_t val1 = 0;
    int8_t val2 = -1;
    uint8_t val3 = 255;
    uint16_t val4 = 256;

    while(1)
    {
        PORTD = val1;
        _delay_ms(2000);
        clignote();
        PORTD = val2;
        _delay_ms(2000);
        clignote();
        PORTD = val3;
        _delay_ms(2000);
        clignote();
        PORTD = val4;
        _delay_ms(2000);
        for (int i=0;i<10;i++) clignote();
    }
}

Question.jpg Indiquer l'affichage réalisé par chacune des lignes PORTD=valx

Les nombres négatifs sont représentés pas la méthodes des compléments à deux : https://fr.wikipedia.org/wiki/Compl%C3%A9ment_%C3%A0_deux ]

Decodage d'un clavier

Câblage

Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L0 à L3) et colonnes (C0 à C2) en vue de dessus :

PC2 PC3 PC4 PC5 PB0 PB1 PB2
L0 L1 L2 L3 C0 C1 C2

ArduinoClavier.png

L/C C0 C1 C2
L0 1 2 3
L1 4 5 6
L2 7 8 9
L3 * 0 #

ClavierMatricielPrincipe.png

Todo.jpg Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les colonnes seront reliées sur le port B et les lignes sur le port C (cf indications ci dessus)

Remarque : On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur.

Bluebg.png
Aidesmall.png
À propos de cette image

pullUp


2 étapes sont nécessaires pour activer une résistance de pullUp sur une broche :

  • Configurer la broche en entrée
    • pour une seule broche : DDRB &=~ (1<<PB1);
    • pour un groupe  : DDRB &=~ ((1<<PB1)|(1<<PB2)|(1<<PB3) ...);
  • Activer ensuite la/les résistance(s) de pullUp
    • pour une seule broche : PORTB |= (1<<PB1);
    • pour un groupe  : PORTB |= (1<<PB1)|(1<<PB2)|(1<<PB3) ...;

Principe de décodage

En utilisant un clavier matriciel, chaque touche n'est pas associé à une broche du µcontrôleur. Dans le cas présent, on passe de :

  • 12 entrées nécessaires si chaque touche était connectée directement
  • 7 broches nécessaires avec le clavier matriciel

L'intérêt évident est donc une réduction du nombre de broches nécessaires à l'utilisation du clavier.

L'inconvénient qui en résulte est la complexité relative du code pour trouver quelle touche est appuyée.

Le principe de décodage est symétrique entre lignes et colonnes. Détaillons donc le fonctionnement pour trouver sur quelle ligne une touche est appuyée :

  • On configure les broches colonnes en sortie.
  • On configure ces sorties à l'état 0
  • Les broches lignes sont en entrée
  • l'état des lignes dépend de l'appui sur un bouton :
    • si aucun bouton appuyé, les résistances de tirage donnent un état 1 sur les lignes
    • si on appui sur un bouton de la ligne0 (key 1/2/3), alors l'entrée ligne PC2 passe à l'état 0.
    • la valeur change suivant la ligne sur laquelle un bouton est appuyé
  • il suffit donc d'observer les 4 bits PC5..PC2 (que l'on note ici etat), et ainsi :
    • si PC5..PC2 = 1111 , pas de touche
    • si PC5..PC2 = 1110 , au moins une touche parmi 1/2/3
    • si PC5..PC2 = 1101 , au moins une touche parmi 4/5/6
    • ...

Indice de ligne

Question.jpg Ecrire et tester le programme lecture_ligne() qui renvoie le numéro de ligne sur laquelle un bouton est appuyé

  • La validation se fera en utilisant des leds connectées sur le port C :
    • On utilisera les 8 leds du PORTD pour afficher le résultat
    • par ex : PORTC = lecture_ligne();
int8_t lecture_ligne()
{
  int8_t etatEntrees;
  DDRB ?= .... ;    // commençons par lister les sorties sur le port B
  DDRC ?= .... ;    // puis les entrées sur le port C
  PORTB?=..... ;    // on place les sortie à l'état 0
  PORTC?= .... ;    // on active les résistances de pull-up sur les entrées

  _delay_ms(1);        // un délai est nécessaire pour l'activation des pull-ups

  etatEntrees = PINC & ??; // on récupère ensuite l'état des entrées en cachant les bits non utiles
  switch (etatEntrees)
  {
     case  : return 0; // L0 (appui sur l'une des touches 1/2/3 )
     case  : return 1; // L1
     case  : return 2; // L2
     case  : return 3; // L3
     // si autre cas, pas de touches deux touches ou autre
     default : return -1;
  }
}

Indice de colonne

Question.jpg De la même façon, écrire et tester la fonction lecture_colonne() qui permettra d'obtenir le numéro de colonne sur laquelle un bouton est appuyé.


Touche appuyée

Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous :

int8_t touches[4][3] = { // tableau de char à 2 dimensions
  {1,2,3},
  {4,5,6},
  {7,..},
  {,,11}
};

int8_t getTouche();
La valeur retournée sera :
  • -1 si pas de touches (ou plusieurs) appuyées
  • la valeur correspondant à la touche pour les chiffres
  • 11 pour le #
  • 10 pour l' *

Question.jpg Écrire cette fonction en vous servant bien évidemment des 2 fonctions précédentes et pourquoi pas du tableau "touches" complété.

int8_t getTouche()
{
   ....
}