Timer interrupts (always them...)

General discussion on mikroC.
Post Reply
Author
Message
JediRemi
Posts: 5
Joined: 03 Jul 2010 01:32

Timer interrupts (always them...)

#1 Post by JediRemi » 03 Jul 2010 01:36

Hello all,
I m new to both the timer and interrupts things.

I tried to write a frequency meter
(using some code from http://www.micro-examples.com/public/mi ... meter.html )
on a PIC18 series (PIC18F2420)

I modified some parts but it s not working,
in debug mode it shows that the interrupt function is never called.

Code: Select all

// Lcd pinout settings
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D4 at RC4_bit;

// Pin direction
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC4_bit;

char freqt[20];
unsigned long   cntr ;          // number of RB0 transition
unsigned int    ovrflw ;        // number of timer0 overflows

void init() {
Lcd_Init();
}

/*
 * interrupt routine called 4000000/256 times by seconds :
 * the timer TMR0 is increased each 4 clock cycles (quartz frequency is 16 Mhz),
 * and overflows when reseting from 255 to 0,
 * calling the interrupt procedure with bit T0IF set
 *
 * also called on each RBO transition, with bit INTF set
 */
void    interrupt(void)
{
        if(INTCON.RBIF)
                {
                /*
                 * RB0 interrupt
                 */
                cntr++ ;                // inc. transition counter
                INTCON.RBIF = 0 ;       // clear interrupt flag to enable next call
                }
        else if(INTCON.TMR0IF)
                {
                /*
                 * TIMER 0 overflow
                 */
                ovrflw++ ;              // inc. overflow counter
                INTCON.T0IF = 0 ;       // clear interrupt flag to enable next call on overflow
                IntToStr(ovrflw,freqt);
                Lcd_Out(1, 2, freqt);
                }
        }

void main() {
     init();
     TRISB0_bit=1;

     T0CON = 0b11001000 ;       // no prescaler

        /*
         * main loop
         */
        for(;;)
                {
                cntr = 0 ;              // clear counters
                ovrflw = 0 ;
                INTCON = 0b10110000 ;           // GIE, T0IF and INTF enabled
                INTCON2.TMR0IP = 1;            // Timer interrupt high priority
                INTCON2.RBIP = 0;              // PortB interrupt low priority
                while(ovrflw < 19352) ;         // wait 1 second : 19352 = 20 000 000 / 4 / 256, rounded up
                INTCON = 0 ;                // stop all interrupts
                //LongToStr(ovrflw,freqt);
                //Lcd_Out(1, 2, freqt);
                }

}
I m fighting with those for a while(1) ... please help me
Last edited by JediRemi on 03 Jul 2010 03:18, edited 2 times in total.

JediRemi
Posts: 5
Joined: 03 Jul 2010 01:32

Re: Timer interrupts (always them...)

#2 Post by JediRemi » 03 Jul 2010 02:19

It appears that Software debugger does not handle timer ... GRRRRR
It works in proteus ISIS,

but another problem arise:
ovrflw should reach 19532 every second,
it is wayyyy slower.

I set 20Mhz in ISIS, but still.

The clock (crystal) is 20Mhz,
i divide by 4 to have the internal clock,
and then by 256 (cycles needed for timer 0 to overflow)
19352 = 20 000 000 / 4 / 256

then why it takes so long ?

------------
EDIT:

Other problem:
once PortB4 interrupt is called,
the other interrupt doesn't work anymore... T_T

JediRemi
Posts: 5
Joined: 03 Jul 2010 01:32

Re: Timer interrupts (always them...)

#3 Post by JediRemi » 04 Jul 2010 06:23

I figured out the problems:

-The PortB flag cannot be set to 0. To do so, we have to read PortB. (don t know why)
-The program doen t not work if the timer0 is set on 8 bit (if someone can tell me why), si I set it on 16 bits.

Corrected code: (work on Proteus ISIS)

Code: Select all

// Lcd pinout settings
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D4 at RC4_bit;

// Pin direction
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC4_bit;

char freqt[20];
unsigned long   cntr ;          // number of RB0 transition
unsigned int    ovrflw ;        // number of timer0 overflows
float freq;

void init() {
Lcd_Init();
}


void    interrupt(void)
{
        if(INTCON.RBIF)
                {
                //* RB0 interrupt
                cntr++ ;                // inc. transition counter
                RB4_bit=0;
                INTCON.RBIF = 0 ;       // clear interrupt flag to enable next call
                }
        else if(INTCON.TMR0IF)
                {
                //* TIMER 0 overflow *
                ovrflw++ ;              // inc. overflow counter
                INTCON.T0IF = 0 ;       // clear interrupt flag to enable next call on overflow
                }
        }

void main() {
     init();
     TRISB0_bit=1;

     T0CON = 0b10001000 ;       // 16 bit timer

        /*
         * main loop
         */
        while(1){
                cntr = 0 ;              // clear counters
                ovrflw = 0 ;
                RB4_bit=0;
                INTCON.RBIF = 0 ;       // clear interrupt flag to enable next call
                INTCON = 0b11111000 ;           // GIE, T0IF and INTF enabled
                RCON.IPEN=0; //enable interrupt priority
                INTCON2.TMR0IP = 1;            // Timer interrupt high priority
                INTCON2.RBIP = 0;              // PortB interrupt low priority
                while(ovrflw < 76) ;         // wait 1 second : 19352 = 20 000 000 / 4 / 256, rounded up
                INTCON.GIE = 0 ;                // stop all interrupts
                freq  = cntr/2; // the /2 factor should be corrected while tuning your setup.
                FloatToStr(freq,freqt);
                Lcd_Out(1, 2, freqt);
                }

}

User avatar
ranko.rankovic
Posts: 433
Joined: 11 Jun 2010 09:22

Re: Timer interrupts (always them...)

#4 Post by ranko.rankovic » 05 Jul 2010 17:06

Hello JediRemi,

I suggest you to look at this project.
It will give you another approach and maybe you'll get some new idea in solving your problem.

Best regards
Ranko Rankovic
mikroElektronika [Support Department]

JediRemi
Posts: 5
Joined: 03 Jul 2010 01:32

Re: Timer interrupts (always them...)

#5 Post by JediRemi » 05 Jul 2010 18:21

Thanks a lot

braus
Posts: 167
Joined: 25 Jul 2007 22:55
Location: Mexico, city.

Re: Timer interrupts (always them...)

#6 Post by braus » 02 Aug 2010 19:13

Code: Select all

char freqt[20];
unsigned long   cntr ;          // number of RB0 transition
unsigned int    ovrflw ;        // number of timer0 overflows

void init() {
Lcd_Init();
}

void    interrupt(void)
{
        if(INTCON.RBIF){
                cntr++ ;     //You are incrementing this variable but you are not using it forward, why?
                INTCON.RBIF = 0 ;   //in case a PORTB.B0 interrupt presents you clean the flag bit, and then?
         }   //what is going to do the MCU to response the interrupt?, besides you are not setting GIE bit
             //prior to leave the ISR


        if(INTCON.TMR0IF)  //I cut "else" word
                {
                ovrflw++ ;              // the same thing, you are not setting GIE bit prior to leave ISR
                INTCON.T0IF = 0 ;       // you are not loading an specific value in TMR0 to achieve an 
                IntToStr(ovrflw,freqt); //accurate time measurement
                Lcd_Out(1, 2, freqt);
                }
        }

void main() {
     init();
     TRISB0_bit=1;

     T0CON = 0b11001000 ;       // no prescaler

        /*
         * main loop
         */
        for(;;)
                {
                cntr = 0 ;              // clear counters
                ovrflw = 0 ;
                INTCON = 0b10110000 ;           // GIE, T0IF and INTF enabled
                INTCON2.TMR0IP = 1;            // Timer interrupt high priority
                INTCON2.RBIP = 0;              // PortB interrupt low priority
                while(ovrflw < 19352) ;         // wait 1 second : 19352 = 20 000 000 / 4 / 256, rounded up
                INTCON = 0 ;                // stop all interrupts
                //LongToStr(ovrflw,freqt);
                //Lcd_Out(1, 2, freqt);
                }

}

In summary, you have to take a deep reading and planification of this project because if the main idea is to measure a frequency you are not using CCP module, which is designed specifically to this kind of projects.
Best Regards
Omar Galicia
Mexico City

JediRemi
Posts: 5
Joined: 03 Jul 2010 01:32

Re: Timer interrupts (always them...)

#7 Post by JediRemi » 02 Aug 2010 19:39

I will then use the ccp module.
I will come back if I can't find a solution by myself.

Thanks a lot for the advice.

Post Reply

Return to “mikroC General”