View previous topic :: View next topic |
Author |
Message |
cxiong
Joined: 09 Sep 2003 Posts: 52
|
For .. Loop Delay |
Posted: Mon Jun 11, 2007 12:10 pm |
|
|
I need help to created custom delay subroutine
I use a 20Mhz Crystal, PIC16F877A
Code: |
void main( void )
{
long i,j;
mcu_init(); /* Init of system clock and processor mode regsiters */
ENABLE_LEDS /* LED initialization */
while(1) /* Endless loop */
{
for(i=0; i<=???; ++i) // Example to delay 40uSec, what # do I need to replace with the ?
//post any formula will help
{
for(j=0; j<=???; ++j)
{
}
}
YLW_LED = LED_ON;
RED_LED = LED_OFF;
}
} |
Need to use the For ... Loop for delay (can not use the delay that came with compiler)
Appreciate if anyone can help me out .... |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Mon Jun 11, 2007 12:53 pm |
|
|
Doing a delay in this fashion will not have precise results. If the loop is interrupted by an interrupt routine the delay length will be longer. If you are not able to use the normal delay_us() command then I would suggest you use one of the timers. This will give you much better results and stability.
Ronald |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Mon Jun 11, 2007 1:28 pm |
|
|
Hello,
If you can not use delay_us() then the best way is to use the hardware built in counter.
here is an example:
Code: | #include <16F877A.h>
#device *=16
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //Crystal osc >= 4mhz
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
void main() {
int16 myDelayMs = 0 ;
// init...
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); // With 20Mhz cristal, Counter T1 is incremented every 1.6µSec
// T1 is 16 bit, so You can count 104 mSec
// 1 mSec = 625 Timer1 count.
//init ...
// for wait n mSec, you need to wait for n * 625
myDelayMs = 40 * 625 ; // for 40 mSec
set_timer1(0) ;
while ( get_timer1() < myDelayMs ) {
// You can make some think hier...
// but shorter than 104mSec
}
} |
_________________ in médio virtus |
|
|
cxiong
Joined: 09 Sep 2003 Posts: 52
|
|
Posted: Mon Jun 11, 2007 1:58 pm |
|
|
I want to use in 40uSec
And it should be able reuse the delay through out the program.
If I use the timer, can I recall the routine and reuse it?
Can you explain how you get 1 mSec = 625 timer1 counter?
Thanks. |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Mon Jun 11, 2007 2:41 pm |
|
|
Sorry, i read 40mSec.
For n uSec, try : Code: |
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
|
So,with 20Mhz cristal, Counter T1 is incremented every 0.2µSec
T1 is 16 bit, so You can count 13 mSec
1 uSec = 5 Timer1 count
40 uSec = 200 Timer1 count
Quote: | Can you explain how you get 1 mSec = 625 timer1 counter? |
The calculation is simple. Take the external frequency (20MHz). This frequency is divided by 4 and give the internal clock = 5MHz.
This internal clock can be divided by 1, 2, 4 or 8 ( is the T1_DIV_BY_n parameter ).
The counter for timer 1 is 16 bit and incremented by this divider.
If this divider is 8 then the counter is incremented each 20000000/4/8 = 625000. 1/625000 = 0.000 0016 = 1.6 uSec.
1mSec = 1 / 0.0016 = 625.
I make about the same calculation for 1 uSec.
Best regards,
dro. _________________ in médio virtus |
|
|
|