Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Problem setting up timer Interrupt using C18 compiler

Status
Not open for further replies.

elec123

New Member
Hi, everyone I have problem which is quite trivial but has taken me days now. All I want to do is set up a timer interrupt to trigger every 0.9525 milliseconds on a PIC 18F4431. The interrupt routine itself only switches a pin on and off just so I can measure whether the interrupt is working properly or not. I have never used interrupts in C18 before and I’m not too sure if it's set correctly. I've used Priority setup for the ISR although I don't really want too, but these were the only examples I could find. Attached is the code I’ve used, the last bit is just to set up a PWM signal which works fine. Any help would be great as this is driving me crazy. Oh, im writting the program in the new version of MPLAB IDE using the C18 compiler.
 

Attachments

  • liamtimer1.c
    2.8 KB · Views: 620
below is the code that i'm using....

#include <p18f4431.h> /* header file for PIC18F4431*/
#include <stdio.h>


/* CONFIGURATION BIT SET UP (all this is done using the configuration bit setup menu) */

/* Oscillator Set up */
/* All FOSC settings set up the ocilator to use HS mode */
/*control which uses external 16MHz crystal.*/
/*Also fail-safe clock mode disabled so uses the external clock setup.*/

/* RE7 (pin 4) to be set up as an input and not a master clear. */

/* Watchdog timer disabled as it is not required */

/* Low Voltage Program disabled so that pin 38 acts as normal I/O. */

/* Polarity of PWM reversed */

/* function prototypes */

void main(void); /* main code */
void init(void); /* Intialisition of the PIC */
void foo(void); /* Interupt Service Routine */

unsigned char test;

#pragma interruptlow foo save = PROD, test
void foo (void)
{
PIR1bits.TMR1IF = 0; /*clear interupt flags */

TMR1H = 0xF1; /* load higher byte */
TMR1L = 0x1D; /* Load lower byte */


}

#pragma code lowvector=0x18
void lowvector(void)
{

_asm goto foo _endasm
}
#pragma code

#pragma code highvector=0x08
void highvector(void)
{

_asm goto foo _endasm
}
#pragma code




void main()
{

init(); /* Intialisation for EUSART control */


while(1) /*Continous Loop*/
{
Nop();
}
}

void init()
{

/* Interrupt Setup */

INTCON = 0x00; /* Clear Registers */
PIR1 = 0x00;
PIE1 = 0x00;
TMR1L = 0x00;
TMR1H = 0x00;
T1CON = 0x00;
RCON = 0x00;


RCONbits.IPEN = 1; /* Set Priorities */
INTCONbits.GIEH = 1; /* Enable global Interupt */
INTCONbits.GIEL = 1; /* Enable peripheral interrupt */
T1CONbits.RD16 = 1; /* Enable 16bit read/write of timer. */
T1CONbits.T1CKPS1 = 0; /* Set Prescaler 1:1 */
T1CONbits.T1CKPS0 = 0;
T1CONbits.TMR1CS = 0; /* Increment every instructrion cycle */
T1CONbits.TMR1ON = 1; /* Enable the timer */
PIE1bits.TMR1IE = 1; /* Enable timer1 interrupt */

/* Load timer for interupt every 0.9525m seconds */
TMR1H = 0xF1; /* Load timer1 higher byte */
TMR1L = 0x1D; /* Load timer1 lower byte */

//PIE1.TMR1IE = 1;

/* Port Set Up*/
TRISA = 0x00; /* Set all pins for ouputs. */
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x00;
TRISE = 0x00;

/* PWM Setup */

PTCON0 = 0x03; /* 1:1 post and prescaler. Continuos up/down*/
/*mode with double updates.*/
PTCON1 = 0x80;
//PTCON.PTEN = 1; /* Turn on the time base. */
PWMCON0 = 0x40; /* Enable PWM 0,1,2,3,4 and 5 pins for PWM. */
/*And put them in complementry output mode. */
//UNDIS = 0; /* Enable updates of duty cycle. */

PTPERH = 0x07; /* Load the time base perod (1050Hz) */
PTPERL = 0x71;

PDC0H = 0x07; /* Duty Cycle of Half */
PDC0L = 0x71;
PDC1H = 0x07;
PDC1L = 0x71;
PDC2H = 0x07;
PDC2L = 0x71;

}
 
Check the C18 user guide on the Microchip website. I used that guide and the datasheet to set up a 1second pulse I hope to turn into a frequency counter. The LED blinks at about 1second but the rest isn't tested yet. Also, make sure your ADC's and comparators are off

#include<p18f4680.h>
#include<timers.h>
#include<delays.h>
#include<xlcd.h>

void timer_isr (void); //prototype
void counter_isr(void);

static int overflow;
static double freq;


#pragma code low_vector=0x18 // set instruction mem to low vector location
void low_interrupt(void) //define function at location 0x18
{
_asm GOTO counter_isr _endasm //jump to timer_isr
}

#pragma code //resume normal memory

#pragma code high_vector=0x08 //set mem to high vector
void high_interrupt(void)
{
_asm GOTO timer_isr _endasm //jump to counter_isr
}

#pragma code

#pragma interruptlow counter_isr //define goto point
void counter_isr(void)
{
//counter interrupt
overflow++;
PORTCbits.RC2=~PORTCbits.RC2; //toggle LED
Delay1KTCYx(100);
PORTCbits.RC2=~PORTCbits.RC2; //toggle LED
Delay1KTCYx(100);
PORTCbits.RC2=~PORTCbits.RC2;

INTCONbits.TMR0IF=0; //clear flag
}

#pragma interrupt timer_isr //define goto point
void timer_isr(void) //actual interrupt routine
{
overflow++;
T0CONbits.TMR0ON=0; //disable counter
PIE1=0x00; //disable timer1 interrupt
PIR1=0x00; //clear flag
T1CONbits.TMR1ON=0; //disable timer 1

PORTCbits.RC2=~PORTCbits.RC2; //toggle LED

freq=ReadTimer0(); //read current count
freq+=overflow*0xFFFF; //multiply # of overflows+1 by 16bits
//and add to current count

overflow=0; //clear registers and overflow
TMR0L=0x00;
TMR0H=0x00;

TMR1H=0x80; //pre load timer 1
TMR1L=0x00;
PIE1=0x01; //enable interrupt
T0CONbits.TMR0ON=1; //enable counter
T1CONbits.TMR1ON=1; //enable timer 1
}

/* used to hold 16-bit timer value */
union Timers
{
unsigned int lt;
char bt[2];
};

unsigned int ReadTimer0(void)
{
union Timers timer;

timer.bt[0] = TMR0L; // Copy Timer0 low byte into union
timer.bt[1] = TMR0H; // Copy Timer0 high byte into union

return (timer.lt); // Return the int
}


void main(void)
{
//led on RC2
overflow=0;
ADCON1=0x0F; //ADC init to digital
CMCON=0x07; //comparators off
PORTA=0x00;
TRISA=0x10;
T0CON=0x38;
TMR0L=0x00;
TMR0H=0x00;
RCON=0x80; //interrupt configure
INTCON=0xC0; //High en, peripheral en, Timer0 dis
//Timer0 flag INTCONbits.TMR0IF <2>
INTCON2=0x00; //tmr0 low priority
PIR1=0x01;
PIE1=0x01;
IPR1=0x01;


TRISC=0x00; //I/O port init
PORTC=0x00;

PORTCbits.RC2=1; //set indicator high

T1CON=0xCE; //Timer 1 module configure
TMR1H=0x80; //pre load timer 1
TMR1L=0x00;
T0CONbits.TMR0ON-1; //enable timer 0
T1CONbits.TMR1ON=1; //enable timer 1

while(1); //loop forever
}
 
elec123 said:
I have never used interrupts in C18 before and I’m not too sure if it's set correctly.
What happens exactly? Is the ISR working or not?

elec123 said:
I've used Priority setup for the ISR although I don't really want too, but these were the only examples I could find.
I took a quick look at your code... you've assigned a low priority level to function 'foo' but all interrupts are high priority by default. You have to clear IPR1bits.TMR1IP in order to make TMR1 a low priority. Or re-write your code using high priority interrupts only:
Code:
IPR1bits.TMR1IP = 1;   // default

;...

INTCONbits.GIEL = 0;   // disable low priority interrupts
 INTCONbits.GIEH = 1;   // enable high priority interrupts
 
;...

#pragma [B]interrupt[/B] foo 
void foo (void)
{
    PIR1bits.TMR1IF = 0;    /*clear interupt flags */
 
    TMR1H = 0xF1;     /* load higher byte */
    TMR1L = 0x1D;     /* Load lower byte */
 
}
 
Thanks so much eng1. Code is now working. Just for interest heres the whole of my code...



#include <p18f4431.h> /* header file for PIC18F4431*/
#include <stdio.h>


/* CONFIGURATION BIT SET UP (all this is done using the configuration bit setup menu) */

/* Oscillator Set up */
/* All FOSC settings set up the ocilator to use HS mode */
/*control which uses external 16MHz crystal.*/
/*Also fail-safe clock mode disabled so uses the external clock setup.*/

/* RE7 (pin 4) to be set up as an input and not a master clear. */

/* Watchdog timer disabled as it is not required */

/* Low Voltage Program disabled so that pin 38 acts as normal I/O. */

/* Polarity of PWM reversed */

/* function prototypes */

void main(void); /* main code */
void init(void); /* Intialisition of the PIC */
void foo(void); /* Interupt Service Routine */

unsigned char test;

#pragma interrupt foo
void foo (void)
{
PIR1bits.TMR1IF = 0; /*clear interupt flags */

test++; /* Toggle portA just to test timer frequency */
if (test == 0x03)
{
PORTA = 0x00;
test = 0x00;
}
if (test == 0x01)
{
PORTA = 0xFF;
test = 0x02;
}

TMR1H = 0xF1; /* load higher byte */
TMR1L = 0x1D; /* Load lower byte */

}


#pragma code highvector=0x08
void highvector(void)
{

_asm goto foo _endasm
}
#pragma code




void main()
{

init(); /* Intialisation for EUSART control */


while(1) /*Continous Loop*/
{
Nop();
}
}

void init()
{
test = 0x00;

/* Interrupt Setup */

INTCON = 0x00; /* Clear Registers */
PIR1 = 0x00;
PIE1 = 0x00;
TMR1L = 0x00;
TMR1H = 0x00;
T1CON = 0x00;
RCON = 0x00;


RCONbits.IPEN = 1; /* Set Priorities */
INTCONbits.GIEL = 0; /* disable low priority interrupts */
INTCONbits.GIEH = 1; /* enable high priority interrupts */
T1CONbits.RD16 = 1; /* Enable 16bit read/write of timer. */
T1CONbits.T1CKPS1 = 0; /* Set Prescaler 1:1 */
T1CONbits.T1CKPS0 = 0;
T1CONbits.TMR1CS = 0; /* Increment every instructrion cycle */
IPR1bits.TMR1IP = 1; /* Make high priority interrupt */
T1CONbits.TMR1ON = 1; /* Enable the timer */
PIE1bits.TMR1IE = 1; /* Enable timer1 interrupt */

/* Load timer for interupt every 0.9525m seconds */
TMR1H = 0xF1; /* Load timer1 higher byte */
TMR1L = 0x1D; /* Load timer1 lower byte */



/* Port Set Up*/
TRISA = 0x00; /* Set all pins for ouputs. */
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x00;
TRISE = 0x00;

/* PWM Setup */

PTCON0 = 0x03; /* 1:1 post and prescaler. Continuos up/down*/
/*mode with double updates.*/
PTCON1 = 0x80;
//PTCON.PTEN = 1; /* Turn on the time base. */
PWMCON0 = 0x40; /* Enable PWM 0,1,2,3,4 and 5 pins for PWM. */
/*And put them in complementry output mode. */
//UNDIS = 0; /* Enable updates of duty cycle. */

PTPERH = 0x07; /* Load the time base perod (1050Hz) */
PTPERL = 0x71;

PDC0H = 0x07; /* Duty Cycle of Half */
PDC0L = 0x71;
PDC1H = 0x07;
PDC1L = 0x71;
PDC2H = 0x07;
PDC2L = 0x71;

}
 
hello everybody and sorry by my english.

i use pic18f452 mplab v8.85, compiler C18 v4.3 and win7. i'm using TIMER3 for two functions "delay_ms" and "delay_us" and works fine. But TIMER0 with interrupt is not so good because when start the interrupt, it go to high_vector=0x08 and next void HIGH_INT(void) and back to vector 0x08 and just do it. So, i need a help, please.

my program:
#main.c#
...
ini_Timer_0(18662);
...

#timer.c#
#include <p18f452.h>
#include "timer.h"

#define T0_IF INTCONbits.TMR0IF
#define T2_IF PIR1bits.TMR2IF
#define T3_OVF PIR2bits.TMR3IF

void HIGH_INT (void);
void LOW_INT(void);

#pragma code low_vector=0x18
void low_interrupt(void)
{ _asm GOTO LOW_INT _endasm }

#pragma code

#pragma code high_vector=0x08
void high_interrupt(void)
{ _asm GOTO HIGH_INT _endasm }

#pragma code

#pragma interrupt HIGH_INT
void HIGH_INT(void)
{
if (T0_IF){
T0_IF = 0;
INT0_OVF();

}
}

void ini_Timer_0 (unsigned int time)
{
unsigned int i;

time *=3;
// i = 65607 - time;
i = 65534; //test
TMR0L = i;
TMR0H = i >> 8;
T0CON = 5; //prescaler 1/64
INTCON2bits.TMR0IP = 1;
INTCON = 0b11100000; // GIE
T0CONbits.TMR0ON = 1;
}
 
Status
Not open for further replies.

Latest threads

Back
Top