hello all
i want to introduce delay in program in microsecond range. can any one give me some examples for lpc17xx.
Thanks in advance.
No. But someone is bound to present something that relies upon a High-Level Language (HLL) - do not believe it!
The following comes from a paper recently cited on this very forum:
"optimizing compilers are free (and, in fact, try very hard) to cache values in registers, to reorder computations, and to eliminate useless and redundant computations." (my emphasis) www.cs.utah.edu/.../emsoft08-preprint.pdf
See: http://www.keil.com/forum/docs/thread16679.asp
A perfect example of what the compiler is likely to consider "useless and redundant computations" is any form of pure time delay coded in the HLL!
See also: www.8052.com/.../162556
ok i understood that using C it is impossible to predict the delays in program and hence the proper way to introduce delay is to write the program in assembly. But can't we use timers provided by LPC17xx to generate delay? I saw one example in LPC17xx software bundle related to timer. the function to produce delay is as follows
void delayMs(uint8_t timer_num, uint32_t delayInMs) { if ( timer_num == 0 ) { LPC_TIM0->TCR = 0x02; /* reset timer */ LPC_TIM0->PR = 0x00; /* set prescaler to zero */ LPC_TIM0->MR0 = delayInMs * (9000000 / 1000-1); LPC_TIM0->IR = 0xff; /* reset all interrrupts */ LPC_TIM0->MCR = 0x04; /* stop timer on match */ LPC_TIM0->TCR = 0x01; /* start timer */ /* wait until delay time has elapsed */ while (LPC_TIM0->TCR & 0x01); } else if ( timer_num == 1 ) { LPC_TIM1->TCR = 0x02; /* reset timer */ LPC_TIM1->PR = 0x00; /* set prescaler to zero */ LPC_TIM1->MR0 = delayInMs * (9000000 / 1000-1); LPC_TIM1->IR = 0xff; /* reset all interrrupts */ LPC_TIM1->MCR = 0x04; /* stop timer on match */ LPC_TIM1->TCR = 0x01; /* start timer */ /* wait until delay time has elapsed */ while (LPC_TIM1->TCR & 0x01); } return; }
what i did not understand is
LPC_TIM1->MR0 = delayInMs * (9000000 / 1000-1);
Why they used (9000000 / 1000-1) ? what is the significance of this number?
Again thanks for your reply.
Regards Rahul Sen
"LPC_TIM1->MR0 = delayInMs * (9000000 / 1000-1);"
They are driving the timer with a 9MHz signal.
So to wait 1ms, you have to wait 9000000/1000 ticks. -1 is a correction because the match register is only compared once/tick.
So MR0=0 would mean that the timer would compare (and potentially auto-reset) with MR0 once/tick. MR0=1 would mean a comparison every second tick (at 0 and at 1).
Thanks for your reply.
i just wanted to know which method is more advantageous? Is there any limitation in using a particular method for a given situation.
Thanks again
Yes, there are limitations.
Polling a timer requires a fixed amount of setup time. So it can't be used for too short delays. Very short delays is then better handled by counting clock cycles from NOP instructions or similar - and when counting clock cycles, you should use assembler so _you_ control the instructions you are counting.
But as soon as the delay times are long enough that you can accept the setup times, then you get the advantage that polling a timer can be done in C.
it means i can't use timer method for 1 microsecond delay?
One more thing in the timer example they have mentioned CCLK = 72 MHz
In the system_lpc17xx.c file PCLKSEL0 have been set as 0x00000000 i.e. peripheral clock selection for timer 0 will be CCLK/4 72 / 4= 18MHz
But the counter value have been set according to 9MHz.
If you can set up the timer and reach the polling loop within 72 clock cycles, then you can use the timer method.
The issue here is if you can guarantee that your C compiler will always manage to produce code that reaches the polling loop within 72 clock cycles. Next thing is that you don't know what instructions the C compiler uses for the polling loop, so you don't know if you may get 1, 2, 3, 4, 5, ... clock cycles worst-case error because of where you are in the loop.
For very short delays using the timer method, it's best to write the code in assembler.
About 9MHz instead of 18MHz - I don't have an explanation right now, without looking closer at the processor. Maybe the example was originally written with the peripherial clock setting 11 instead of 00, which is 1/8 division. The documentation seems to indicate that the counter should be updated every PCLK when PR=0, so 18000000/1000-1 would have seen a more logical.
You may also try to use the WDT for this delay job. The internal RC oscillator (which is fixed freq) is not very good but depending on your requirement, it may handle it.
Just talking about timing, there are a large number of ways to generate some form of delay.
It's possible to take a SPI device and let it perform x words of transmission at a specific baudrate. There is no need to map any external pins, but the device can generate an interrupt when the virtual "transfer" is done.
Same thing with taking one of the four UARTs.
The CAN devices can also be abused.
A freerunning timer can be used in polling mode, where the current value is retrieved and stored in an unsigned. Then it's enough to constantly retrieve the current value and check if the difference with the start value is >= the requested delay time. This allows the timer to be used with less setup time.
There are even more ways to measure time in this specific processor. It's just a question of creativity and what delay range that is needed.
If the assembly language program is written in c file using embedded assembler, will it have the same effect as separate assembly program?
__asm void delay(uint16_t usec) { MOVS r1,#0 B |L1.6| |L1.4| ADDS r1,r1,#1 |L1.6| ADD r2,r0,r0,LSL #2 ADD r2,r2,r0,LSL #3 CMP r2,r1 BGT |L1.4| BX lr ENDP }