2013-03-03 2 views
1

J'essaye d'obtenir le Timer1 sur mon PIC18F2550 pour déclencher des interruptions chaque seconde pour des compte à rebours. Jusqu'à présent, j'ai pu établir la priorité d'interruption correctement, ainsi que d'autres paramètres, mais mon ISR ne se déclenche qu'une seule fois. J'ai mis en place mon programme pour imprimer la quantité de secondes restantes dans le compte à rebours sur l'écran LCD, il est donc évident pour l'utilisateur combien d'interruptions sont passées. J'ai veillé à effacer les drapeaux d'interruption appropriés dans les ISR, puisque c'est la source du problème pour la majorité des personnes ayant le même problème sur google, mais cela n'a pas résolu le problème. Tout le reste de mon programme a bien fonctionné jusqu'à présent.Interruption sur les incendies PIC18 seulement une fois

(Par souci de vérifier si oui ou non la priorité à droite a tiré, un faible nombre au lieu de descendre)

est ici l'extrait de code

//First testing program for PIC18F2550 

#include <p18f2550.h> 
#include <stdlib.h> 
#include <delays.h> 

#define _XTAL_FREQ 4915200 

#pragma config PLLDIV = 1 
#pragma config CPUDIV = OSC1_PLL2 
#pragma config FOSC = XT_XT 
#pragma config MCLRE = ON 
#pragma config BOR = OFF 
#pragma config WDT = OFF 
#pragma config IESO = OFF 
#pragma config PBADEN = OFF 
#pragma config LVP = OFF 

unsigned char Countdown = 30; (other vars, fcns omitted) 

#pragma code high_vector = 0x08 
void highvectinterrupt(void){ 
    _asm goto highisr _endasm 
} 

#pragma code low_vector = 0x18 
void lowvectinterrupt(void){ 
    _asm goto lowisr _endasm 
} 


(...) 

void highisr(void){ 
    Countdown--; 
    PIR1bits.TMR1IF = 0; 
} 

void lowisr(void){ 
    Countdown++; 
    PIR1bits.TMR1IF = 0; 
} 

void main(void){ 
    UCONbits.USBEN=0; //Setup I/O 
    UCFGbits.UTRDIS=1; 
     OSCCONbits.SCS1 = 0; 
     OSCCONbits.SCS0 = 0; 
    BAUDCONbits.TXCKP=0; 
     SPBRG = 0x3F; //1200 baud 
    TRISA = 0x00; 
    TRISB = 0xFF; 
    TRISC = 0x00;  

    beephigh(); //Done, clear the line and beep speaker 1 

    LATA = 0;    //reset 
    LATC = 0; 
    Delay10KTCYx(8); 
    LATAbits.LATA2 = 1;  //load the reset 
    Delay10KTCYx(8); 
    LATAbits.LATA3 = 1;  //stop reset 
    LATAbits.LATA4 = 1; 
    LATAbits.LATA2 = 0; 
    Delay10KTCYx(123); 

    initlcd(); 

    Delay10KTCYx(10); 

    setupUI(); 

    LATAbits.LATA0 = 0; //Done, clear the line and beep speaker 2 
    beeplow(); 

    INTCON = 0;    //Reset high interrupt flags and disable interrupts 
    T1CON = 0x11110100;  //16 bit r/w; internal system clock; 8x prescale; timer1 osc disabled 
    TMR1H = 0;    //Clear the counting register 
    TMR1L = 0; 
    PIE1bits.TMR1IE = 1; //Enable Interrupts on Timer1 
    PIR1bits.TMR1IF = 0; //Clear the flag if set 
    RCONbits.IPEN = 1;  //Enable priority levels 
    INTCON2bits.TMR0IP = 0; //Timer0 on low priority 
    IPR1bits.TMR1IP = 0; //Timer1 on low priority 
    IPR1bits.RCIP = 1;  //RS232 on high priority 
    INTCONbits.GIEL = 1; //Enable all low priority interrupts 
    INTCONbits.GIEH = 1; //Enable all high priority (must be enabled for low priority) 
    T1CONbits.TMR1ON = 1; //Turn Timer1 on  

    while(1){ //Idle and refresh screen 
     Delay10KTCYx(8); 
     bin2ascii(Countdown); 
     cmdlcd(0xCE); 
     putclcd(ConvRegTens); 
     putclcd(ConvRegOnes); 
    } 
} 

En fin de compte, je suis à regarder un écran LCD avec "31" dessus. C'est probablement un seul drapeau que je ne mets pas correctement qui ne fait rien fonctionner correctement, mais pour autant que j'ai vérifié, tout est activé et effacé correctement. Qu'est-ce que je fais mal? J'apprécierais toute aide, c'est énormément frustrant. En outre, j'ai effacé tous les points d'arrêt afin qu'ils ne s'arrêtent nulle part et programme la dernière version lors de la compilation. J'ai donc exclu l'exécution d'une ancienne version du code.

Éditer: Pour clarifier, ce code est seulement pour la fonctionnalité; il ne se déclenchera pas toutes les secondes mais plutôt beaucoup plus vite. Une fois que je l'aurai fonctionné, je jouerai le compte de débordement pour l'obtenir à 1 seconde.

Répondre

2

Vous ne terminez pas la routine ISR correctement!

#pragma code low_vector = 0x18 
void lowvectinterrupt(void){ 
    _asm goto lowisr _endasm 
} 

Après l'exécution de l'interruption ISR doit être sous tension à nouveau, de sorte que le lowvectinterrupt doit être terminé avec l'instruction RETFIE et au moins drapeaux et registre WREG doit être restauré.

est Normaly dans la routine ISR déclaré comme:

static void interrupt isr(void) 
    { 

    } 
+1

Vous aviez raison, je l'ISR mal Initialisation. J'ai creusé un peu plus et j'ai trouvé [this] (http://www.xargs.com/pic/c-faq.html#c18isr) comme exemple de la façon de faire des interruptions de priorité en C. Merci. –

+1

@Bamako: Nice FAQ. Lisez attentivement également: [Dois-je utiliser les priorités d'interruption sur le PIC18?] (Http://www.xargs.com/pic/c-faq.html#intpri) –

Questions connexes