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("] 1n,0ff[ ] ");
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;
}
};
}
};
}
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("] 1n,0ff[ ] ");
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;
}
};
}
};
}