maybe try to prefend variables you use inside the interrupt with the "volatile" keyword.. to tell the compiler not to do optimization on the variables.... sample: volatile union { } this is from a book developing embeded softwsre in C Volatile We add the volatile modifier to a variable that can change value outside the scope of the function. Usually the value of a global variable changes only as a result of explicit statements in the C function that is currently executing. The paradigm results when a single program executes from start to finish, and everything that happens is an explicit result of actions taken by the program. There are two situations that break this simple paradigm in which the value of a memory location might change outside the scope of a particular function currently executing: 1) interrupts and 2) input/output ports. An interrupt is a hardware-requested software action. Consider the following multithreaded interrupt example. There is a foreground thread called main(), which we setup as the usual main program that all C programs have. Then, there is a background thread called TOFhandler(), which we setup to be executed on a periodic basis (e.g., every 16 ms). Both threads access the global variable, Time. The interrupt thread increments the global variable, and the foreground thread waits for time to reach 100. Notice that Time changes value outside the influence of the main() program. volatile char Time; #pragma interrupt_handler TOFhandler void TOFhandler(void){ /* every 16ms */ TFLG2=0x80; /* TOF interrupt acknowledge */ Time=Time+1; } void main(void){ TSCR |=0x80; /* TEN(enable) */ TMSK2=0xA2; /* TOI arm, TPU(pullup) timer/4 (500ns) */ CLKCTL=0x00; Time=0; while(Time<100){}; /* wait for 100 counts of the 16 ms timer*/ } Listing 4-6: ICC12 example showing shared access to a common global variable Without the volatile modifier the compiler might look at the two statements: Time=0; while(Time<100){}; and conclude that since the while loop does not modify Time, it could never reach 100. Some compilers (not yet in the current versions of ICC11 and ICC12) might attempt to move the read Time operation, performing it once before the while loop is executed. The volatile modifier disables the optimization, forcing the program to fetch a new value from the variable each time the variable is accessed. In the next 6812 example, assume PORTA is an input port containing the current status of some important external signals. The program wishes to collect status versus time data of these external signals. unsigned char data[100]; #define PORTA *(unsigned char volatile *)(0x0000) #define DDRA *(unsigned char volatile *)(0x0004) void main(void){ short i; DDRA=0x00; /* make Port A an input */ for(i=0;i<100;i++){ /* collect 100 measurements */ data[i]=PORTA; /* collect ith measurement */ } } Listing 4-7: Example showed shared access to a common global variable Without the volatile modifier in the PORTA definition, the compiler might optimize the for loop, reading PORTA once, then storing 100 identical copies into the data array. Hope this help............ ----- Original Message ----- From: "Dumitru Stama" Newsgroups: gmane.comp.hardware.microcontrollers.pic Sent: Tuesday, December 05, 2006 3:13 AM Subject: [PIC] Problems with C18 interrupt code > Hi guys, > I have problems with the folowing piece of code. I modified the > original example from Microchip C18 which implements TIMER0 interrupt > and i added PORTB on-change interrupt. The code does only one thing : > it increments pulse_count.b1234 which is an unsigned long (this being > made inside ISR) when it detects a change from 0 to 1 on RB4 and in the > main loop sends the value to PORTC so i can see it. > I tested this code using Proteus VSM and it works well. I applied an > impulse train on RB4 and the programs acts as it shoul with only one > problem : after ~30 seconds it behaves erratically for a few moments and > starts to count again from 0 ! > I disabled watchdog timer (even from VSM), i disabled LVP, i disabled > BOR, i disabled Stack overflow reset, no luck whatsoever. > Can anyone see if i am doing something wrong with the folowing piece > of code ? I have the .lst as well as .hex files if that might help. I > have been doing this for the last 10 hours and i feel like i am > loosing my mind. > > Thank you for your understanding, > > //---------------------------------------------------------------------------- > > > #include > #pragma config OSC = XT, OSCS = OFF, PWRT = ON, BOR = OFF, WDT = OFF, > STVR = OFF, LVP = OFF, DEBUG = OFF > > //---------------------------------------------------------------------------- > > void main (void); > void InterruptHandlerHigh (void); > > union { > struct { > unsigned Timeout:1; //flag to indicate a TMR0 timeout > unsigned None:7; > } Bit; > unsigned char Byte; > } Flags; > > //========================= > union { > struct { > unsigned char B0; > unsigned char B1; > unsigned char B2; > unsigned char B3; > } byte; > unsigned long b1234; > } pulse_count; > > > //========================= > union { > struct { > unsigned RB0:1; > unsigned RB1:1; > unsigned RB2:1; > unsigned RB3:1; > unsigned RB4:1; > unsigned RB5:1; > unsigned RB6:1; > unsigned RB7:1; > }; > unsigned char old_portb; > } old_portb_bits; > > //---------------------------------------------------------------------------- > // Main routine > > void main () { > Flags.Byte = 0; > INTCON = 0x28; //disable global and enable TMR0 interrupt and RB > INTCON2 = 0x85; //TMR0 high priority > RCONbits.IPEN = 1; //enable priority levels > TMR0H = 0; //clear timer and set TMR0H > TMR0L = 0; //clear timer low byte and also updates high byte from > TMR0H > T0CON = 0x88; //set up timer0 - no prescaler > INTCONbits.GIEH = 1; //enable interrupts > TRISB = 0x7E; //PORTB bits 0 and 7 are output, the rest are input > TRISC = 0; //PORTC bits are output > PORTC = 0; > > old_portb_bits.old_portb = 0; > pulse_count.b1234 = 0; > > while (1) { > PORTC = pulse_count.byte.B0; > } > } > > //---------------------------------------------------------------------------- > // 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 > } > > if (INTCONbits.RBIF) { > PORTB = PORTB; > INTCONbits.RBIF = 0; > if (PORTBbits.RB4 == 1 && old_portb_bits.RB4 == 0) > (unsigned long)pulse_count.b1234++; > old_portb_bits.old_portb = PORTB; > } > } > > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist