# How can I make 1 ms delay ?

Status
Not open for further replies.

#### bianchi77

Guys,

How can I make 1 ms second delay for 11.093Mhz crystal on AT89S52
Is this code right ?

Code:
void delay_ms(unsigned int msec)    //delay function
{
//;

unsigned int i,j;
for(i=0;i<msec;i++);
for(j=0;j<1110;j++);

}
Thanks

#### bianchi77

Delay Generator - 8052.com

---------- Post added at 14:26 ---------- Previous post was at 14:22 ----------

Delay Generator - 8052.com
I've tried it
Code:
; Delay Routine
Delay:
mov	R0,#8		; 1
D1:
mov	R1,#1		; 1

D2:
mov	R2,#59		; 1
djnz	R2,\$		; 2
nop			; 1
djnz	R1,D2		; 2
djnz	R0,D1		; 2
ret			; 2
;
; call into routine		; 2
;
; initial mov			; 1
;
; End of Delay - total cycles 1005
any idea on how to translate it into C ?

#### doraemon

##### Super Moderator
Staff member
Hello!

You can directly use this inside your C code.
I wouldn't bother with assembler. It's not portable, and if you look at the code
in 2 or 3 months, it will not be readable anymore even if you wrote it.

Th C function above is right, it should work.
BUT: You should NEVER hard code the ms value (1110).
#define LOOP_COUNT 1110

and then for(j = 0 ; j< LOOP_COUNT ; ++j)

Doing this, you can reuse your code on any other processor by changing the LOOP_COUNT to the
proper value.

Now one more comment: this method is one of the worst. Any micro controller has timers.
You can fire a timer, put the CPU to sleep and wait for the timer interrupt.

Dora.

#### bianchi77

Hello!

I wouldn't bother with assembler. It's not portable, and if you look at the code
in 2 or 3 months, it will not be readable anymore even if you wrote it.

Th C function above is right, it should work.
BUT: You should NEVER hard code the ms value (1110).
#define LOOP_COUNT 1110

and then for(j = 0 ; j< LOOP_COUNT ; ++j)

Doing this, you can reuse your code on any other processor by changing the LOOP_COUNT to the
proper value.

Now one more comment: this method is one of the worst. Any micro controller has timers.
You can fire a timer, put the CPU to sleep and wait for the timer interrupt.

Dora.
how can I use the timer, do you have idea ?

#### doraemon

##### Super Moderator
Staff member
Hello!

how can I use the timer, do you have idea ?
You mean the hardware timer? It depends on your processor.
Basically:
- Set up the timer; (to be done only once in the program setup)
Now when you want to use it:
- Let it start counting;
- Put the processor to sleep;

When the interrupt comes, continue what you were doing. This implies
some changes in your code architecture, but it's worth the pain.
The timer method works well for milliseconds, but for microseconds
it would probably become tricky due to the interrupt overhead
(maybe a few 10 **** cycles).

Dora.

#### bianchi77

I'm using 89S52, how can I make the code below becoming 1ms ?

like this one :
Code:
#include <reg52.h>
#include <stdio.h>

/*------------------------------------------------
Timer 0 Interrupt Service Routine.

Set a breakpoint on 'overflow_count++' and run the
program in the debugger.  You will see this line
executes every 65536 clock cycles.
------------------------------------------------*/
static unsigned long overflow_count = 0;

void timer0_ISR (void) interrupt 1
{
overflow_count++;   /* Increment the overflow count */
}

/*------------------------------------------------
MAIN C function
------------------------------------------------*/
void main (void)
{
/*--------------------------------------
Set Timer0 for 16-bit timer mode.  The
timer counts to 65535, overflows, and
generates an interrupt.

Set the Timer0 Run control bit.
--------------------------------------*/
TMOD = (TMOD & 0xF0) | 0x01;  /* Set T/C0 Mode */
ET0 = 1;                      /* Enable Timer 0 Interrupts */
TR0 = 1;                      /* Start Timer 0 Running */
EA = 1;                       /* Global Interrupt Enable */

/*--------------------------------------
Do Nothing.  Actually, the timer 0
interrupt will occur every 65536 clocks.
--------------------------------------*/
while (1)
{
}
}

---------- Post added at 09:24 ---------- Previous post was at 09:20 ----------

Hello!

You mean the hardware timer? It depends on your processor.
Basically:
- Set up the timer; (to be done only once in the program setup)
Now when you want to use it:
- Let it start counting;
- Put the processor to sleep;

When the interrupt comes, continue what you were doing. This implies
some changes in your code architecture, but it's worth the pain.
The timer method works well for milliseconds, but for microseconds
it would probably become tricky due to the interrupt overhead
(maybe a few 10 **** cycles).

Dora.

- Let it start counting;
- Put the processor to sleep;

How can I do that ?

#### doraemon

##### Super Moderator
Staff member
Hello!

As I told you, it depends on your processor.
If your processor has some kind of sleep mode, then you can do it. First read the docs.
Configure your timer, write an interrupt function, put the processor to sleep.
If there is no sleep mode, then using a timer is still a good solution because you will
have a better precision (you can fine-tune down to 1 clock cycle vs about 10 in the case
of a loop.

Dora.

#### Marvin_G

##### Junior Member level 3
Guys,

How can I make 1 ms second delay for 11.093Mhz crystal on AT89S52
Is this code right ?

Code:
void delay_ms(unsigned int msec)    //delay function
{
//;

unsigned int i,j;
for(i=0;i<msec;i++);
for(j=0;j<1110;j++);

}
Thanks
easy...just use crystal frequency...set timer 0 as delay..set in Timer mode register..baudrate..and serial port as well..
void delay (void) //1ms delay
{
TH0=0;
TL0=0;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(!TF0);
TR0 = 0;
TF0 = 0;
return;
}

#### bianchi77

easy...just use crystal frequency...set timer 0 as delay..set in Timer mode register..baudrate..and serial port as well..
void delay (void) //1ms delay
{
TH0=0;
TL0=0;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(!TF0);
TR0 = 0;
TF0 = 0;
return;
}
How can I calculate :

Code:
     TH0 = 0xFC;
TL0 = 0x66;
as 1 ms my crystal is 11.0592 Mhz, and uC =AT89S52

Thanks

---------- Post added at 23:14 ---------- Previous post was at 23:09 ----------

How can I calculate :

Code:
     void delay (void) //1ms delay
{
TH0=0;
TL0=0;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(!TF0);
TR0 = 0;
TF0 = 0;
return;
}
as 1 ms my crystal is 11.0592 Mhz, and uC =AT89S52

Thanks
11Mhz divide by FC66 ? equal to 1ms ?

11Mhz / 64614 = 171 ?

is it 171 cycle equal to 1ms ???

Thanks

#### IanP

See attachment, examples are in ASM and C ..

:wink:
IanP

#### Attachments

• 642.1 KB Views: 15

#### bianchi77

See attachment, examples are in ASM and C ..

:wink:
IanP
Thank you very much for the document

---------- Post added at 04:46 ---------- Previous post was at 04:42 ----------

I got it x=1ms/(6/11Mhz), then y= 65535- x, I must enter y into the timer to get 1ms delay, y=65535-1843 , y = FC66 Hex...

Thanks

---------- Post added at 04:49 ---------- Previous post was at 04:46 ----------

I can put this delay function like this ?

....
function A();
delay();
functionB();

Thanks

#### Marvin_G

##### Junior Member level 3
How can I calculate :

Code:
     TH0 = 0xFC;
TL0 = 0x66;
as 1 ms my crystal is 11.0592 Mhz, and uC =AT89S52

Thanks

---------- Post added at 23:14 ---------- Previous post was at 23:09 ----------

11Mhz divide by FC66 ? equal to 1ms ?

11Mhz / 64614 = 171 ?

is it 171 cycle equal to 1ms ???

Thanks
its 11.0729MHz..1 period freq-=12*(1/11.0729M)=1.085microsec
1ms/1.085microsec=922 cycles..
65536(max cycle) - 922= 64614 (decimal) = FC66 (hex)...this is for 1ms delay..understood?

#### bianchi77

its 11.0729MHz..1 period freq-=12*(1/11.0729M)=1.085microsec
1ms/1.085microsec=922 cycles..
65536(max cycle) - 922= 64614 (decimal) = FC66 (hex)...this is for 1ms delay..understood?
I got it, I read the document above..

#### bianchi77

easy...just use crystal frequency...set timer 0 as delay..set in Timer mode register..baudrate..and serial port as well..
void delay (void) //1ms delay
{
TH0=0;
TL0=0;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(!TF0);
TR0 = 0;
TF0 = 0;
return;
}
if I want to create 100ms,

Code:
void delay (void) //1ms delay
{
TH0=0;
TL0=0;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(!TF0);
TR0 = 0;
TF0 = 0;
return;
}

for (i=0;i<100;i++)
{
delay()
}
?

Thanks

#### luben111

@dora

Hello!
If there is no sleep mode, then using a timer is still a good solution because you will
have a better precision (you can fine-tune down to 1 clock cycle vs about 10 in the case
of a loop.
Dora.
Just to mention that it's possible to make a software delay with 1 cycle resolution. Even it's possible to make universal software delay procedure that takes the number of delay cycles and has resolution of one machine cycle. For sure it's more complex from what was listed above. And the timer is the preferred way for the delays - while you're waiting you can do some other tasks.
Regards

#### Tahmid

Which compiler are you using? Shouldn't the compiler have delay routines/functions?

#### bianchi77

Which compiler are you using? Shouldn't the compiler have delay routines/functions?
I use keil, is there a function in it ?

#### doraemon

##### Super Moderator
Staff member
Hello!

I'm aware of that.
If it just consists in consuming cycles, IAR provides a kind of function called delay_cycles(uint32 count);
I have never tried with only a few cycles, but with a fair amount of cycles (for instance delay_cycles(CLK_KHZ) allows
to delay exactly 1ms. CLK_KHZ is the clock frequency in khz. 25000 in case of a 25MHz clock. However, it consumes
clocks (therefore energy) and setting a timer is better.

Dora.

@dora

Just to mention that it's possible to make a software delay with 1 cycle resolution. Even it's possible to make universal software delay procedure that takes the number of delay cycles and has resolution of one machine cycle. For sure it's more complex from what was listed above. And the timer is the preferred way for the delays - while you're waiting you can do some other tasks.
Regards

Status
Not open for further replies.