View previous topic :: View next topic |
Author |
Message |
lfnickel
Joined: 07 May 2010 Posts: 4 Location: New Jersey
|
PIC12F629_Timer 0 issue |
Posted: Fri May 07, 2010 10:38 am |
|
|
Hi guys
I'm pretty much new with micro controllers.
I'm trying to implement a TIMER0 with 33us, which is going to be 30.3Khz and toggle pin A4.
When I see the Stopwatch in MPLAB and I define a breakpoint inside the interruption I see 68us.
This is my code so far.
Could anybody help me with?
Code: |
#include <12F629.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#use delay(clock=4M) // fosc/4 --> 4MHz/4 = 1000000Hz =>1us
#define TMR0_COUNT 224
///////////////////////////////// DEFINES A PORT //////////////////////////////////////
#define PGD PIN_A0 // output
#define LED PIN_A1 // output
#define RECEIVER PIN_A2 // input
#define MODE PIN_A3 // input
#define TRANSMITTER PIN_A4 // output
#define RELAY PIN_A5 // output
///////////////////////////////// FUNCTION DECLARATIONS //////////////////////////////
void Initialize(void);
void Sensor_Check(void);
void Timer1(void);
void Timer2(void);
void Timer3(void);
///////////////////////////////// GLOBAL VARIABLES DECLARATION ///////////////////////
BYTE alarm_flag=0;
BYTE time=0;
///////////////////////////////// MAIN FUNCTION ///////////////////////////////////////////
void main()
{
Initialize();
// RESTART_WDT(); // kick the dog
while(1)
{
Sensor_check();
}
}
///////////////////////////////// SENSOR CHECK ///////////////////////////////////////////
void Sensor_check()
{
if(input(RECEIVER)== FALSE)
{
output_high(RELAY);
}
else
{
output_low(RELAY);
}
}
///////////////////////////////// INITIALIZE /////////////////////////////////////////////
void Initialize()
{
#use FAST_IO(A)
SET_TRIS_A( 0b00001100 ); // 1 = input // 0 = output
// PGD PIN_A0 // output
// LED PIN_A1 // output
// RECEIVER PIN_A2 // input
// MODE PIN_A3 // input
// TRANSMITTER PIN_A4 // output
// RELAY PIN_A5 // output
PORT_A_PULLUPS(TRUE); // turn pull up on SET BUTTOM
SETUP_TIMER_0(RTCC_INTERNAL);
SETUP_TIMER_0(RTCC_DIV_2);
SET_TIMER0(TMR0_COUNT);
SETUP_COMPARATOR(FALSE);
SETUP_VREF(FALSE);
ENABLE_INTERRUPTS(INT_TIMER0);
ENABLE_INTERRUPTS(GLOBAL);
/////////////////////// initialize ports ////////////////////////////
output_A(0x00); // turn off all outputs PORT A
}
///////////////////////////////// INTERRUPT BY TIMER 0 //////////////////////////////////////////
#INT_TIMER0 // interrupt each 33us
void timer0interrupt()
{
SET_TIMER0(TMR0_COUNT); // preset timer 33us
/////////////////////TRANSMITTER TOGGLE 30KHz/////////////////////////////////////
output_toggle(TRANSMITTER); // Set LED to oscilate in 30 Khz.
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Fri May 07, 2010 12:09 pm |
|
|
Do a search here for 'interrupt overhead' (look for both words). You will find what is going on....
Best Wishes |
|
|
lfnickel
Joined: 07 May 2010 Posts: 4 Location: New Jersey
|
|
Posted: Fri May 07, 2010 12:35 pm |
|
|
No luck so Far.
I tried many things and it didn't work.
I'm using internal oscillator.
Let's go from begging.
Should ? use 20Mhz or 4MHz here
#use delay(clock=4M)
?
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 07, 2010 12:46 pm |
|
|
This thread explains the interrupt overhead issue:
http://www.ccsinfo.com/forum/viewtopic.php?t=42222
The internal oscillator on the 12F629 only supports 4 MHz operation.
The data sheet says:
Quote: |
9.2.5 INTERNAL 4 MHZ OSCILLATOR
When calibrated, the internal oscillator provides
a fixed 4 MHz (nominal) system clock.
|
Yes, if you use a 20 MHz crystal, the PIC will run 5x faster, and this
will reduce the interrupt overhead time by a factor of 5. |
|
|
lfnickel
Joined: 07 May 2010 Posts: 4 Location: New Jersey
|
|
Posted: Fri May 07, 2010 1:36 pm |
|
|
I understood the overhead problem that I'm having now, and i know that i could use the preescale and divide, but then my frequency will lower.
I didn't want to use external parts for OSC.
How could i handle that in the code?
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Fri May 07, 2010 2:38 pm |
|
|
Except on the 12F629 being used here, there is no RETFIE 1, so the useage would instead have to be based on something like EX_GLINT.C.
Seriously, even with this, you will have problems.
An interrupt is responded to at the start of the 'next' instruction after it happens. So 1 or 2 instruction times delay. Then the code to save and restore the minimum registers will take about 10 instruction times, the return, a couple more, the toggling of the pin at least a couple more (more unless fast_io is used), and then clearing the interrupt another instruction time. So the processor is going to be spending over 50% of it's time just generating the pulse, at the very 'best'... :(
It is much simpler, to not actually use the interrupts. Multiple solutions:
1) Simply toggle pin, wait.
2) Use the interrupt flag, but not the interrupt. When the flag goes true, toggle the pin, clear the flag. Total time less than half a dozen instructions...
3) For speeds like this, the 'real' solution, is to change chips, and use a PWM, which generates the pulse for you...
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 07, 2010 2:52 pm |
|
|
The 12F683 is an 8-pin 12F-series PIC that has hardware PWM. |
|
|
lfnickel
Joined: 07 May 2010 Posts: 4 Location: New Jersey
|
|
Posted: Fri May 07, 2010 2:54 pm |
|
|
Hi Ttelmah,
I used your function as INT_GLOBAL, but even with that after certain time the micro gets lost and now i understand better why.
Yes I'm going to use toggle pin for this case. Faster and less time consuming.
Thanks. I learned a lot!
I'll keep going and i keep posting my doubts.
Regards. |
|
|
|