1

PIC18F2550のTimer1を取得して、カウントダウンのために毎秒割り込みを発生させようとしています。これまでのところ、割り込み優先度やその他の設定を正しく確立できましたが、ISRは1回しか起動しません。カウントダウンの残り秒数をLCDに出力するようにプログラムを設定したので、何回の割り込みが経過したかがユーザーにわかります。ISRで適切な割り込みフラグをクリアするようにしました。これが、Googleで同じ問題を抱えている大多数の人々にとって問題の原因であったためですが、これでは修正されませんでした。私のプログラムに関する他のすべては、これまでのところうまく機能しています。

(正しい優先順位が実行されたかどうかをテストするために、低いカウントはダウンではなくアップします)

これがコードスニペットです

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

最終的には「31」が付いたLCDを見つめています。正しく設定されていない単一のフラグが正しく機能しない可能性がありますが、すべてが有効になっていて正しくクリアされていることを確認した限りです。私は何が間違っているのですか?助けていただければ幸いです。これは非常に苛立たしいことです。

また、すべてのブレークポイントをクリアしたので、どこでも停止せず、コンパイル時に最新バージョンをプログラムします。そのため、古いバストバージョンのコードを実行することを除外しました。

編集:明確にするために、このコードは機能のためだけのものです。毎秒発砲するのではなく、はるかに速く発砲します。動作するようになったら、オーバーフローカウントを再生して1秒にします。

4

1 に答える 1

2

ISR ルーチンを正しく終了していません!

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

ISR の実行後、割り込みを再度オンにするlowvectinterrupt必要があるため、命令で終了する必要がRETFIEあり、少なくともフラグと WREG レジスタを復元する必要があります。

通常は、次のように宣言された ISR ルーチンにあります。

static void interrupt isr(void)
  {

  }
于 2013-03-03T00:36:03.600 に答える