2013-03-03 4 views
1

카운트 다운을 위해 매초마다 인터럽트를 발생시키는 PIC18F2550에서 Timer1을 가져 오려고합니다. 지금까지는 인터럽트 우선 순위를 올바르게 설정할 수 있었지만 다른 설정과 마찬가지로 ISR은 한 번만 실행됩니다. 카운트 다운에서 남은 시간 (초)을 LCD에 출력하도록 프로그램을 설정 했으므로 얼마나 많은 인터럽트가 경과했는지 사용자에게 분명합니다. ISR에서 적절한 인터럽트 플래그를 지우는 것이 확실합니다. 그 이유는 ISR이 ISG에서 동일한 문제를 겪고있는 대다수의 사람들에게 문제의 원인 이었기 때문입니다.하지만이 문제를 해결하지는 못했습니다. 지금까지 내 프로그램에 관한 모든 것이 잘 돌아갔다. PIC18에 대한 인터럽트는 한 번만 발생합니다.

은 (오른쪽 우선 해고 여부 테스트를 위해, 낮은 카운트까지 대신 아래)

는 여기에 내가 가진 LCD를 응시하고있어 코드 궁극적으로

//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". 내가 제대로 설정하지 않은 단일 플래그 일 가능성이 있습니다. 즉, 아무 것도 올바르게 작동하지 않을 수 있지만, 모든 항목이 활성화되어 있고 올바르게 지워졌는지 확인한 것입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 나는 어떤 도움을 주셔서 감사합니다, 이것은 엄청난 좌절입니다.

기타 : 모든 중단 점을 지워서 어디서나 중단되지 않고 컴파일시 최신 버전을 프로그래밍하십시오. 그래서 나는 코드의 낡은 버전을 운영하는 것을 배제했다.

편집 : 명확히하기 위해이 코드는 기능만을위한 것입니다. 매초마다 발사되는 것이 아니라 오히려 더 빨리 발사됩니다. 일단 작동 시키면 오버 플로우 카운팅을 1 초가 걸리게 할 것입니다.

답변

2

ISR 루틴을 올바르게 완료하지 못했습니다!

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

ISR이 실행되면 인터럽트가 다시 전환해야하므로 lowvectinterrupt 복원해야 RETFIE 명령어와 상기 플래그 및 WREG 레지스터에 완료되어야한다. 당신이 옳았

static void interrupt isr(void) 
    { 

    } 
+1

, 나는 ISR 잘못 초기화되었습니다

은 Normaly 같은 선언 ISR 루틴입니다. 좀 더 파고 들었고 C에서 우선 순위 인터럽트를 수행하는 방법에 대한 예로서 [this] (http://www.xargs.com/pic/c-faq.html#c18isr)를 발견했습니다. 감사합니다. –

+1

@Bamako : 좋은 FAQ. 조심스럽게 읽으십시오 : [PIC18에서 인터럽트 우선 순위를 사용해야합니까?] (http://www.xargs.com/pic/c-faq.html#intpri) –