CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Timer1 not keeping time as expected

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 23, 2003 6:55 pm     Reply with quote

PCMprogrammer suggested polling the "hardware interrupt
flag" for Timer1. What register address should I poll?


The Timer1 interrupt flag is bit 0 of the PIR1 register.
For the 16F877, you could define it like this:

#bit TMR1IF = 0x0C.0

Then get rid of this code:

flag = 0;
while(flag == 0);
{
}

and replace it with this:

TMR1IF = 0;
while(TMR1IF == 0); // Wait here until interrupt flag goes high
Hans Wedemeyer



Joined: 15 Sep 2003
Posts: 226

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 10:03 am     Reply with quote

As you are running at 20MHz and the time period is as long as 480uS it should be possible to do your work in the ISR.
I did something similar 1mS and 19mS and it wrkds just fine.

Try this... it is untedted, however I think it's reasonable.

Hans W

#include <16f877.h>

#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP
#zero_ram
#case

//global variables
long T480Value;
long T10msValue;
int flag;

/////////////////////////////////////////////////////////////////
// ____ ____
// PIN_D0 ____| |_________________________| |_________
// 480uS Aprox. 10mS
//
#INT_TIMER1
void my_timer1_intRoutine(void)
{
if ( flag == 0 )
{
set_timer1( T480Value ); // high
output_high(PIN_D0);
flag++;
}
else
{
output_low(PIN_D0); // low end of 480 microsecond pulse.
flag++ // flag is now 2
set_timer1( T10msValue ); //reload the timer for 500 uSec
if ( flag >= ) // 10mS / 500uS = 20
{
flag = 0
}
}
}
//////////////////////////////////////////////////
//
void main(void)
{
T480Value = 65536 - (0.00048/(4/20000000)); // the 480 uS value
T10msValue = 65536 - (0.0005 /(4/20000000); // the 500 uS value

setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);

set_timer1(T480Value); //480microsecond pulse.

enable_interrupts(GLOBAL);

output_low(PIN_D0); // start with pin low
flag = 0;

while(1)
{
}

} //end main
Freddie



Joined: 06 Sep 2003
Posts: 49

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 1:26 pm     Reply with quote

Thanks PCMprogrammer,
I like the idea of polling the Timer1 Interrupt Flag. Using the code below on an actual PIC and simulating it in MPLAB, TMR1IF never goes to 1. Timer1 is counting and rolling over though. Any ideas why?

#include <16f877.h>

#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP
#zero_ram
#case

int flag; //global variable

void main(void)
{
#bit TMR1IF = 0x0C.0

setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);

while(1)
{
output_high(PIN_D0);
set_timer1(65535-(480*5)); //480microsecond pulse.
TMR1IF = 0;
while(TMR1IF == 0); // Wait here until interrupt flag goes high
output_low(PIN_D0);

delay_ms(10); //pause between pulses.
}

} //end main

#INT_TIMER1
void my_timer1_intRoutine(void)
{

}
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Sep 24, 2003 1:51 pm     Reply with quote

Yeah, because you still have the interrupt handler there!

Code:

#include <16f877.h>

#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP
#zero_ram
#case
#bit TMR1IF = 0x0C.0


void main(void)
{
  setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  while(1)
  {
    output_high(PIN_D0);
    set_timer1(65535-(480*5)); //480microsecond pulse.
    TMR1IF = 0;
    while(TMR1IF == 0); // Wait here until interrupt flag goes high
    output_low(PIN_D0);

    delay_ms(10); //pause between pulses.
  }

} //end main



Regards,
Mark
Freddie



Joined: 06 Sep 2003
Posts: 49

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 2:01 pm     Reply with quote

Ah yes, now it works perfectly!

Thanks to all that responded.
Hans Wedemeyer



Joined: 15 Sep 2003
Posts: 226

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 3:14 pm     Reply with quote

If all the chip has to do is generate a pulse this code may be fine,
The main problem with this type of code is, the moment you need to do something else, the 480uS goes to hell...
With the solution I provided the while(1) (;) in main leaves your program open to handling other tasks, and the the pulse train will continue as expected.

hansw


#include <16f877.h>

#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP
#zero_ram
#case

int flag; //global variable

void main(void)
{
#bit TMR1IF = 0x0C.0

setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);

while(1)
{
output_high(PIN_D0);
set_timer1(65535-(480*5)); //480microsecond pulse.
TMR1IF = 0;
while(TMR1IF == 0); // Try to do somethinghere and the 480uS goes to hell... this is not a good idea... !
output_low(PIN_D0);

delay_ms(10); //pause between pulses.
}

} //end main
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 5:27 pm     Reply with quote

I like the hardware approach using the compare features of the CCP modules.
Just tested the code below, pulse was 479uS, time between pulses 10.0017mS.

#include <16F877.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,PUT,NOLVP
#define PULSE PIN_D0

#int_CCP1
CCP1_isr() {
output_bit(PULSE,0);
}

#int_CCP2
CCP2_isr() {
output_bit(PULSE,1);
}

void main(void)
{

setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // 0.2uS increments
setup_ccp1(CCP_COMPARE_INT);
setup_ccp2(CCP_COMPARE_RESET_TIMER);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_CCP2);
enable_interrupts(global);
set_timer1(0);
output_bit(PULSE,1);
CCP_1 = 480*5;
CCP_2 = (10000 + 480)*5;

while (1);

}
Hans Wedemeyer



Joined: 15 Sep 2003
Posts: 226

View user's profile Send private message

PostPosted: Wed Sep 24, 2003 8:32 pm     Reply with quote

what a waste of resources...
About as good as a sledge hammer for cracking.

One simple TIMER1 ISR fixes all the problem...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group