| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| edi 
 
 
 Joined: 22 Dec 2003
 Posts: 82
 
 
 
			    
 
 | 
			
				| 16F1507 keep entering INT_RA3 |  
				|  Posted: Thu Feb 14, 2013 12:48 pm |   |  
				| 
 |  
				| My circuit is connected to a 7seg and has a TACT switch on RA3. RA3 should act as wake up from sleep and other press function during operation.
 My problem is when I press the TACT after the first sleep the INT_RA3 is entring to an endless loop.
 Any idea?
 Compiler 4.128 and using PICkit3 for programimg.
 
  	  | Code: |  	  | #include <16F1507.h>
 #device adc=16
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
 #FUSES WDT_SW                   //No Watch Dog Timer, enabled in Software
 #FUSES NOMCLR                   //Master Clear pin used for I/O
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 
 #use delay(int=4000000)
 
 short ON=1;
 short OFF=0;
 int16 Ton=500;    // 7seg segments on time (function of refresh rate vs. on time)
 int8  sensetivity=5;  // number of ADC reads
 int16 Sensor_level=3000;  // ADC level threshold ut of 12bit resolution
 int8 count=0;
 short sleep_mode;
 
 #byte porta=0x0c
 #byte trisa=0x8c
 #byte portb=0x0d
 #byte trisb=0x8d
 #byte portc=0x0e
 #byte trisc=0x8e
 
 #bit DIGITR = portc.0
 #bit DIGITL = porta.2
 #bit SEG_A = porta.5
 #bit SEG_B = porta.4
 #bit SEG_C = portc.5
 #bit SEG_D = portc.4
 #bit SEG_E = portc.3
 #bit SEG_F = portb.7
 #bit SEG_G = portb.5
 #bit TACT = porta.3
 
 void init()
 {
 porta = 0b00001111;   // |     |     | AAA | BBB | TCT | LFT | PGC | SEN |
 trisa = 0b00001001;   // |     |     | OUT | OUT |  IN | OUT | OUT |  IN |
 portb = 0b01011111;   // | FFF |     | GGG |     |     |     |     |     |
 trisb = 0b00000000;   // | OUT | OUT | OUT | OUT | OUT | OUT | OUT | OUT |
 portc = 0b11000111;   // | SDO | SS~ | CCC | DDD | EEE | DOT | LED | RGT |
 trisc = 0b00000000;   // | OUT | OUT | OUT | OUT | OUT | OUT | OUT | OUT |
 PORT_A_PULLUPS(0b00001000); //
 }
 
 
 void debugg()
 {
 DIGITR = 0;
 DIGITL = 1;
 SEG_G = ON;
 delay_ms(80);
 SEG_G = OFF;
 delay_ms(200);
 SEG_G = ON;
 delay_ms(80);
 SEG_G = OFF;
 delay_ms(200);
 SEG_G = OFF;
 DIGITL = 1;
 DIGITR = 1;
 }
 
 void debugd()
 {
 DIGITR = 0;
 DIGITL = 1;
 SEG_D = ON;
 delay_ms(80);
 SEG_D = OFF;
 delay_ms(200);
 SEG_D = ON;
 delay_ms(80);
 SEG_D = OFF;
 delay_ms(200);
 SEG_D = OFF;
 DIGITL = 1;
 DIGITR = 1;
 }
 
 
 void display_bye()
 {
 SET_TIMER1(0x4001);
 while (GET_TIMER1() > 0x4000)
 {
 DIGITL = 1;
 DIGITR = 0;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 
 DIGITR = 1;
 DIGITL = 0;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_E = ON;
 delay_us(Ton);
 SEG_E = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 
 }
 }
 
 
 void Segment (int seg_char)
 {
 switch (seg_char)
 {
 case 0:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_E = ON;
 delay_us(Ton);
 SEG_E = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 }
 break;
 case 1:
 {
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 }
 break;
 case 2:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_E = ON;
 delay_us(Ton);
 SEG_E = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 3:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 4:
 {
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 5:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 6:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_E = ON;
 delay_us(Ton);
 SEG_E = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 7:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 }
 break;
 case 8:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_E = ON;
 delay_us(Ton);
 SEG_E = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 9:
 {
 SEG_A = ON;
 delay_us(Ton);
 SEG_A = OFF;
 SEG_B = ON;
 delay_us(Ton);
 SEG_B = OFF;
 SEG_C = ON;
 delay_us(Ton);
 SEG_C = OFF;
 SEG_D = ON;
 delay_us(Ton);
 SEG_D = OFF;
 SEG_F = ON;
 delay_us(Ton);
 SEG_F = OFF;
 SEG_G = ON;
 delay_us(Ton);
 SEG_G = OFF;
 }
 break;
 case 0xa:
 {
 SEG_G = ON;
 delay_us(10);
 SEG_G = OFF;
 }
 break;
 default:
 {
 }
 break;
 }
 
 }
 
 
 void display_7seg (int disp)
 {
 unsigned int8 yehidot, asarot;
 
 SET_TIMER1(0x4001);
 while (GET_TIMER1() > 0x4000)
 {
 DIGITL = 1;
 DIGITR = 0;
 yehidot = disp%10;
 Segment (yehidot);
 DIGITR = 1;
 DIGITL = 0;
 asarot = disp/10;
 Segment (asarot);
 }
 }
 
 
 #INT_RA
 void RA3_isr()
 {
 int8 onoff_time;
 onoff_time=TACT; // clear the RA3 INT
 debugg(); //just to indicate that interrupt routine is entered
 disable_interrupts(GLOBAL); // all interrupts OFF
 onoff_time=0;
 if ((!TACT) && (!sleep_mode))
 {
 display_7seg(count);
 while (!TACT)
 {
 display_7seg(count);
 onoff_time++;
 if (onoff_time>=6)
 {
 sleep_mode=true;
 return;
 }
 }
 }
 sleep_mode=false;
 debugd(); //just to indicate that interrupt routine is exit
 }
 
 
 
 void main()
 {
 unsigned int8 i;
 unsigned int16 mean=0, blink=0, value;
 disable_interrupts(GLOBAL); // all interrupts OFF
 disable_interrupts(INT_RA); // RA interrupt OFF
 //   setup_oscillator(OSC_4MHZ);
 init();
 sleep_mode=true;
 setup_adc_ports(sAN0 || VSS_VDD);
 setup_adc(ADC_CLOCK_INTERNAL);            // Built-in A/D setup function
 set_adc_channel(0);                       // Built-in A/D setup function
 SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
 i=porta;       // this is just to clean INT_RA
 
 CLEAR_INTERRUPT(INT_RA3);
 ENABLE_INTERRUPTS(INT_RA3_H2L);
 enable_interrupts(GLOBAL);
 //   enable_interrupts(PERIPH);
 
 sleep();
 
 //   display_7seg(33);
 display_7seg(22);
 display_7seg(11);
 display_7seg(0);
 
 while(1)
 {
 if (sleep_mode)
 {
 disable_interrupts(INT_RA3); // RA interrupt OFF
 display_bye();
 display_bye();
 //         display_bye();
 //         display_bye();
 //         display_bye();
 //         display_bye();
 count=0;
 CLEAR_INTERRUPT(INT_RA3);
 ENABLE_INTERRUPTS(INT_RA3_H2L);
 sleep();
 display_7seg(33);
 display_7seg(22);
 display_7seg(11);
 display_7seg(0);
 }
 for (i=0; i<sensetivity; i++)
 {
 value = read_adc();                 // Built-in A/D read function
 mean = mean + value;
 }
 mean = mean/i;
 if (mean > Sensor_level)         //This is the mean vlue of the ADC
 {
 count++;
 if (count==100)
 count=99;
 display_7seg(count);
 }
 mean=0;
 
 if (blink == 3800)
 {
 DIGITL = 1;
 DIGITR = 0;
 SEG_G = ON;
 }
 else if (blink==3900)
 {
 DIGITL = 1;
 DIGITR = 0;
 SEG_G = OFF;
 }
 if (blink == 4000)
 {
 DIGITL = 0;
 DIGITR = 1;
 SEG_G = ON;
 }
 else if (blink==4100)
 {
 DIGITL = 0;
 DIGITR = 1;
 SEG_G = OFF;
 blink=0;
 }
 blink++;
 
 }
 }
 | 
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 14, 2013 12:51 pm |   |  
				| 
 |  
				| INT_RA3, is an 'interrupt on change' on this chip. These _always_ require that the handler _reads the pin_. Otherwise the interrupt cannot be cleared As a general comment, the global interrupt flag is already 'off' when you enter an interrupt, and is re-enabled by the hardware when the interrupt exits. You should never disable/enable the global flag inside interrupts.
 
 Best Wishes
 |  | 
	
		|  | 
	
		| edi 
 
 
 Joined: 22 Dec 2003
 Posts: 82
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 14, 2013 1:30 pm |   |  
				| 
 |  
				| Thanks Ttelmah. This is the reason I put the line:
 
  	  | Code: |  	  | onoff_time=TACT; // clear the RA3 INT
 
 | 
 It supposed to read RA3 and clear the interrupt, isn't it?
 |  | 
	
		|  | 
	
		| ckielstra 
 
 
 Joined: 18 Mar 2004
 Posts: 3680
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Feb 14, 2013 2:35 pm |   |  
				| 
 |  
				| I only had a quick glance at your code and think it is not easy to follow, but have you considered the possibility that the ISR did end? There is a code path in your ISR where a return is done without calling  debugd(), leaving your interrupt debug active. |  | 
	
		|  | 
	
		|  |