« Utiliser les PIC 16F et 18F/Exercices/Les ports et le langage C » : différence entre les versions
m Robot : Changement de type cosmétique |
Aucun résumé des modifications |
||
Ligne 1 : | Ligne 1 : | ||
{{Exercice |
|||
| idfaculté = sciences de l'ingénieur |
|||
| numéro = 6 |
|||
| leçon = [[Utiliser les PIC 16F et 18F]] |
|||
| niveau = 15 |
|||
| titre = Les sous-programmes en assembleur |
|||
| précédent = [[../Introduction au langage C/]] |
|||
| suivant = [[../Le Timer0 des 16FXXX et le langage C/]] |
|||
}} |
|||
==Exercice 1== |
==Exercice 1== |
||
=== Interfaçage d'un clavier 12 touches === |
=== Interfaçage d'un clavier 12 touches === |
Version du 6 mars 2012 à 20:36
Exercice 1
Interfaçage d'un clavier 12 touches
Sur un PC, le clavier est complètement décodé. C'est-à-dire que lorsqu'une touche est appuyée, sa position sur le clavier est envoyée sur la liaison PS2. Le fait d'envoyer la position et non le code ASCII permet de gérer les claviers en divers langues.
Pour de petites applications, on utilise un clavier à 12 touches. Il est composé de simples contacts et le décodage est réalisé par le système informatique. Avec seulement 8 touches, un PORT de 8 bits en entrée suffit. Si le clavier possède plus de 8 touches, il faut:
- soit utiliser d'avantage d'entrées,
- soit multiplexer les entrées en deux étapes.
En utilisant 4 fils pour les lignes et 4 fils pour les colonnes, on peut différencier par croisement 16 touches. On utilise donc 8 fils reliés à 8 bits d'un PORT pour 16 touches. Pour nos 12 touches on peut câbler comme indiqué ci-dessus.
Il s'agit ensuite de procéder en deux phases, une pour la détection de la colonne et une autre pour la détection de ligne.
Question 1 : détermination du numéro de colonne Programmer les directions avec TRISB (PB6-PB3 en sortie et PB2-PB0 en entrée).
Tester si une touche est appuyée. Si oui sauvegarder dans une variable la valeur lue sur PORTB puis transformer cette valeur en numéro de colonne (0 à gauche et 2 à droite)
Quel est le code correspondant : sous-programme char lecture_colonne()
Question 2 : détermination du numéro de ligne
Programmer les directions avec TRISB (PB6-PB3 en entrée et PB2-PB0 en sortie).
Tester si une touche est appuyée. Si oui sauvegarder dans une variable la valeur lue sur PORTB puis transformer cette valeur en numéro de ligne (0 en haut et 3 en bas)
Quel est le code correspondant : sous-programme char lecture_ligne()
Question 3 : détermination du caractère
À partir des deux informations précédentes transformer le numéro de colonne et le numéro de ligne en caractère correspondant sur le clavier : '1' ou '2' ou ... ou '0' ou '#'
Les bits RB4-RB7 peuvent servir à déclencher une interruption (RB port change Interrupt). Si l'on veut utiliser cette interruption il faudrait câbler notre clavier autrement. Les interruptions seront abordées plus loin.
Le schéma indique que l'appui d'une touche fait un contact entre un fil horizontal et un fil vertical.
Question 1 : on met alors tous les fils verticaux à 0 (3 bits de poids faible du PORTB) et on cherche sur quelle touche on a appuyé en cherchant où est le 0 ? Cela nous donnera une colonne.
// question 1 TD8
#define NOTAKEY 127
// colonne 1 à gauche
char lecture_colonne(){
char ch;
TRISB=0x78; // 0111 1000
PORTB = PORTB & 0x87; // B3, B4,B5 et B6 mis à 0
ch = PORTB & 0x07; // on ne garde que les bits intéressants B0, B1 et B2
switch (ch) {
case 7 : return 0;//aucune touche
case 3 : return 1;//a gauche
case 5 : return 2;// au milieu
case 6 : return 3;//a droite
// si autre cas, deux touches ou autre
default : return NOTAKEY;
}
}
Question 2 : on met alors tous les fils horizontaux à 0 (4 bits p6...p3 du PORTB) et on cherche sur quelle touche on a appuyé en cherchant où est le 0 ? Cela nous donnera la ligne.
// #define NOTAKEY 127
// ligne 1 en haut
char lecture_ligne(){
char ch;
TRISB = 0x07; // 0000 0111
PORTB = PORTB & 0xF8; //B0, B1 et B2 mis à 0
ch=PORTB & 0x78; // on ne garde que les bits intéressants B3, B4,B5 et B6
switch (ch) {
case 0x78 : return 0;//aucune touche
case 0x38 : return 1;//en haut = 0011 1000
case 0x58 : return 2;// au milieu = 0101 1000
case 0x68 : return 3;// au milieu = 0110 1000
case 0x70 : return 4;//en bas = 0111 0000
// si autre cas, deux touches ou autre
default : return NOTAKEY;
}
}
Question 3 : la conversion ligne colonne vers caractère paut se faire avec un simple tableau 2 dimensions comme suit :
#include <htc.h> // a modifier si autre compilateur que Hitech C
#define NOTAKEY 127
char lecture_colonne();
char lecture_ligne();
char tabconv[4][3]={{'1','2','3'},{'4','5','6'},{'7','8','9'},{'*','0','#'}};
void main (void){
char col,lign,res;
do {
col=lecture_colonne();
}while (col == NOTAKEY || col == 0);
do {
lign=lecture_ligne();
}while (col == NOTAKEY || col == 0);
res=tabconv[lign-1][col-1];
// on fait ce que l'on veut du résultat.
while(1);
}
On fait une attente de touche qui ne permet pas de faire autre chose !!! Il est naturellement possible de ne pas enfermer les "lecture_colonne()" et "lecture_ligne()" dans un boucle. Cette façon de faire est laissée au lecteur.
Exercice 2 (d'après les TPs)
Le PORTB est relié à un ensemble de LEDs permettant la réalisation de chenillards. Un chenillard est donné par le programme suivant :
// MikroC
main(){
int i;
TRISB=0x00; // 0 = sorties
for(;;) {
for(i=0;i<6;i++) {
PORTB=(0x03<<i|0xC0>>i);
Delay_ms(1000);
}
}
}
Compléter la suite des états de ce chenillard (ceux où une ou plusieurs leds sont allumées).
- 11000011 (avec i = 0)
- 01100110 (avec i = 1)
- 00111100 (avec i = 2)
- 00011000 (avec i = 3)
- 00111100 (avec i = 4)
- 01100110 (avec i = 5)
- 11000011 retour au début (avec i = 0)
- 01100110 (avec i = 1)
- 00111100 (avec i = 2)
....