//基于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 }