I'm trying to get the Timer1 on my PIC18F2550 to fire interrupts every second for countdowns. So far I've been able to establish interrupt priority correctly, as well as other settings, however my ISR only fires once. I've set up my program to print the amount of seconds left in the countdown onto the LCD, so it's obvious to the user how many interrupts have passed. I've made sure to clear the proper interrupt flags in the ISR, since that's what was the source of the problem for the majority of the people having the same issue on google, but this didn't fix it. Everything else about my program has worked fine so far.

(For the sake of testing whether or not the right priority has fired, low counts up instead of down)

Here's the code snippet

//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);
    }
}

Ultimately I'm staring at an LCD with "31" on it. It's likely a single flag that I'm not setting properly that's causing nothing to work right, but as far as I've checked everything's being enabled and being cleared properly. What am I doing wrong? I'd appreciate any help, this is enormously frustrating.

Also: I've cleared all breakpoints so it's not halting anywhere, and program the latest version on compile. So I've ruled out running an old busted version of the code.

Edit: To clarify, this code is only for functionality; it will not fire every second but rather much faster. Once I get it working I'll play the overflow counting to get it to 1 second.

有帮助吗?

解决方案

You are not finishing ISR routine correctly!

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

After ISR execution the interrupt must be switched on again, so the lowvectinterrupt must be finished with RETFIE instruction and at least flags and WREG register must be restored.

Normaly is in ISR routine declared like:

static void interrupt isr(void)
  {

  }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top