Maker Pro
Maker Pro

Why does this freeze?

S

Simoc

Jan 1, 1970
0
Hello,

Well, I've got my first microcontroller project *almost* working :)
So this should be some kind of burglar alarm. It is otherwise working
well,
but it tends to freeze when it's counting either arming or alarm
delay.
It doesn't freeze everytime, but often, say, averagely every other
time.

The program code below might be pretty long and complicated to
analyze,
but if someone would bother to tell why does that freeze, I'd be
extremely
grateful =)

The freezing happens when in "arming" or "triggered" loop on
the main program, the variables "armDelay and "alarmDelay" are
decremented
by Timer 1 overflow interrupt.

Btw, as I'm still a newbie on both programming and using
microcontrollers,
I know that the program might be _far_ from ideal/optimal design, but
I'm
currently mostly interested just about that why does it freeze.

Thanks in advance for everyone having any thought...


#include <mega16.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <delay.h>
#include <lcd.h>
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
#define BLINKERS PORTA.0 //Blinkers (turn signals) control relay
#define HORN PORTA.1 //Horn control relay
#define CALL PORTA.2 //Call -signal for attached cell phone
#define IGNITION PORTA.3 //Ignition relay
#define SENSOR PINB.7 //Sensor input
#define POWER PINB.6 //Ignition lock state input (1-active)

// global variables
char key='A'; //tells the number of pressed key
int m=4; //keypad row multiplexer
unsigned char intToChar[4]={'A'}; //integer to be displayed is
converted to char in this variable
eeprom int correctCode[4]={2,3,4,5}; //the correct code is stored in
this table
int code[4]={'A','A','A','A'}; //entered code is stored in
this table
int newCode[4]={'A','A','A','A'}; //fed new code is stored in
this table before verification
int p; //code input pointer
int t; //code comparison pointer
char c; //code[4] resetting pointer
bit enterCode=0; //if 0, "enter code" displayed
bit correct=0; //turns 1 when correct code entered
int okKey=0; //tells what to do when # (OK-key) pressed:
//if 0, code[4] will be compared to correctCode and
correct=1 if matched
//if 1, code[4] string will be converted to integer
and stored in setAlarmDelay
//if 2, code[4] string will be converted to integer
and stored in setArmDelay
//if 3, code[1] will be stored in
autoArm
//if 4, code[4] will be stored to newCode[4] and re-
entering requested
//if 5, code[4] will be compared to newCode and
stored in correctCode if matched
bit horn=0; //horn cycler
int hornCycle=3; //horn on-off cycle interval, to be
decremented by timer
int callTime=0; //call-signal pulse timing
eeprom int setArmDelay=20; //delay before arming
int armDelay=0; //variable to be decremented by timer
eeprom int setAlarmDelay=30; //Delay before activating alarm
int alarmDelay=0; //variable to be decremented by timer
eeprom int arming=0; //sets 1 when in "arming" -loop
eeprom int armed=0; //sets 1 when in "armed" -loop
eeprom int triggered=0; //sets 1 when in "triggered" -loop
eeprom int alarm=0; //sets 1 when in "alarm" -loop
bit settingsCodeQuery=0; //sets 1 when in "settings code query" -loop
of settings entry
bit cancel=0; //if 1, settings will be cancelled
bit settingsEntry=0; //sets 1, when in settings mode
bit settings=0; //sets 1, when correct code entered in
settingsCodeQuery
eeprom int autoArm=1; //sets 1, if "auto arming" -feature is
enabled, 0 if disabled
bit noAutoArm=1; //Turns 1 when disarming, reset to 0 when
POWER==1. if 1,
//auto arming temporarily disabled
until reset
//(in order to prevent auto arming
right after disarming before ignition
//has been turned on one time)
int n; //number of digits fed in code[4] in delay
settings
long int r; //calculated (n-t)th power of 10
//(used when converting a string into an
integer in delaysettings)
int e=0; //the exponent of 10 of a digit being
calculated (n-t)
//(used when converting a string into an
integer in delay settings)


void nollaus() //resets code[4], its display, and input
pointer p
{
for(c=0;c<4;c++)
{
code[c]='A';
}
p=0;
lcd_gotoxy(11,1);
lcd_putsf(" ");
}


void keypad()
{
if(enterCode==0) //displays "enter code to arm" if enterCode==0
{
lcd_gotoxy(0,0);
lcd_putsf("enter code to arm [ ]");
enterCode=1;
lcd_gotoxy(11,1);
}
else if(key!='A'&&settings==0) //inputs the value of key to code[p],
if changed, displays it or '*', increments p
{
code[p]=key;
key='A';
itoa(code[p],intToChar);
lcd_gotoxy(p+11,1);
if(okKey==1||okKey==2||okKey==3) //if in delay or auto
arming setting mode, the number is displayed
lcd_puts(intToChar);
else //otherwise
'*' is displayed
lcd_putchar('*');
delay_ms(200);
if(p<3&&okKey!=3) //p incremented,
provided p<3 and not in auto arming setting mode
p++;
}
else if(key!='A'&&settings==1) //if improper key pressed in
"settings" mode, its value is cleared from "key" immediately
{
key='A';
}
}

// External Interrupt 0 service routine (the left column of the
keypad)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PIND.2==0) //(the service routine will be proceeded if
the int0 input is still active after 140ms delay)
{
if(PORTD.4==0) //the 1st row of the keypad (1)
{
if(settings==0)
key=1;
if(settings==1) //alarm delay setting
{
settings=0;
lcd_clear();
lcd_putsf("Set alarm delay [");
itoa(setAlarmDelay,intToChar);
lcd_puts(intToChar);
lcd_putsf("]");
lcd_gotoxy(10,1);
lcd_putsf("[ ]");
okKey=1;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (4)
{
if(settings==0)
key=4;
if(settings==1) //code change mode
{
settings=0;
lcd_gotoxy(0,0);
lcd_putsf("enter new code
[ ]");
okKey=4;
}
}
if(PORTD.6==0) //the 3rd row of the keypad (7)
key=7;
if(PORTD.7==0) //the 4rd row of the keypad (*)
{
if(p==0&&settingsEntry==1) //if no digits fed in
settingsEntry mode, cancelled
{
cancel=1;
if(settingsCodeQuery==0)
{
cancel=0;
okKey=0;
settings=0;
settingsEntry=0;
enterCode=0;
nollaus();
}
}

if(p>0) //if digits fed in code[4], the
last will be cleared
{
if(code[p]=='A')
p--;
lcd_gotoxy(p+11,1);
lcd_putsf(" ");
code[p]='A';
lcd_gotoxy(p+11,1);
}
}
}
SREG=0x80; //interruptions allowed
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PIND.3==0) //
{
if(PORTD.4==0) //the 1st row of the keypad (2)
{
if(settings==0)
key=2;
if(settings==1) //arming delay setting
{
settings=0;
lcd_clear();
lcd_putsf("Set arming delay[");
itoa(setArmDelay,intToChar);
lcd_puts(intToChar);
lcd_putsf("]");
lcd_gotoxy(10,1);
lcd_putsf("[ ]");
okKey=2;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (5)
key=5;
if(PORTD.6==0) //the 3rd row of the keypad (8)
key=8;
if(PORTD.7==0) //the 4rd row of the keypad (0)
key=0;
}
SREG=0x80; //interruptions allowed
}

// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PINB.2==0) //
{
if(PORTD.4==0) //the 1st row of the keypad (3)
{
if(settings==0)
key=3;
if(settings==1) //auto arming
setting
{
settings=0;
itoa(autoArm,intToChar);
lcd_gotoxy(0,0);
lcd_putsf("Auto arming:[");
lcd_puts(intToChar);
lcd_putsf("] 1:eek:n,0:eek:ff[ ] ");
okKey=3;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (6)
key=6;
if(PORTD.6==0) //the 3rd row of the keypad (9)
key=9;
if(PORTD.7==0) //the 4rd row of the keypad (#)
{
t=0;
if(p==0&&arming==0&&okKey==0&&settingsEntry==0) //if
no digits fed in disarmed mode
{
settingsEntry=1;
lcd_gotoxy(0,0);
lcd_putsf("settings, enter code [ ]");
SREG=0x80; //interruptions allowed
while(1) //loop: settings code
query
{
settingsCodeQuery=1;
keypad();
if(cancel==1) //if
cancel==1, settings will be cancelled
{
cancel=0;
settingsCodeQuery=0;
settingsEntry=0;
break;
}
if(correct==1) //if
correctCode entered, entered to settings
mode

{

correct=0;

settings=1;

lcd_clear();
lcd_putsf("Settings");
delay_ms(2000);
lcd_clear();
lcd_putsf("1:alm d 2:arm
d3:AutoArm 4:code");
settingsCodeQuery=0;

break;
}
};
SREG=0x00; //interruptions
denied
}
if(okKey==0&&p!=0&&settings==0) //entered code is
checked if it is correct
while(1) //comparing entered code to
correctCode
{
if(code[t]!=correctCode[t]) //
if mismatched, "wrong code" displayed
{
if((armed==1&&triggered==0)||
arming==0)
{
lcd_clear();
lcd_putsf("Wrong code");
}
else
{
lcd_gotoxy(0,1);
lcd_putsf("Wrong code
");
}
delay_ms(2000);
nollaus();
break;
}
if(t==3) //if all 4
characters matched, correct=1
{
nollaus();
correct=1;
break;
}
t++;
};
if(okKey==4) //entered code will be copied to
"newCode" and re-entering
requested
if(code[3]!='A')
{
for(t=0;t<4;t++)
{

newCode[t]=code[t];
}
lcd_gotoxy(0,0);
lcd_putsf("verify new code");
nollaus();
okKey=5;
}
if(okKey==5) //entered code compared to
newCode and stored in correctCode if matched
if(code[3]!='A') //if 4 digits fed
while(1)
{
if(code[t]!
=newCode[t]) //if mismatch occured
{
lcd_clear();
lcd_putsf("mismatch
");
nollaus();
delay_ms(2000);
okKey=0;
settingsEntry=0;
break;
}

if(t==3) //if all 4 digits matched
{
nollaus();
for(t=0;t<4;t++)
{

correctCode[t]=newCode[t];
}
lcd_clear();
lcd_putsf("changed");
nollaus();
delay_ms(2000);
okKey=0;

settingsEntry=0;
break;
}
t++; //t
incremented if digit t matched
};
if(okKey==2&&code[0]!='A') //entered string will be
converted to integer and stored in setArmDelay
{
n=3; //identifying the
number of fed digits
if(code[3]=='A') //
n=2; //
if(code[2]=='A') //
n=1; //
if(code[1]=='A') //
n=0; //
armDelay=0;
for(t=0;t<=n;t++) //each digit is
multiplied by its power of 10 and added to armDelay
{
r=1;
for(e=n-t;e>0;e--) //(n-t)th
power of 10 is calculated and stored in r
{
r=10*r;
}
armDelay=armDelay+(code[t]*r); //
digit t multiplied by its power of 10 (r)
}
setArmDelay=armDelay; //the value
calculated in armDelay is stored in setArmDelay
itoa(setArmDelay,intToChar); //the
stored setArmDelay value is displayed
lcd_gotoxy(0,0);
lcd_putsf("Arming delay changed:[");
lcd_puts(intToChar);
lcd_putsf("] ");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}

if(okKey==1&&code[0]!='A') //entered string
converted to integer and stored in setAlarmDelay
{
n=3; //identifying the
number of fed digits
if(code[3]=='A') //
n=2; //
if(code[2]=='A') //
n=1; //
if(code[1]=='A') //
n=0; //
alarmDelay=0;
for(t=0;t<=n;t++) //each digit is
multiplied by its power of 10 and added to alarmDelay
{
r=1;
for(e=n-t;e>0;e--) //(n-t)th
power of 10 is calculated and stored in r
{
r=10*r;
}
alarmDelay=alarmDelay+(code[t]*r); //
digit t multiplied by its power of 10 (r)
}
setAlarmDelay=alarmDelay; //the value
calculated in alarmDelay is stored in setAlarmDelay
itoa(setAlarmDelay,intToChar); //the
stored setAlarmDelay value is displayed
lcd_gotoxy(0,0);
lcd_putsf("Alarm delay changed:[");
lcd_puts(intToChar);
lcd_putsf("] ");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}

if(okKey==3&&(code[0]==0||code[0]==1)) //
code[0] will be stored to autoArm
{
autoArm=code[0];
noAutoArm=1;
lcd_clear();
if(autoArm==0)
lcd_putsf("Auto arming disabled");
if(autoArm==1)
lcd_putsf("Auto arming
enabled");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}
if(triggered==1) //if in
"triggered" mode, "enter code" displayed
{
lcd_gotoxy(0,1);
lcd_putsf("enter code[ ]");
}
if(armed==1&&triggered==0) //if in
armed mode, "enter code to disarm" dispalyed
{
lcd_gotoxy(0,0);
lcd_putsf("enter code to disarm
[ ]");
}

if(arming==0&&settingsEntry==0&&settingsCodeQuery==0) //if in disarmed
mode
enterCode=0;
if(settingsCodeQuery==1) //if in settings
code query mode, "settings, enter code" displayed
{
lcd_gotoxy(0,0);
lcd_putsf("settings, enter code
[ ]");
}
}
}
SREG=0x80; //interruptions allowed
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //keypad rows
multiplexed
{
PORTD.4=1;
PORTD.5=1;
PORTD.6=1;
PORTD.7=1;

if(m==4)
PORTD.4=0;
if(m==5)
PORTD.5=0;
if(m==6)
PORTD.6=0;
if(m==7)
PORTD.7=0;

m++;
if(m==8)
m=4;
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
if(alarmDelay>0) //alarmDelay decremented
alarmDelay--;

if(armDelay>0) //armDelay decremented
armDelay--;

if(callTime>0) //callTime decremented
callTime--;

if(hornCycle==0) //if hornCycle==0, horn inverted and hornCycle
reset to 3
{
horn=~horn;
hornCycle=3;
}
hornCycle--; //hornCycle decremented


//PORTC.3=~PORTC.3; //led

}


void main(void)
{

// Input/Output Ports initialization
// Port A initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out
Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0
State0=0
PORTA=0x00;
DDRA=0xFF;

// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In In Func1=In
Func0=In
// State7=P State6=T State5=P State4=P State3=P State2=P State1=P
State0=P
PORTB=0xBF;
DDRB=0x00;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out
Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0
State0=0
PORTC=0x00;
DDRC=0xFF;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In
Func0=In
// State7=1 State6=1 State5=1 State4=1 State3=P State2=P State1=P
State0=P
PORTD=0xFF;
DDRD=0xF0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x05;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: On
// INT1 Mode: Falling Edge
// INT2: On
// INT2 Mode: Falling Edge
GICR|=0xE0;
MCUCR=0x0A;
MCUCSR=0x00;
GIFR=0xE0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x05;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1) //main loop: waiting for correct,
checking for "arming", and monitoring "POWER"
{
keypad();
IGNITION=1; //ignition enabled
if(POWER==1) //when ignition power is turned on,
noAutoArm is reset (with debounce)
{
delay_ms(1000);
if(POWER==1)
noAutoArm=0;
}
if(correct==1||arming==1||
(settingsEntry==0&&noAutoArm==0&&autoArm==1&&POWER==0))
//if correct code fed, arming==1
already, or auto arming triggered

{
correct=0;
arming=1;
IGNITION=0;
lcd_clear();
armDelay=setArmDelay;
while(1) //loop: arming, with
delay
{
keypad();
itoa(armDelay,intToChar);
lcd_gotoxy(0,0);
lcd_putsf("arming... [");
lcd_puts(intToChar);
lcd_putsf("] ");
lcd_gotoxy(0,1);
lcd_putsf(" [");
lcd_gotoxy(15,1);
lcd_putsf("]");
if(armDelay==0||armed==1) //if armDelay
time-out or armed==1 already
{
armed=1;
lcd_clear();
lcd_putsf("armed");
delay_ms(2000);
lcd_gotoxy(0,0);
lcd_putsf("enter code to disarm
[ ]");
while(1) // loop:
armed, waiting for sensor trigger or correctCode
{
keypad();
if(SENSOR==0||POWER==1||
triggered==1) //if SENSOR or POWER signal fed
{ //
or triggered==1 already
triggered=1;
lcd_gotoxy(0,1);
lcd_putsf("enter code[ ]");
alarmDelay=setAlarmDelay;
while(1) //loop: triggered,
alarm being activated, with delay
{
keypad();
lcd_gotoxy(0,0);
lcd_putsf("alarm ");
itoa(alarmDelay,intToChar);
lcd_gotoxy(6,0);
lcd_puts(intToChar);
lcd_putsf(" ");
if(alarmDelay==0||
alarm==1) //if alarm delay time-out or alarm==1
{
lcd_gotoxy(5,0);
lcd_putsf(" ");
alarm=1;
callTime=4; //CALL
signal activated
CALL=1;
while(1) //loop:
alarm activated
{
keypad();
BLINKERS=1;
HORN=horn;
if(callTime==0)
CALL=0;

if(correct==1) //if correct code fed, disarmed
break;
};
}
if(correct==1)
break;
};
}
if(correct==1)
break;
};
}
if(correct==1)
{
noAutoArm=1;
BLINKERS=0;
HORN=0;
CALL=0;
correct=0;
alarm=0;
triggered=0;
armed=0;
arming=0;
enterCode=0;
lcd_clear();
lcd_putsf("disarmed");
delay_ms(2000);
break;
}
};
}
};
}
 
M

Mikkel Lund

Jan 1, 1970
0
Simoc skrev:
....

Hmmm, only 790 lines of code, i don't have anything to do this weekend,
why not debug.... NOT
 
B

Bob Myers

Jan 1, 1970
0
And you just HAD to leave the whole 700-something lines
of code quoted, didn't you?

Geeze....


Bob M.
 
S

scada

Jan 1, 1970
0
Simoc said:
Hello,

Well, I've got my first microcontroller project *almost* working :)
So this should be some kind of burglar alarm. It is otherwise working
well,
but it tends to freeze when it's counting either arming or alarm
delay.
It doesn't freeze everytime, but often, say, averagely every other
time.

The program code below might be pretty long and complicated to
analyze,
but if someone would bother to tell why does that freeze, I'd be
extremely
grateful =)

The freezing happens when in "arming" or "triggered" loop on
the main program, the variables "armDelay and "alarmDelay" are
decremented
by Timer 1 overflow interrupt.

Btw, as I'm still a newbie on both programming and using
microcontrollers,
I know that the program might be _far_ from ideal/optimal design, but
I'm
currently mostly interested just about that why does it freeze.

Thanks in advance for everyone having any thought...


#include <mega16.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <delay.h>
#include <lcd.h>
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
#define BLINKERS PORTA.0 //Blinkers (turn signals) control relay
#define HORN PORTA.1 //Horn control relay
#define CALL PORTA.2 //Call -signal for attached cell phone
#define IGNITION PORTA.3 //Ignition relay
#define SENSOR PINB.7 //Sensor input
#define POWER PINB.6 //Ignition lock state input (1-active)

// global variables
char key='A'; //tells the number of pressed key
int m=4; //keypad row multiplexer
unsigned char intToChar[4]={'A'}; //integer to be displayed is
converted to char in this variable
eeprom int correctCode[4]={2,3,4,5}; //the correct code is stored in
this table
int code[4]={'A','A','A','A'}; //entered code is stored in
this table
int newCode[4]={'A','A','A','A'}; //fed new code is stored in
this table before verification
int p; //code input pointer
int t; //code comparison pointer
char c; //code[4] resetting pointer
bit enterCode=0; //if 0, "enter code" displayed
bit correct=0; //turns 1 when correct code entered
int okKey=0; //tells what to do when # (OK-key) pressed:
//if 0, code[4] will be compared to correctCode and
correct=1 if matched
//if 1, code[4] string will be converted to integer
and stored in setAlarmDelay
//if 2, code[4] string will be converted to integer
and stored in setArmDelay
//if 3, code[1] will be stored in
autoArm
//if 4, code[4] will be stored to newCode[4] and re-
entering requested
//if 5, code[4] will be compared to newCode and
stored in correctCode if matched
bit horn=0; //horn cycler
int hornCycle=3; //horn on-off cycle interval, to be
decremented by timer
int callTime=0; //call-signal pulse timing
eeprom int setArmDelay=20; //delay before arming
int armDelay=0; //variable to be decremented by timer
eeprom int setAlarmDelay=30; //Delay before activating alarm
int alarmDelay=0; //variable to be decremented by timer
eeprom int arming=0; //sets 1 when in "arming" -loop
eeprom int armed=0; //sets 1 when in "armed" -loop
eeprom int triggered=0; //sets 1 when in "triggered" -loop
eeprom int alarm=0; //sets 1 when in "alarm" -loop
bit settingsCodeQuery=0; //sets 1 when in "settings code query" -loop
of settings entry
bit cancel=0; //if 1, settings will be cancelled
bit settingsEntry=0; //sets 1, when in settings mode
bit settings=0; //sets 1, when correct code entered in
settingsCodeQuery
eeprom int autoArm=1; //sets 1, if "auto arming" -feature is
enabled, 0 if disabled
bit noAutoArm=1; //Turns 1 when disarming, reset to 0 when
POWER==1. if 1,
//auto arming temporarily disabled
until reset
//(in order to prevent auto arming
right after disarming before ignition
//has been turned on one time)
int n; //number of digits fed in code[4] in delay
settings
long int r; //calculated (n-t)th power of 10
//(used when converting a string into an
integer in delaysettings)
int e=0; //the exponent of 10 of a digit being
calculated (n-t)
//(used when converting a string into an
integer in delay settings)


void nollaus() //resets code[4], its display, and input
pointer p
{
for(c=0;c<4;c++)
{
code[c]='A';
}
p=0;
lcd_gotoxy(11,1);
lcd_putsf(" ");
}


void keypad()
{
if(enterCode==0) //displays "enter code to arm" if enterCode==0
{
lcd_gotoxy(0,0);
lcd_putsf("enter code to arm [ ]");
enterCode=1;
lcd_gotoxy(11,1);
}
else if(key!='A'&&settings==0) //inputs the value of key to code[p],
if changed, displays it or '*', increments p
{
code[p]=key;
key='A';
itoa(code[p],intToChar);
lcd_gotoxy(p+11,1);
if(okKey==1||okKey==2||okKey==3) //if in delay or auto
arming setting mode, the number is displayed
lcd_puts(intToChar);
else //otherwise
'*' is displayed
lcd_putchar('*');
delay_ms(200);
if(p<3&&okKey!=3) //p incremented,
provided p<3 and not in auto arming setting mode
p++;
}
else if(key!='A'&&settings==1) //if improper key pressed in
"settings" mode, its value is cleared from "key" immediately
{
key='A';
}
}

// External Interrupt 0 service routine (the left column of the
keypad)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PIND.2==0) //(the service routine will be proceeded if
the int0 input is still active after 140ms delay)
{
if(PORTD.4==0) //the 1st row of the keypad (1)
{
if(settings==0)
key=1;
if(settings==1) //alarm delay setting
{
settings=0;
lcd_clear();
lcd_putsf("Set alarm delay [");
itoa(setAlarmDelay,intToChar);
lcd_puts(intToChar);
lcd_putsf("]");
lcd_gotoxy(10,1);
lcd_putsf("[ ]");
okKey=1;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (4)
{
if(settings==0)
key=4;
if(settings==1) //code change mode
{
settings=0;
lcd_gotoxy(0,0);
lcd_putsf("enter new code
[ ]");
okKey=4;
}
}
if(PORTD.6==0) //the 3rd row of the keypad (7)
key=7;
if(PORTD.7==0) //the 4rd row of the keypad (*)
{
if(p==0&&settingsEntry==1) //if no digits fed in
settingsEntry mode, cancelled
{
cancel=1;
if(settingsCodeQuery==0)
{
cancel=0;
okKey=0;
settings=0;
settingsEntry=0;
enterCode=0;
nollaus();
}
}

if(p>0) //if digits fed in code[4], the
last will be cleared
{
if(code[p]=='A')
p--;
lcd_gotoxy(p+11,1);
lcd_putsf(" ");
code[p]='A';
lcd_gotoxy(p+11,1);
}
}
}
SREG=0x80; //interruptions allowed
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PIND.3==0) //
{
if(PORTD.4==0) //the 1st row of the keypad (2)
{
if(settings==0)
key=2;
if(settings==1) //arming delay setting
{
settings=0;
lcd_clear();
lcd_putsf("Set arming delay[");
itoa(setArmDelay,intToChar);
lcd_puts(intToChar);
lcd_putsf("]");
lcd_gotoxy(10,1);
lcd_putsf("[ ]");
okKey=2;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (5)
key=5;
if(PORTD.6==0) //the 3rd row of the keypad (8)
key=8;
if(PORTD.7==0) //the 4rd row of the keypad (0)
key=0;
}
SREG=0x80; //interruptions allowed
}

// External Interrupt 2 service routine
interrupt [EXT_INT2] void ext_int2_isr(void)
{
SREG=0x00; //interruptions denied
delay_ms(140); //debouncing
if(PINB.2==0) //
{
if(PORTD.4==0) //the 1st row of the keypad (3)
{
if(settings==0)
key=3;
if(settings==1) //auto arming
setting
{
settings=0;
itoa(autoArm,intToChar);
lcd_gotoxy(0,0);
lcd_putsf("Auto arming:[");
lcd_puts(intToChar);
lcd_putsf("] 1:eek:n,0:eek:ff[ ] ");
okKey=3;
}
}
if(PORTD.5==0) //the 2nd row of the keypad (6)
key=6;
if(PORTD.6==0) //the 3rd row of the keypad (9)
key=9;
if(PORTD.7==0) //the 4rd row of the keypad (#)
{
t=0;
if(p==0&&arming==0&&okKey==0&&settingsEntry==0) //if
no digits fed in disarmed mode
{
settingsEntry=1;
lcd_gotoxy(0,0);
lcd_putsf("settings, enter code [ ]");
SREG=0x80; //interruptions allowed
while(1) //loop: settings code
query
{
settingsCodeQuery=1;
keypad();
if(cancel==1) //if
cancel==1, settings will be cancelled
{
cancel=0;
settingsCodeQuery=0;
settingsEntry=0;
break;
}
if(correct==1) //if
correctCode entered, entered to settings
mode

{

correct=0;

settings=1;

lcd_clear();
lcd_putsf("Settings");
delay_ms(2000);
lcd_clear();
lcd_putsf("1:alm d 2:arm
d3:AutoArm 4:code");
settingsCodeQuery=0;

break;
}
};
SREG=0x00; //interruptions
denied
}
if(okKey==0&&p!=0&&settings==0) //entered code is
checked if it is correct
while(1) //comparing entered code to
correctCode
{
if(code[t]!=correctCode[t]) //
if mismatched, "wrong code" displayed
{
if((armed==1&&triggered==0)||
arming==0)
{
lcd_clear();
lcd_putsf("Wrong code");
}
else
{
lcd_gotoxy(0,1);
lcd_putsf("Wrong code
");
}
delay_ms(2000);
nollaus();
break;
}
if(t==3) //if all 4
characters matched, correct=1
{
nollaus();
correct=1;
break;
}
t++;
};
if(okKey==4) //entered code will be copied to
"newCode" and re-entering
requested
if(code[3]!='A')
{
for(t=0;t<4;t++)
{

newCode[t]=code[t];
}
lcd_gotoxy(0,0);
lcd_putsf("verify new code");
nollaus();
okKey=5;
}
if(okKey==5) //entered code compared to
newCode and stored in correctCode if matched
if(code[3]!='A') //if 4 digits fed
while(1)
{
if(code[t]!
=newCode[t]) //if mismatch occured
{
lcd_clear();
lcd_putsf("mismatch
");
nollaus();
delay_ms(2000);
okKey=0;
settingsEntry=0;
break;
}

if(t==3) //if all 4 digits matched
{
nollaus();
for(t=0;t<4;t++)
{

correctCode[t]=newCode[t];
}
lcd_clear();
lcd_putsf("changed");
nollaus();
delay_ms(2000);
okKey=0;

settingsEntry=0;
break;
}
t++; //t
incremented if digit t matched
};
if(okKey==2&&code[0]!='A') //entered string will be
converted to integer and stored in setArmDelay
{
n=3; //identifying the
number of fed digits
if(code[3]=='A') //
n=2; //
if(code[2]=='A') //
n=1; //
if(code[1]=='A') //
n=0; //
armDelay=0;
for(t=0;t<=n;t++) //each digit is
multiplied by its power of 10 and added to armDelay
{
r=1;
for(e=n-t;e>0;e--) //(n-t)th
power of 10 is calculated and stored in r
{
r=10*r;
}
armDelay=armDelay+(code[t]*r); //
digit t multiplied by its power of 10 (r)
}
setArmDelay=armDelay; //the value
calculated in armDelay is stored in setArmDelay
itoa(setArmDelay,intToChar); //the
stored setArmDelay value is displayed
lcd_gotoxy(0,0);
lcd_putsf("Arming delay changed:[");
lcd_puts(intToChar);
lcd_putsf("] ");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}

if(okKey==1&&code[0]!='A') //entered string
converted to integer and stored in setAlarmDelay
{
n=3; //identifying the
number of fed digits
if(code[3]=='A') //
n=2; //
if(code[2]=='A') //
n=1; //
if(code[1]=='A') //
n=0; //
alarmDelay=0;
for(t=0;t<=n;t++) //each digit is
multiplied by its power of 10 and added to alarmDelay
{
r=1;
for(e=n-t;e>0;e--) //(n-t)th
power of 10 is calculated and stored in r
{
r=10*r;
}
alarmDelay=alarmDelay+(code[t]*r); //
digit t multiplied by its power of 10 (r)
}
setAlarmDelay=alarmDelay; //the value
calculated in alarmDelay is stored in setAlarmDelay
itoa(setAlarmDelay,intToChar); //the
stored setAlarmDelay value is displayed
lcd_gotoxy(0,0);
lcd_putsf("Alarm delay changed:[");
lcd_puts(intToChar);
lcd_putsf("] ");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}

if(okKey==3&&(code[0]==0||code[0]==1)) //
code[0] will be stored to autoArm
{
autoArm=code[0];
noAutoArm=1;
lcd_clear();
if(autoArm==0)
lcd_putsf("Auto arming disabled");
if(autoArm==1)
lcd_putsf("Auto arming
enabled");
okKey=0;
settingsEntry=0;
delay_ms(2000);
nollaus();
}
if(triggered==1) //if in
"triggered" mode, "enter code" displayed
{
lcd_gotoxy(0,1);
lcd_putsf("enter code[ ]");
}
if(armed==1&&triggered==0) //if in
armed mode, "enter code to disarm" dispalyed
{
lcd_gotoxy(0,0);
lcd_putsf("enter code to disarm
[ ]");
}

if(arming==0&&settingsEntry==0&&settingsCodeQuery==0) //if in disarmed
mode
enterCode=0;
if(settingsCodeQuery==1) //if in settings
code query mode, "settings, enter code" displayed
{
lcd_gotoxy(0,0);
lcd_putsf("settings, enter code
[ ]");
}
}
}
SREG=0x80; //interruptions allowed
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //keypad rows
multiplexed
{
PORTD.4=1;
PORTD.5=1;
PORTD.6=1;
PORTD.7=1;

if(m==4)
PORTD.4=0;
if(m==5)
PORTD.5=0;
if(m==6)
PORTD.6=0;
if(m==7)
PORTD.7=0;

m++;
if(m==8)
m=4;
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
if(alarmDelay>0) //alarmDelay decremented
alarmDelay--;

if(armDelay>0) //armDelay decremented
armDelay--;

if(callTime>0) //callTime decremented
callTime--;

if(hornCycle==0) //if hornCycle==0, horn inverted and hornCycle
reset to 3
{
horn=~horn;
hornCycle=3;
}
hornCycle--; //hornCycle decremented


//PORTC.3=~PORTC.3; //led

}


void main(void)
{

// Input/Output Ports initialization
// Port A initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out
Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0
State0=0
PORTA=0x00;
DDRA=0xFF;

// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In In Func1=In
Func0=In
// State7=P State6=T State5=P State4=P State3=P State2=P State1=P
State0=P
PORTB=0xBF;
DDRB=0x00;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out
Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0
State0=0
PORTC=0x00;
DDRC=0xFF;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In
Func0=In
// State7=1 State6=1 State5=1 State4=1 State3=P State2=P State1=P
State0=P
PORTD=0xFF;
DDRD=0xF0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x05;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: On
// INT1 Mode: Falling Edge
// INT2: On
// INT2 Mode: Falling Edge
GICR|=0xE0;
MCUCR=0x0A;
MCUCSR=0x00;
GIFR=0xE0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x05;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1) //main loop: waiting for correct,
checking for "arming", and monitoring "POWER"
{
keypad();
IGNITION=1; //ignition enabled
if(POWER==1) //when ignition power is turned on,
noAutoArm is reset (with debounce)
{
delay_ms(1000);
if(POWER==1)
noAutoArm=0;
}
if(correct==1||arming==1||
(settingsEntry==0&&noAutoArm==0&&autoArm==1&&POWER==0))
//if correct code fed, arming==1
already, or auto arming triggered

{
correct=0;
arming=1;
IGNITION=0;
lcd_clear();
armDelay=setArmDelay;
while(1) //loop: arming, with
delay
{
keypad();
itoa(armDelay,intToChar);
lcd_gotoxy(0,0);
lcd_putsf("arming... [");
lcd_puts(intToChar);
lcd_putsf("] ");
lcd_gotoxy(0,1);
lcd_putsf(" [");
lcd_gotoxy(15,1);
lcd_putsf("]");
if(armDelay==0||armed==1) //if armDelay
time-out or armed==1 already
{
armed=1;
lcd_clear();
lcd_putsf("armed");
delay_ms(2000);
lcd_gotoxy(0,0);
lcd_putsf("enter code to disarm
[ ]");
while(1) // loop:
armed, waiting for sensor trigger or correctCode
{
keypad();
if(SENSOR==0||POWER==1||
triggered==1) //if SENSOR or POWER signal fed
{ //
or triggered==1 already
triggered=1;
lcd_gotoxy(0,1);
lcd_putsf("enter code[ ]");
alarmDelay=setAlarmDelay;
while(1) //loop: triggered,
alarm being activated, with delay
{
keypad();
lcd_gotoxy(0,0);
lcd_putsf("alarm ");
itoa(alarmDelay,intToChar);
lcd_gotoxy(6,0);
lcd_puts(intToChar);
lcd_putsf(" ");
if(alarmDelay==0||
alarm==1) //if alarm delay time-out or alarm==1
{
lcd_gotoxy(5,0);
lcd_putsf(" ");
alarm=1;
callTime=4; //CALL
signal activated
CALL=1;
while(1) //loop:
alarm activated
{
keypad();
BLINKERS=1;
HORN=horn;
if(callTime==0)
CALL=0;

if(correct==1) //if correct code fed, disarmed
break;
};
}
if(correct==1)
break;
};
}
if(correct==1)
break;
};
}
if(correct==1)
{
noAutoArm=1;
BLINKERS=0;
HORN=0;
CALL=0;
correct=0;
alarm=0;
triggered=0;
armed=0;
arming=0;
enterCode=0;
lcd_clear();
lcd_putsf("disarmed");
delay_ms(2000);
break;
}
};
}
};
}

Are you using the WDT? try turning it off...
 
H

Homer J Simpson

Jan 1, 1970
0
but it tends to freeze when it's counting either arming or alarm
delay.
It doesn't freeze everytime, but often, say, averagely every other
time.

It does it because you coded it to do it. What else?
 
S

Simoc

Jan 1, 1970
0
Homer said:
It does it because you coded it to do it.

Of course. But I meant "how did I do that" :)
What else?

See above.

I really don't expect you'd like to debug. Just if someone is having
too much time and energy.
Or if there's just some little thing that might be causing that.

I've spent myself a couple of months unsuccesfully trying to find the
bug, and am still doing.
So I thought to ask, if someone could help. Sorry if you found it
offensive.
 
S

Simoc

Jan 1, 1970
0
scada said:
Are you using the WDT? try turning it off...

Thanks for the only proper reply in the thread =)
But I'm not using WDT, at least not intentionally. And AFAIK, it
should reset the chip if it times out, and not cause freezing. But I
found that as I reduced the clock freq from 8MHz to 1MHz, it's now
working better, but still freezes sometimes...
 
H

Homer J Simpson

Jan 1, 1970
0
So I thought to ask, if someone could help. Sorry if you found it
offensive.

I didn't find it offensive. I just pointed out that the problem is in the
code, barring some odd hardware problem.
 
S

Simoc

Jan 1, 1970
0
Anthony said:
it smells like this to me. You're probably overflowing the stack
somewhere or damaging the program context in an ISR.

I thought too that it might be something like that, but as I'm still
not too familiar, with these things, I didn't know what that would
practically mean...so thanks for your suggestion, that would confirm
my thinking.
You have to sit down
and figure out your worst case scenario of call stack depth. You have to
take into consideration that the ISR can occur at any time and also pushes
the stack at least one level and then further pushes it when it calls other
functions. You are also spending vast amounts of time inside an interrupt
handler.

Yes, I've been doing so, but haven't got a real good idea yet..
That's not necessarily bad, but it is a sign that maybe you should
attack the problem a little bit differently <snip>

Well, I'll try to examine that more...
After looking at your code some, I don't understand why you are setting SREG
at the beginning and end of some of your ISRs.

The idea was to secure the completing of the ISR before starting
another, actually in order to prevent the stack overflow :) But
however, I based the idea just on my own logical thinking, which
probably went wrong.
Since you are
enabling interrupts at the end of your ISR manually, you're probably causing
your stack overflow right there when it re-enters the ISR without cleaning
up from the previous invocation.

Thanks for the suggestion, I'll try removing the SREG settings.
 
S

Simoc

Jan 1, 1970
0
Homer said:
I didn't find it offensive.

Sorry, It just looked like a naive comment, and combined with Mikkel
Lund's one and some things IRL, I was losing my mind...
 
H

Homer J Simpson

Jan 1, 1970
0
Sorry, It just looked like a naive comment, and combined with Mikkel
Lund's one and some things IRL, I was losing my mind...

Your question was unfocused. At this point you need some sort of debugger,
hardware or simulator, IMO.
 
S

Simoc

Jan 1, 1970
0
Anthony said:
Nah, he doesn't really need any of that to fix this. A scope, some LEDs and
a couple of spare i/o pins will do fine.

Thanks for the idea, I might try that approach sometime..
I really suspect that the manual manipulation of SREG and interrupt enabling
is what is getting him by causing the ISR to be reentered recursively. The
compiler should be taking care of enabling interrupts as part of the exit
code for the ISR. Manually enabling interrupts while inside an ISR is
usually dangerous at best. It's not necessarily wrong, but I suspect the OP
can avoid it.

Unfortunately, it seems that I was probably right in my thinking :
( ...I tried removing the SREG settings from the code, but it just
made the thing working a lot worse.
I don't know how big his stack is, or how it works. On a PIC, he'd have a
huge problem with what he is doing since it has only 8 levels of stack
depth. I assume the AVR he is using is deeper than that?

Sorry my newbiness, I don't know it myself either... I tried to look
for that on the datasheet, I did't find anything about "stack
levels", but I found this kind of text:

"During interrupts and subroutine calls, the return address program
counter (PC) is
stored on the Stack. The Stack is effectively allocated in the general
data SRAM, and
consequently the stack size is only limited by the total SRAM size and
the usage of the
SRAM. All user programs must initialize the SP in the reset routine
(before subroutines
or interrupts are executed). The Stack Pointer SP is read/write
accessible in the I/O
space. The data SRAM can easily be accessed through the five different
addressing
modes supported in the AVR architecture."

So might the number of stack levels be somehow dynamic?
 
H

Homer J Simpson

Jan 1, 1970
0
So might the number of stack levels be somehow dynamic?

In a larger processor, i.e., not a PIC. But if you recurse any computer you
can run out of stack.
 
Top