View previous topic :: View next topic |
Author |
Message |
giaanthunder
Joined: 19 Dec 2012 Posts: 4
|
delay function using timer 1 |
Posted: Wed Dec 19, 2012 3:15 am |
|
|
Hi everybody! i am trying to make a delay function like delay_ms() using timer 1 with pic 16f877a, but it didnt work at all. im using 4mhz xtal and the simulation was stuck at the line PORTD=0xff;
help me please
Code: | #include <main.h>
#include <def_877a.h>
void mydelay (int16 x)
{
int8 i=0;
for(i=0;i<x;i++)
{
set_timer1(0);
while(get_timer1()!=1000);
}
}
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //65.5 ms overflow
TRISD=0;
PORTD=0;
while(1)
{
PORTD=0xff;
mydelay(500);
PORTD=0;
mydelay(500);
}
} |
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Dec 19, 2012 4:02 am |
|
|
Several things:-
1) You don't tell us which simulator.
2) How long does it take to perform this test? " while(get_timer1()!=1000); "
3) How long does timer1 stay in the condition where timer1 is 1000?
4) #FUSES
5) Compiler version
6) ......................
Mike |
|
|
giaanthunder
Joined: 19 Dec 2012 Posts: 4
|
|
Posted: Wed Dec 19, 2012 4:21 am |
|
|
1/ im using protues to flash 8 led
2/ while(get_timer1()!=1000); make the pic delay until the timer1 reach 1000 (1000us=1ms) b/c i using 4mhz xtal so it take 1us to increase timer1 by 1. i think so.
3/ when timer1 reach 1000, i think it will do the next statement immediately
4/this is file .h:
Code: | #include <16F877A.h>
#device adc=16
#FUSES NOWDT, HS, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT
#use delay(clock=4000000) |
5/v4.114 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Wed Dec 19, 2012 4:48 am |
|
|
Start with i.
How can it count to 500?.....
You will potentially get problems reading the timer like this. Better to use the interrupt flag (not the interrupt). So:
Code: |
void mydelay (int16 x) {
int16 i; //...... Also no point in wasting time initialising it
for(i=0;i<x;i++) {
set_timer1(-1000);
clear_interrupt(INT_TIMER1);
while(!interrupt_active(INT_TIMER1)); //wait for the interrupt
}
}
|
Problem is that the 'read' is of two separate bytes. To ensure that one hasn't changed while you have read the other, the compiler has to check if the MSB has changed since the LSB as read, making the read very slow (takes typically 12+ machine cycles). Then testing a 16bit value involves another half dozen cycles. The interrupt bit is read and tested in just one cycle.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Dec 19, 2012 5:07 am |
|
|
giaanthunder wrote: | 1/ im using protues to flash 8 led
2/ while(get_timer1()!=1000); make the pic delay until the timer1 reach 1000 (1000us=1ms) b/c i using 4mhz xtal so it take 1us to increase timer1 by 1. i think so.
3/ when timer1 reach 1000, i think it will do the next statement immediately
4/this is file .h:
Code: | #include <16F877A.h>
#device adc=16
#FUSES NOWDT, HS, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT
#use delay(clock=4000000) |
5/v4.114 |
1) Forget Proteus. I wont even install it. Read other's comments on this forum.
2) You answered the wrong question. I asked how long will it take to do the test, NOT how long will it take for timer1 to reach 1000.
Ttelmah has explained it's highly likely the test will never produce a true result.
In other words, you're doing the wrong test.
Testing for get_timer1()<1000 might have worked better.
3) Yes, timer1 will only be 1000 for 1us with your crystal and timer1 setting.
The test you were doing takes much longer, so you were more likely to miss than hit.
If you must simulate use MPLAB.
Better to use REAL hardware.
Mike |
|
|
giaanthunder
Joined: 19 Dec 2012 Posts: 4
|
|
Posted: Wed Dec 19, 2012 5:17 am |
|
|
thank you so much
I fix this code for hours but dont realize the problem was i, a very basic mistake
the idea using interrupt flag is so good. |
|
|
giaanthunder
Joined: 19 Dec 2012 Posts: 4
|
|
Posted: Wed Dec 19, 2012 5:43 am |
|
|
thanks Mike |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
for example---- |
Posted: Wed Dec 19, 2012 3:25 pm |
|
|
Code: |
// 18F family code - 8 mhz INTOSC 2mhz OP clock
// setup_timer_0( RTCC_DIV_8|RTCC_8_BIT ); // rollovers 1.024 ms ms 8 mhz
// setup_timer_0( RTCC_DIV_16|RTCC_8_BIT ); // rollovers 2.048 ms ms 8 mhz
// setup_timer_0( RTCC_DIV_32|RTCC_8_BIT ); // rollovers 4.096 ms ms 8 mhz
// wait for delay by appx mytix milliseconds
void msdelay(unsigned int16 mytix){
if (!mytix) return; // trap zero argument
setup_timer_0( RTCC_DIV_8|RTCC_8_BIT ); // set for rollovers 1.024 ms ms
set_timer0(0);
T0IF = 0; // one more 1 ms delay
DO {
while (!T0IF) { };
// --- this segment will execute every 1.024 msec
T0IF=0;
--mytix;
// -- and any POLLING operation that runs less than a msec
// can be placed here
} while (mytix);
}
|
Since I use timer0 for other stuff when not doing this timer bit -
I set it up for the delay I want at each use. |
|
|
|