View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 23, 2003 6:55 pm |
|
|
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
|
|
Posted: Wed Sep 24, 2003 10:03 am |
|
|
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
|
|
Posted: Wed Sep 24, 2003 1:26 pm |
|
|
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
|
|
Posted: Wed Sep 24, 2003 1:51 pm |
|
|
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
|
|
Posted: Wed Sep 24, 2003 2:01 pm |
|
|
Ah yes, now it works perfectly!
Thanks to all that responded. |
|
|
Hans Wedemeyer
Joined: 15 Sep 2003 Posts: 226
|
|
Posted: Wed Sep 24, 2003 3:14 pm |
|
|
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
|
|
Posted: Wed Sep 24, 2003 5:27 pm |
|
|
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
|
|
Posted: Wed Sep 24, 2003 8:32 pm |
|
|
what a waste of resources...
About as good as a sledge hammer for cracking.
One simple TIMER1 ISR fixes all the problem... |
|
|
|