//基於MCC18編譯器,使用HI-PICC不可用 //-------------------------------------------- #include <p18F452.h> //---------------------------------------------------------------------------- void main (void); void InterruptHandlerHigh (void); unsigned int Timeout; //---------------------------------------------------------------------------- // Main routine void main () { Timeout = 0; INTCON = 0x20; //disable global and enable TMR0 interrupt INTCON2 = 0x84; //TMR0 high priority RCONbits.IPEN = 1; //enable priority levels TMR0H = 0; //clear timer TMR0L = 0; //clear timer T0CON = 0x82; //set up timer0 - prescaler 1:8 INTCONbits.GIEH = 1; //enable interrupts TRISD = 0; /* configure PORTD for output */ PORTD=0X00; while (1) { if (Timeout == 1) { //timeout? Timeout = 0; //clear timeout indicor PORTD++; //PORTD端口二進制計數 } } } PIC18F452定時器中斷@ZSTU //---------------------------------------------------------------------------- // High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm } //---------------------------------------------------------------------------- // High priority interrupt routine #pragma code #pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () { if (INTCONbits.TMR0IF) { //check for TMR0 overflow INTCONbits.TMR0IF = 0; //clear interrupt flag Timeout = 1; //indicate timeout } } //----------------------------------------------------------------------------
PIC18F4520單片機提供多個中斷源及一個中斷優先級功能,可以給大多數中斷源分配高優先級或者低優先級.高優先級中斷向量地址為0008H,低優先級中斷向量地址為0018H。高優先級中斷事伯將中斷所有可參正在進行的低優先級中斷。
有10個寄存器用於控制中斷的操作。它們是:
RCON
INTCON
INTCON2
INTCON3
PIR1和PIR2
PIE1和PIE2
IPR1和IPR2
通常,用三個位控制中斷源的操作。
標志位 表明發生了中斷事件
使能位 允許程序跳轉轉到中斷向量地址處執行(當標志位置1時)
優先級 用於選擇是高優先級還是低先級,通過將IPEN位(RCON<7>)置1,可使能中斷優先級功能。當使能中斷優先級時,有2位可使能全局中斷。將GIEH位(INTCON<7>)置1,可使能所有優先級位置1(高優先級)的中斷。將GIEL位(INTCON<6>)置1,可使能所有優先級位清零(低優先級)的中斷。
當中斷標志位、使能位以及相應的全局中斷使能位均被置1時,程序將立即跳轉到中斷地址0008H或0018H,具體地址取決於優先級位的設置。通過設置相應的使能位可以禁止單個中斷。
注意:系統復位時IPEN位為零(默認狀態)時,便會禁止中斷優先級功能,此時中斷與PIC16系統中檔單片機相兼容。在兼容模式下,所有中斷均跳轉到地址0008H執行。
下面是在SP9608-PIC增強型單片機開發板利用PIC18F4520單片機來實現的數字頻率計數器功能,程序中使用了T0用為外部信號源輸入,通TMR0來實現對信號源的頻率計數。TMR3作為定時器,來產生1mS數碼管掃描時基和1S秒時基信號。為了提高頻率計數的准確度,采用中斷嵌套技術來完成,將TMR3產生1mS的定時信號作為高優先級中斷,TMR0作為頻率計數溢出中斷作為低先級中斷。源程序采用MCC18編譯器和MPLAB7.50版本的集成開發環境,調試工具采用ICD2;具體源程序如下:
系統時鍾:采用外部的12MHz晶振經過內部PLL的4倍頻到48MHz。(HS-PLL配置位)
1 #include <p18cxxx.h> 2 #define TRUE 1 3 #define FALSE 0 4 #define HIGH 1 5 #define LOW 0 6 rom unsigned char LEDDATA[]= 7 { 8 0x3F,0x06,0x5B,0x4F,0x66, 9 0x6D,0x7D,0x07,0x7F,0x6F, 10 0x40,0x00, 11 }; 12 struct TIMER_STRUCT 13 { 14 unsigned int Interval; 15 unsigned char Enable; 16 }; 17 struct TIMER_STRUCT Timer1S; 18 struct T0_T1_STRUCT 19 { 20 unsigned int High_Byte; 21 unsigned int Low_Byte; 22 unsigned long Result; 23 }; 24 struct T0_T1_STRUCT My_T0,My_T1; 25 struct LED_STRUCT 26 { 27 unsigned char DotPointer; 28 unsigned char ScanPointer; 29 unsigned char Buffer[8]; 30 }; 31 struct LED_STRUCT NumberLED; 32 void PIC18F_High_isr (void); 33 void PIC18F_Low_isr (void); 34 #pragma code high_vector_section=0x8 35 void high_vector (void) 36 { 37 _asm goto PIC18F_High_isr _endasm 38 } 39 #pragma code low_vector_section=0x18 40 void low_vector (void) 41 { 42 _asm goto PIC18F_Low_isr _endasm 43 } 44 #pragma code 45 //---中斷高優先級---// 46 #pragma interrupt PIC18F_High_isr 47 void PIC18F_High_isr (void) 48 { 49 if(TRUE==PIR2bits.TMR3IF) 50 { 51 PIR2bits.TMR3IF=FALSE; 52 TMR3H=(65536-11965)/256; 53 TMR3L=(65536-11965)%256; 54 55 if(FALSE==Timer1S.Enable) 56 { 57 Timer1S.Interval++; 58 if(1000==Timer1S.Interval) 59 { 60 T0CONbits.TMR0ON=FALSE; 61 Timer1S.Interval=0; 62 Timer1S.Enable=TRUE; 63 } 64 } 65 66 if(LOW==LATAbits.LATA0)LATAbits.LATA0=HIGH; 67 else LATAbits.LATA0=LOW; 68 69 LATD=LEDDATA[NumberLED.Buffer[NumberLED.ScanPointer]]; 70 LATE=NumberLED.ScanPointer; 71 NumberLED.ScanPointer++; if(NumberLED.ScanPointer==sizeof(NumberLED.Buffer))NumberLED.ScanPointer=0; 72 } 73 } 74 //---中斷低優先級---// 75 #pragma interruptlow PIC18F_Low_isr 76 void PIC18F_Low_isr (void) 77 { 78 if(TRUE==INTCONbits.TMR0IF) 79 { 80 INTCONbits.TMR0IF=FALSE; 81 My_T0.High_Byte++; 82 } 83 84 } 85 void main(void) 86 { 87 unsigned int i; 88 unsigned long temp; 89 90 Timer1S.Enable=FALSE; 91 Timer1S.Interval=0; 92 My_T0.High_Byte=0; 93 My_T0.Low_Byte=0; 94 My_T1.High_Byte=0; 95 My_T1.Low_Byte=0; 96 for(i=0;i<sizeof(NumberLED.Buffer);i++)NumberLED.Buffer[i]=0; 97 NumberLED.ScanPointer=0; 98 NumberLED.DotPointer=0; 99 TRISAbits.TRISA0=0; 100 LATAbits.LATA0=0; 101 TRISD=0; 102 LATD=0; 103 TRISE=0; 104 LATE=0; 105 T0CONbits.TMR0ON=FALSE; 106 TMR0L=0; 107 TMR0H=0; 108 T0CONbits.T0CS=1; 109 T0CONbits.T0SE=0; 110 T0CONbits.PSA=1; 111 T0CONbits.T08BIT=1; 112 INTCONbits.T0IF=FALSE; 113 INTCONbits.T0IE=TRUE; 114 T0CONbits.TMR0ON=TRUE; 115 T3CON=0x00; 116 TMR3H=(65536-12000)/256; 117 TMR3L=(65536-12000)%256; 118 PIR2bits.TMR3IF=FALSE; 119 PIE2bits.TMR3IE=TRUE; 120 T3CONbits.TMR3ON=TRUE; 121 INTCONbits.GIEH=TRUE; 122 INTCONbits.GIEL=TRUE; 123 RCONbits.IPEN=TRUE; 124 //---設置中斷優先級---// 125 INTCON2bits.TMR0IP=FALSE; 126 IPR2bits.TMR3IP=TRUE; 127 128 while(1) 129 { 130 if(TRUE==Timer1S.Enable) 131 { 132 My_T0.Result=0; 133 My_T0.Result=My_T0.High_Byte; 134 My_T0.Result<<=8; 135 My_T0.Result|=TMR0L; 136 temp=My_T0.Result; 137 for(i=0;i<sizeof(NumberLED.Buffer);i++)NumberLED.Buffer[i]=0; 138 i=0; 139 while(temp) 140 { 141 NumberLED.Buffer[i]=temp%10; 142 temp/=10; 143 i++; 144 } 145 TMR0L=0; 146 TMR0H=0; 147 My_T0.Low_Byte=0; 148 My_T0.High_Byte=0; 149 Timer1S.Enable=FALSE; 150 T0CONbits.TMR0ON=TRUE; 151 } 152 } 153 }