Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
LinkBack Thread Tools Display Modes
Old 17th November 2007, 12:23 AM   (permalink)
Default Please help me with my Interrupts

I am currently working on a piece of code that uses two interrupt routines. A high priority and a low priority. I will be using the PIC18F4620 but currently only debugging in simulation mode in MPLAB (v7.60). I am using the MCC18 library to compile my code.
I am using a 20Mhz external oscillating crystal.

This is what i would like to happen:
Timer0 interrupts as a high priority
Timer1 interrupts as a low priority

This is what happens:
Timer0 interrupts as it should
Timer1 just sits there watching tea while drinking hot chocolate!

I would be very grateful if you can tell me where I've gone wrong.

All I care about is my interrupt flag..and my hair loss due to stress...

Here is my code, I realise its really unclear but I've tampered with it so many times its got messy.

#include <p18f4620.h>
#include <timers.h>
#include <stdio.h>
#include <delays.h>


void power (void);
void signal (void);
unsigned int ReadTimer0(void);
unsigned int ReadTimer1 (void);
void WriteTimer0( unsigned int timer );
void Delay100TCYx( unsigned char unit );
void Delay10TCYx( unsigned char unit );
void HandlerHigh (void);
void HandlerLow (void);

int number = 15;
unsigned char clock = 0;
unsigned char clock2 = 0;
int servo_flag = 0;

void main (void)
{
int Time = 0;

INTCON = 0x20; //disable global and enable TMR0 interrupt
INTCON2 = 0x84; //TMR0 high priority
IPR1 = 0x00; //TMR1 low priority
RCONbits.IPEN = 1; //enable priority levels
INTCONbits.GIEH = 1; //enable interrupts
INTCONbits.GIEL = 1; //enable low interrupts
OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_128);
T0CONbits.TMR0ON = 1;
TMR1H = 0;
TMR1L = 0;
T1CON = 0x13; /*b'00001001' */
PIE1bits.TMR1IE = 1;
RCONbits.IPEN = 1;

power();


while (1)
{
// clock++;
// signal(); //send out servo signal
}
}

void signal (void)
{
if (servo_flag == 1)
{
PORTAbits.RA1 = 1;
servo_flag = 0;
}

if (clock >= 100)
{
PORTAbits.RA1 = 0;

}
}

/*Set a Led to show PIC is running*/
void power (void)
{
ADCON1 = 0x0f;
TRISA = 0x00000110;
PORTA = 0;
PORTAbits.RA0 = 1;
}


//----------------------------------------------------------------------------
// High priority interrupt vector

#pragma code VectorHigh = 0x08
void VectorHigh (void)
{
_asm
goto HandlerHigh //jump to interrupt routine
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt HandlerHigh

void HandlerHigh (void)
{
if (INTCONbits.TMR0IF) //check for TMR0 overflow
{
clock++;
INTCONbits.TMR0IF = 0; //clear interrupt flag
}
if (clock > 2)
{
clock = 0;
servo_flag = 1;
}

}
//----------------------------------------------------------------------------
// Low priority interrupt vector
#pragma code VectorLow = 0x18
void VectorLow (void)
{
_asm
goto HandlerLow
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine
#pragma code
#pragma interrupt HandlerLow
void HandlerLow (void)
{
if (PIR1bits.TMR1IF) //check for TMR1 overflow
{
clock2++;
PIR1bits.TMR1IF = 0; //clear interrupt flag
}
}

// END

Please don't just recommend me to use OpenTimer1() unless you can inform me what needs to go in there. I tried this method first and failed.

Thanks for reading,

James
Wilko is offline  
Old 17th November 2007, 06:41 AM   (permalink)
Default

I believe your problem lies here:
T1CON = 0x13; /*b'00001001' */
The HEX doesn't match the binary. The HEX is setting up timer1 to use external clock from pin RC0/T1OSO/T13CKI. Which clock do you intend to use with timer1? For SIM, I would use the internal clock for simplicity.
__________________
--- The days of the digital watch are numbered. ---

Last edited by kchriste; 17th November 2007 at 06:55 AM.
kchriste is offline  
Old 17th November 2007, 07:46 PM   (permalink)
Default

Actually I want to use an external clock source. The same for timer0 and timer1. Timer zero is set to interrupt around20ms and timer1 needs to be 100us. Don't suppose you can see why timer1 interrupts so slowly. I've tried changing the pre scaler but nothing changes.
Wilko is offline  
Old 17th November 2007, 09:05 PM   (permalink)
Default

I've updated my code and now both my interrupts work but only if i use an internal clock and then it runs at the wrong speed. I want timer0 to interrupt every 20ms and timer1 as 100us. Im trying to get my code to use an external 20Mhz crystal but just no luck.

#include <p18f4620.h>
#include <timers.h>
#include <stdio.h>
#include <delays.h>


void power (void);
void signal (void);
//unsigned int ReadTimer0(void);
//unsigned int ReadTimer1 (void);

void HandlerHigh (void);
void HandlerLow (void);

int number = 15;
unsigned char clock = 0;
unsigned char clock2 = 0;
int servo_flag = 0;

void main (void)
{
int Time = 0;

INTCON = 0x20; //disable global and enable TMR0 interrupt
INTCON2 = 0x84; //TMR0 high priority
IPR1 = 0x00; //TMR1 low priority
RCONbits.IPEN = 1; //enable priority levels
INTCONbits.GIEH = 1; //enable interrupts
INTCONbits.GIEL = 1; //enable low interrupts
OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_EXT & T0_PS_1_128);
// T0CONbits.TMR0ON = 1;
// TMR1H = 0;
// TMR1L = 0;
// T1CON = 0x09; /*b'00001001'*/
PIE1bits.TMR1IE = 1;
RCONbits.IPEN = 1;
OpenTimer1(TIMER_INT_ON & T1_8BIT_RW & T1_SOURCE_EXT & T1_PS_1_2);
power();


while (1)
{
clock++;
signal(); //send out servo signal
}
}

void signal (void)
{
if (servo_flag == 1)
{
PORTAbits.RA1 = 1;
servo_flag = 0;
}

if (clock >= 100)
{
PORTAbits.RA1 = 0;
}
}

/*Set a Led to show PIC is running*/
void power (void)
{
ADCON1 = 0x0f;
TRISA = 0x00000110;
PORTA = 0;
PORTAbits.RA0 = 1;
}


//----------------------------------------------------------------------------
// High priority interrupt vector

#pragma code VectorHigh = 0x08
void VectorHigh (void)
{
_asm
goto HandlerHigh //jump to interrupt routine
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt HandlerHigh

void HandlerHigh (void)
{
if (INTCONbits.TMR0IF) //check for TMR0 overflow
{
clock++;
INTCONbits.TMR0IF = 0; //clear interrupt flag
}
if (clock > 2)
{
clock = 0;
servo_flag = 1;
}

}
//----------------------------------------------------------------------------
// Low priority interrupt vector
#pragma code VectorLow = 0x18
void VectorLow (void)
{
_asm
goto HandlerLow
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine
#pragma code
#pragma interrupt HandlerLow
void HandlerLow (void)
{
if (PIR1bits.TMR1IF) //check for TMR1 overflow
{
clock2++;
PIR1bits.TMR1IF = 0; //clear interrupt flag
}
}
Wilko is offline  
Old 17th November 2007, 11:58 PM   (permalink)
Default

To use an external clock for the timers in the SIM you need to open the SCL workbook. It's located under Debugger/SCL Generator/NewWorkBook. Click the clock stimulus tab and fill in the necessary info, save your workbook and then Generate SCL from Workbook. Close the workbook and then open the Stimulus Controller under Debugger/Stimulus Controller/NewScenario. Now load the file you created with the SCL generator by attaching the file here. Leave this window active while you run the simulation and it will toggle the pin as per your setup.
Quote:
Im trying to get my code to use an external 20Mhz crystal but just no luck.
Under Debugger/Settings... you can set the processor speed.
__________________
--- The days of the digital watch are numbered. ---
kchriste is offline  
Old 18th November 2007, 03:06 AM   (permalink)
Default

Thank you.

One last problem..Why is my timer1 taking so long to interrupt? it seems to always take around 13ms (using internal clock set in SIM as 20MHz). I'm after 100us or at least close to that.

Thanks guys
Wilko is offline  
Old 18th November 2007, 03:56 AM   (permalink)
Default

Timer1 is a 16bit timer and you are getting an interrupt when it rolls over. Timer0 is an 8bit timer and it can roll over 256 times faster. You need to preload timer1 during every interrupt by doing some thing like this:
TMR1H |= 0xF0;
Don't try to load TMR1L directly (TMR1L = 0xE0) because interrupt latency will add cumulative errors. Use the Or function instead.
__________________
--- The days of the digital watch are numbered. ---

Last edited by kchriste; 18th November 2007 at 04:00 AM.
kchriste is offline  
Old 18th November 2007, 07:24 AM   (permalink)
Default

You can also use the Special Events Trigger of the CCP module. This makes the CCP1 value a 16 bit period for timer1. Have a look at section 15.3.4 & 12.5 of the data sheet for details. Note that the interrupt generated is the CCP int, not the timer1 int.

Mike.
Pommie is offline  
Reply

Bookmarks

Thread Tools
Display Modes



Similar Threads
Title Starter Forum Replies Latest
Interrupts.... asp1987 Micro Controllers 4 1st October 2007 12:33 PM
Interrupts 16F88 andrew12345678 Micro Controllers 4 13th September 2007 12:38 PM
Status of a comparator affecting interrupts. 2camjohn Micro Controllers 7 19th July 2005 12:14 PM
Interrupts or not interrupts ? That is the question ! ZERS Micro Controllers 9 1st March 2005 08:26 PM
PIC18F452 & ADC --> no interrupts : is it right ? ZERS Micro Controllers 8 6th April 2004 10:32 AM



All times are GMT. The time now is 12:55 AM.


Electronic Circuits  |  Learning Electronics
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.

eXTReMe Tracker