我正试图让我的PIC18F2550上的Timer1每秒触发中断以进行倒计时。到目前为止,我已经能够正确地建立中断优先级,以及其他设置,但是我的ISR只会触发一次。我已经设置了我的程序来将倒计时中剩下的秒数打印到LCD上,因此对用户来说很明显已经过了多少个中断。我已经确保在ISR中清除正确的中断标志,因为这是大多数人在谷歌上遇到相同问题的问题的根源,但这并没有解决它。关于我的程序的其他所有内容到目前为止都运行良好。
(为了测试正确的优先级是否已被触发,低计数而不是向下计数)
这是代码段
//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秒。
答案 0 :(得分:2)
您没有正确完成ISR例程!
#pragma code low_vector = 0x18
void lowvectinterrupt(void){
_asm goto lowisr _endasm
}
执行ISR后,必须再次打开中断,因此必须使用lowvectinterrupt
指令完成RETFIE
,并且必须至少恢复标志和WREG寄存器。
Normaly在ISR例程中声明如下:
static void interrupt isr(void)
{
}