Salut la communauté!
Ce post était au départ une question, mais en cours de route, j'ai résolu la chose. C'est donc devenu une info à prendre pour ceux qui auront ce genre de souci de PCINT.
Alors voilà, je parlais de gérer un clavier matriciel par les PCINT...
en gros, on a 8 fils du clavier que j'ai relié au port K du 2560 (entrées analogiques A8 à A16). la méthode est simple : les 4 lignes sur K3:0 et les 4 colonnes sur K7:4. on initialise le port K pour avoir les colonnes en sorties à 0, et les lignes en entrée avec pull-up. on active PCINT2 sur les lignes, il ne doit donc rien se passer tant qu'on n'appuie pas sur une touche, et on doit lire PINK = 0x0F. si on appuie sur une touche, cela mettra la ligne correspondante à 0, donc déclenchement de PCINT2.
Dans l'ISR (routine appelée par PCINT2), on relève donc les lignes, puis on inverse le sens entrées / sorties du port K ainsi que les pull-up, puis on relève les colonnes et on remet le port K comme à l'initialisation. on obtient alors un couple colonnes / ligne contenant un 0 sur la ligne et la colonne de la touche appuyée, des 1 partout ailleurs. Lorsqu'on relâche la touche, même interruption, mais on ne lit que des 1, puisqu'aucune touche n'est en contact.
Super!
Ben non, car ma PCINT2 se déclenche en continu, même en débranchant le clavier (c'est pour dire!). Vous remarquerez que j'utilise également les PCINT0 du port B pour détecter 5 boutons poussoirs, et là, ça marche impeccable!
volatile kb_key, btn_key; // variables contenant l'état des clavier / boutons
void keyB_init(){
DDRB &= 0xE0; // B4:0 input : 5 boutons (pin 50, 51, 52, 53 et 10)
DDRK = 0xF0; // clavier : lignes en entrée, colonnes en sortie
PORTB |= 0x1F; // pull-up sur boutons
PORTK = 0x0F; // colonnes à 0 et pull-up clavier lignes
PCMSK2 = 0x0F; // active PCINT19:16 (lignes clavier)
PCMSK0 = 0x1F; // active PCINT4:0 (boutons poussoirs)
PCICR = 0x05; // active PCI2 et PCI0;
}
ISR(PCINT0_vect){ // interruption boutons
btn_key = PINB & 0x1F; // lecture des 5 boutons
PORTA ^= 0x04; // led rouge témoin de déclenchement de PCINT2
}
ISR(PCINT2_vect){ // interruption clavier
PCICR &=0xFB; // désactive PCINT2
kb_key = PINK & 0x0F; // lecture lignes
DDRK = 0x0F; // inverse les I/O clavier : lignes en sortie et colonnes en entrée
PORTK = 0xF0; // lignes à 0 et pull-up sur colonnes
delay(1);
kb_key += PINK & 0xF0; // lecture colonnes
DDRK = 0xF0; // remet les lignes en entrée, colonnes en sortie
PORTK = 0x0F; // colonnes = 0 et pull-up sur lignes
PCICR |=0x04; // réactive PCINT2
PORTA ^= 0x02; // led verte témoin de déclenchement de PCINT2
}
Il semblerait que mes déclenchements intempestifs et continus de PCINT2 soient dus à mes manips sur le port K dans l'ISR, pourtant, je désactive bien l'interruption PCINT2 avant de toucher à quoi que ce soit (sinon, l'interruption est prise en compte et sera exécutée dès la sortie de l'ISR)! je vais essayer en désactivant aussi les masques d'interruption dans PCMSK2.
L'ajout de la ligne
PCMSK2 = 0; // désactive toutes les PCINT23:16
(traitement isr)
PCMSK2 = 0x0F; // résactive les PCINT19:16
dans l'ISR ne change rien... ma led verte clignote toujours comme une tarée. pareil si juste avant de sortir de l'ISR je fais un "clear" du flag de PCINT2, ça ne change rien.
finalement, juste avant de réactiver les PCINT, j'ai ajouté un "delay(10);", et là, miracle, ça marche! en fait, la solution est bien là : il y a un délai entre un PORTK=qqchose et l'apparition de ce qqchose sur la pin du composant, ce qui fait que si on réactive trop tôt les INT, alors les pins du port apparaîtront après la réactivation du PCINT, donc la redéclenche... ma led verte s'allume au démarrage, car dans l'initialisation du port K, je n'attends pas assez avant d'activer la PCINT, elle est donc déclenchée une fois...
j'ai résolu mon pb...