EDIT : j'ai changé le titre : en fait ma requête se résume à "comment mettre l'adresse d'une fonction (pointeur?) dans la case mémoire correspondant à une interruption"...
Bon, voilà, après avoir galéré dans tous les sens, la fonction attachInterrupt() n'a jamais marché sur ma mega2560.
void raz_ph123() {
digitalWrite(13, !digitalRead(13));
}
void setup(){
pinMode(13, OUTPUT);
pinMode(21, INPUT);
digitalWrite(13, LOW);
attachInterrupt (0, raz_ph123, RISING);
sei(); // avec ou sans, ça marche pas.
}
void loop(){
}
On ne peut pas faire plus simple : la led 13 doit clignoter deux fois moins vite que le signal carré sur la broche 21 (INT0), mais un coup elle est allumée, un reset et elle s'éteint... assez aléatoire! (pour info, mon impultion est à 50Hz, 0 à 5V bien propre, d'une durée de 1ms).
Puis j'ai fait ça :
ISR(INT0_vect){
digitalWrite(13, !digitalRead(13));
}
void setup(){
pinMode(13, OUTPUT);
pinMode(21, INPUT);
digitalWrite(13, LOW);
EICRA = 0x03; // INT0 sur RISING
EIMSK = 0x01; // Activer INT0
sei();
}
void loop(){
}
Et là, ça marche!
résolu? ben non, car comment je fais pour changer ma proc d'interruption? Quelqu'un a une idée pour aller écrire l'adresse d'une fonction dans l'adresse 0x0002 (adresse du pointeur INT0) un truc genre :
void maFonction(){
(...)
}
INT0_pointer = maFonction;
help please!
EDIT : je viens de regarder la lib WInterrupt.c :
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc;
switch (interruptNum) {
#if defined(EICRA) && defined(EICRB) && defined(EIMSK) // config MEGA2560
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 4:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
break;
case 5:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
break;
case 0:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
break;
case 1:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
#endif
}
}
}
en gros, attachInterrupt(int, fonction, mode) renseigne les registres du gestionnaire d'interruption comme je l'ai fait, et assigne fonction à un pointeur. Mais dans mon cas, quand je demande interrupt_num = 0, ça active l'INT4. Un peu navrant, non? Petite vérif : en effet, attachInterrupt fonctionne mais en envoyant mon signal sur la broche INT4... ET CA ME PLAIT PAS DU TOUT!
ensuite, on trouve :
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_2])
intFunc[EXTERNAL_INT_2]();
}
A chaque fois que je tente un truc qui sort du blink, je trouve des erreurs à foison dans les libs du core arduino! Et après on s'étonne que je veuille toujours passer par les registres!!!
donc en cours de programme, quand on appelle attachInterrupt(), ça modifie juste le pointeur intFunc[EXTERNAL_INT_2].
Mais moi, je trouve plus sûr et plus précis d'aller directement écrire l'adresse d'une fonction dans la case mémoire "INT0" (voir tableau page 105 ou chapitre 14.1 du datasheet de ATMEGA2560.pdf). Mais comment qu'on fait? il faudrait trouver le mot clé qui correspond à l'adresse mémoire 0x0002...
Je vais chercher comment ça se passe pour PORTA = 0xFF par exemple, car PORTA renvoie sur l'adresse 0x02 (bas de page 415 du PDF), il doit y avoir une constante qui correspond à l'adresse de mon vecteur!