On 9 Jul 2006 14:29:00 -0700, "bromio" <bromio_47@yahoo.com> wrote:
>im required to make a digital clock , i made several codes using
>iteration for delay which give not perfect delay. So i want to have
>suggestion about how to use timer interrupts to have perfect 1 sec
>delay each time. ive written code please see am i using interrupts
>correctly..
>
[more code snipped]
Doing devides on a 8051 in an interrupt routine is not a good idea.
Using a switch statement in an interrupt routine on a 8051 using many
of the 8051 compilers not a good idea. (Switch statement code is not
re-entrant, so if you use a switch statement anywhere else you will
have very strange bugs)
Do the minimum in the interrupt routine. In stead of doing a divide
and a mod, rather have a timer counter that you increment every
interrupt. You then increment the "second" interrupt every n number of
timer interrupts.
something like:
int_counter++;
if(int_count>=NUMBER_OF_INTS_PER_SECOND)
{
int_counter=0;
sec_counter++;
if(sec_counter>=60)
{
sec_counter=0;
min_counter++;
}
}
Remember that if you are reading these variables from outside the
interrupt routine, they should be volatile.
Regards
Anton Erasmus
Reply by Dave●July 10, 20062006-07-10
On Sun, 09 Jul 2006 16:44:34 -0700, GaryKato@aol.com wrote:
>
> bromio wrote:
>>
>> LED[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,125,0x07,0x7F,111};
>> unsigned char AMPM[2]={119,115};
>>
>> timer1() interrupt 3
>> {
>> hmin=min/10;
>> lmin=min%10;
>> hhour=hour/10;
>> lhour=hour%10;
>> while(c<=4000)
>> {
>> le++;
>> c++;
>> switch(le)
>> {
>> <case stmt deleted>
>> }
>> }c=0;
>> sec++;
>> if(sec==60)
>> {sec=0;
>> min++;
>> }
>> if(min==60)
>> {min=0;
>> hour++;
>> }
>>
>> }
>> main()
>> {
>>
>> EA=1;
>> am=0;
>> le=0;
>> sec = 0;
>> min = 0;
>> hour= 0;
>> c=0;
>> init_timer();
>> for(;;)
>> {}
>> }
>
> A loop in an interrupt service routine? No. Interrupt service routines
> should do what is needed at that time and nothing more. They should be
> as quick as possible.
He's using the loop to refresh the LEDs and provide a delay, I think.
Commented code is usually required for assignments--Profs and TAs hate
to guess what code is supposed to do. That code should not be in the ISR.
If you are trying to adjust the ISR rate to once per second this way, give
up. There are other ways to get a one second (more or less) tick for your
clock, and none of them involve running off a second in your ISR. Hint:
think in terms of averages for one approach.
How does am ever change? How do you expect to reset this clock--wait
until midnight and plug it in? Why do you use different bases for values
in LED? Why does LED use a different base than (some of) AMPM? The
if-clauses at the end of the ISR should logically be nested--only if
sec==60 does min need to be checked for 60.
I wouldn't expect much of a grade out of this effort. :-/ _Rethink_
then rewrite.
~Dave~
Reply by Neil●July 10, 20062006-07-10
bromio wrote:
> im required to make a digital clock , i made several codes using
> iteration for delay which give not perfect delay. So i want to have
> suggestion about how to use timer interrupts to have perfect 1 sec
> delay each time. ive written code please see am i using interrupts
> correctly..
>
> #include <reg51.h>
> #include <stdio.h>
> unsigned char
> LED[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,125,0x07,0x7F,111};
> unsigned char AMPM[2]={119,115};
> long int
> x,sec=0,min=0,hour=0,lmin=0,hmin=0,c=0;hhour=0,lhour=0,le=0,am=0;
> sbit a=P3^0;
> sbit b=P3^1;
> sbit d=P3^4;
> sbit e=P3^7;
> sbit f=P3^6;
> void init_timer()
> {
> ET1=1;
> TMOD=0x20;
> TH1=0x6;
> EA=1;
> TR1=1;
> }
>
> timer1() interrupt 3
> {
> hmin=min/10;
> lmin=min%10;
> hhour=hour/10;
> lhour=hour%10;
> while(c<=4000)
> {
> le++;
> c++;
> switch(le)
> {
> case 1:
> a=0;
> b=1;
> d=1;
> e=1;
> f=1;
> P0=~LED[hhour];
> break;
>
> case 2:
> a=1;
> b=0;
> d=1;
> e=1;
> f=1;
> P0=~LED[lhour];
> break;
>
> case 3:
> a=1;
> b=1;
> d=0;
> e=1;
> f=1;
> P0=~LED[hmin];
> break;
>
> case 4:
> a=1;
> b=1;
> d=1;
> e=0;
> f=1;
> P0=~LED[lmin];
> break;
> case 5:
> a=1;
> b=1;
> d=1;
> e=1;
> f=0;
> P0=~AMPM[am];
> le=0;
> break;
> }
> }c=0;
> sec++;
> if(sec==60)
> {sec=0;
> min++;
> }
> if(min==60)
> {min=0;
> hour++;
> }
>
> }
> main()
> {
>
> EA=1;
> am=0;
> le=0;
> sec = 0;
> min = 0;
> hour= 0;
> c=0;
> init_timer();
> for(;;)
> {}
> }
>
Too much in the interrupt. Set a flag or inc a counter in the
interrupt. Do the work in main.
I assume this is a school project. CPU Xtals are do not have the
tolerance to keep time very well. It can be off by several minutes a month.
Reply by Gary...@aol.com●July 9, 20062006-07-09
bromio wrote:
> im required to make a digital clock , i made several codes using
> iteration for delay which give not perfect delay. So i want to have
> suggestion about how to use timer interrupts to have perfect 1 sec
> delay each time. ive written code please see am i using interrupts
> correctly..
>
> #include <reg51.h>
> #include <stdio.h>
> unsigned char
> LED[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,125,0x07,0x7F,111};
> unsigned char AMPM[2]={119,115};
> long int
> x,sec=0,min=0,hour=0,lmin=0,hmin=0,c=0;hhour=0,lhour=0,le=0,am=0;
> sbit a=P3^0;
> sbit b=P3^1;
> sbit d=P3^4;
> sbit e=P3^7;
> sbit f=P3^6;
> void init_timer()
> {
> ET1=1;
> TMOD=0x20;
> TH1=0x6;
> EA=1;
> TR1=1;
> }
>
> timer1() interrupt 3
> {
> hmin=min/10;
> lmin=min%10;
> hhour=hour/10;
> lhour=hour%10;
> while(c<=4000)
> {
> le++;
> c++;
> switch(le)
> {
> case 1:
> a=0;
> b=1;
> d=1;
> e=1;
> f=1;
> P0=~LED[hhour];
> break;
>
> case 2:
> a=1;
> b=0;
> d=1;
> e=1;
> f=1;
> P0=~LED[lhour];
> break;
>
> case 3:
> a=1;
> b=1;
> d=0;
> e=1;
> f=1;
> P0=~LED[hmin];
> break;
>
> case 4:
> a=1;
> b=1;
> d=1;
> e=0;
> f=1;
> P0=~LED[lmin];
> break;
> case 5:
> a=1;
> b=1;
> d=1;
> e=1;
> f=0;
> P0=~AMPM[am];
> le=0;
> break;
> }
> }c=0;
> sec++;
> if(sec==60)
> {sec=0;
> min++;
> }
> if(min==60)
> {min=0;
> hour++;
> }
>
> }
> main()
> {
>
> EA=1;
> am=0;
> le=0;
> sec = 0;
> min = 0;
> hour= 0;
> c=0;
> init_timer();
> for(;;)
> {}
> }
A loop in an interrupt service routine? No. Interrupt service routines
should do what is needed at that time and nothing more. They should be
as quick as possible.
Reply by Glenn Gundlach●July 9, 20062006-07-09
bromio wrote:
> im required to make a digital clock , i made several codes using
> iteration for delay which give not perfect delay. So i want to have
> suggestion about how to use timer interrupts to have perfect 1 sec
> delay each time. ive written code please see am i using interrupts
> correctly..
>
<snip code>
I take it C is the required language? The timer is a snap in assembler
- less than 10 lines. I'm not a C guy but that interrupt routine looks
all wrong to me. Oh well.
GG
Reply by bromio●July 9, 20062006-07-09
im required to make a digital clock , i made several codes using
iteration for delay which give not perfect delay. So i want to have
suggestion about how to use timer interrupts to have perfect 1 sec
delay each time. ive written code please see am i using interrupts
correctly..
#include <reg51.h>
#include <stdio.h>
unsigned char
LED[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,125,0x07,0x7F,111};
unsigned char AMPM[2]={119,115};
long int
x,sec=0,min=0,hour=0,lmin=0,hmin=0,c=0;hhour=0,lhour=0,le=0,am=0;
sbit a=P3^0;
sbit b=P3^1;
sbit d=P3^4;
sbit e=P3^7;
sbit f=P3^6;
void init_timer()
{
ET1=1;
TMOD=0x20;
TH1=0x6;
EA=1;
TR1=1;
}
timer1() interrupt 3
{
hmin=min/10;
lmin=min%10;
hhour=hour/10;
lhour=hour%10;
while(c<=4000)
{
le++;
c++;
switch(le)
{
case 1:
a=0;
b=1;
d=1;
e=1;
f=1;
P0=~LED[hhour];
break;
case 2:
a=1;
b=0;
d=1;
e=1;
f=1;
P0=~LED[lhour];
break;
case 3:
a=1;
b=1;
d=0;
e=1;
f=1;
P0=~LED[hmin];
break;
case 4:
a=1;
b=1;
d=1;
e=0;
f=1;
P0=~LED[lmin];
break;
case 5:
a=1;
b=1;
d=1;
e=1;
f=0;
P0=~AMPM[am];
le=0;
break;
}
}c=0;
sec++;
if(sec==60)
{sec=0;
min++;
}
if(min==60)
{min=0;
hour++;
}
}
main()
{
EA=1;
am=0;
le=0;
sec = 0;
min = 0;
hour= 0;
c=0;
init_timer();
for(;;)
{}
}