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: 19513
|
|
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. |
|
|
|