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.

Timer0 Timeout.

Status
Not open for further replies.

Vizier87

Active Member
Hi guys,
Like declared before, I've just started to use MikroC (only for a week already) instead of ASM and I already think it's pretty comfortable for an impatient person like me.

Just a few more tweaks of C language itself and hopefully I can be good at this!
So...here's my problem (my Timer0 program to blink an LED, not using the normal Delay_ms directive) for my PIC18F4455:

Code:
[COLOR="red"]void main() {[/COLOR]

TRISD=0;                       // PORTD as output
IPEN_bit=1;                    // to enable all high priority interrupt
GIE_bit=1;                      // enable interrupt globally
T0CON= 0B00000101;     // 16-bit timer,internal clock, +ve edge,1:64 Prescale

[COLOR="blue"]while (1){[/COLOR]                      //Loop starts
TMR0H=0X00;               //reset both registers 
TMR0L=0X00;                //
TMR0IF_bit=0;               //clear the Timer0 interrupt flag
TMR0ON_bit=1;             //start the Timer

if (TMR0IF_bit=1);          //wait for the Timer0 interrupt flag bit to go HIGH
TMR0ON_bit=0;
PORTD=~PORTD;           //toggle PORTD
[COLOR="blue"]}[/COLOR]

[COLOR="red"]}[/COLOR]

I'm using a 20 Mhz crystal, so I suppose the delay generated should be 20Mhz/(4x65535x64)=1.19211109 Hz..

But what I got is a PORTD which turns on all the time without any flicker.
I suppose it has to do with the C language.
Any help is appreciated.

Vizier87
 
Last edited:
Hi Vizier, I've not long started using C myself. I find it a lot better and easier than assembly.

Remember that your while(1) statement is a loop. In your loop you are continuously clearing the timer and therefore it will never overflow.

Try something like this:

Code:
void main() {

TRISD=0;                       // PORTD as output
IPEN_bit=1;                    // to enable all high priority interrupt
GIE_bit=1;                      // enable interrupt globally
T0CON= 0B00000101;     // 16-bit timer,internal clock, +ve edge,1:64 Prescale

TMR0H=0X00;               //reset both registers 
TMR0L=0X00;                //
TMR0IF_bit=0;               //clear the Timer0 interrupt flag
TMR0ON_bit=1;             //start the Timer


while (1){                      //Loop starts


if (TMR0IF_bit=1){          //wait for the Timer0 interrupt flag bit to go HIGH
TMR0ON_bit=0;
PORTD=~PORTD;           //toggle PORTD
TMR0H=0X00;               //reset both registers 
TMR0L=0X00;                //
TMR0IF_bit=0;               //clear the Timer0 interrupt flag
TMR0ON_bit=1;             //start the Timer
}

}

}


It should work as-is, though I haven't tested it.
 
Last edited:
Actually, even easier, just change your 'if(TMR0IF_bit=1);' to a 'while(!TMR0IF_bit);' so that the program waits there until the interrupt flag is detected.
 
Might I suggest you start using indenting so your code is much easier to read.
Code:
[COLOR="green"]void ScrollDisplay(){[/COLOR]
char i,j,chr;
    [COLOR="blue"]for(i=0;i<20;i++){[/COLOR]
        [COLOR="red"]for(j=0;j<3;j++){[/COLOR]
            SetPos(i,j+1);
            chr=ReadChar();
            SetPos(i,j);
            WriteChar(chr);
        [COLOR="red"]}[/COLOR] 
    [COLOR="blue"]}[/COLOR]
    SetPos(0,3);
    for(i=0;i<20;i++)
        WriteChar(' ');
    SetPos(0,3);
[COLOR="green"]}[/COLOR]

The indenting shows where a command starts and stops. I've coloured them as well for clarity.

Mike.
 
"if(blah=1)" is a mistake as it first assigns 1 to blah, and that is always "true" by C syntax.

I believe you should have typed "if(blah==1)"

It's one of those C things that catches all of us sometimes... I still do it from time to time. :)
 
It's one of those C things that catches all of us sometimes... I still do it from time to time. :)

Yes, still gets me from time to time (I blame the basic people:D). Some people advocate putting if(1==var) so an error will be generated if you put if(1=var) but I never got into the habit.

Mike.
 
Nice...I just went back to take forty winks and now a set of replies!! Hehe thanks guys.
Actually, even easier, just change your 'if(TMR0IF_bit=1);' to a 'while(!TMR0IF_bit);' so that the program waits there until the interrupt flag is detected.
Gobbledok: Thanks for that tweak, and I have to tell you my C stinks... :eek:
Pommie: I've tried to use the C code wrapping, but this time it didn't work. I wondered why... but then you'd read my thread here.
Mr RB: You're right. I find that C language has dialects with it. C-18, MikroC, Hi-Tech C, blah3. :D

Thanks for all the replies guys... let me drill down the code first and I'll get back to you.

Vizier87
 
Hi guys, I've tried the tweaking as Gobbledok proposed and still no avail. Anything else to be scrutinized? How about the config part? Do I need to set any other Prescale other than dividing it by 4?
 
Had you indented it properly you would have seen your error,
Code:
void main() {
    TRISD=0;                       // PORTD as output
    IPEN_bit=1;                    // to enable all high priority interrupt
    GIE_bit=1;                      // enable interrupt globally
    T0CON= 0B00000101;     // 16-bit timer,internal clock, +ve edge,1:64 Prescale
    
    while (1){                      //Loop starts    
        TMR0H=0X00;               //reset both registers 
        TMR0L=0X00;                //
        TMR0IF_bit=0;               //clear the Timer0 interrupt flag
        TMR0ON_bit=1;             //start the Timer
        if (TMR0IF_bit=1);          //wait for the Timer0 interrupt flag bit to go HIGH
        [COLOR="red"]TMR0ON_bit=0;
        PORTD=~PORTD;           //toggle PORTD[/COLOR]  Not part of if statement
    }
}

TMR0ON and PortD aren't in the if statement.

Try,
Code:
void main() {
    TRISD=0;                       // PORTD as output
    IPEN_bit=1;                    // to enable all high priority interrupt
    GIE_bit=1;                      // enable interrupt globally
    T0CON= 0B00000101;     // 16-bit timer,internal clock, +ve edge,1:64 Prescale
    TMR0H=0X00;               //reset both registers 
    TMR0L=0X00;                //
    TMR0IF_bit=0;               //clear the Timer0 interrupt flag
    TMR0ON_bit=1;             //start the Timer
    
    while (1){                      //Loop starts    
        if (TMR0IF_bit==1){          //wait for the Timer0 interrupt flag bit to go HIGH
            TMR0IF_bit=0;
            PORTD=~PORTD;           //toggle PORTD
	}
    }
}

Mike.
 
Last edited:
Oh yeah!!! It worked like magic. Sorry Mike, I'll indent my codes in future. Like I said, I'm learning C coding as well along the way, so itsy bitsy stuff like this really helps.

Pommie is my hero of the day today. :)

Thanks.
 
No need to be sorry, I wasn't critisizing, just trying to show you that indenting makes code much easier to follow and debug.

Mike.
 
Thanks anyway. :)
Even with ASM my code writing exploration is limited up to before trying out Timers. I was exhausted by all the ASM syntaxes and I gave up pursuing coding much, and I only concentrated on electronics (building sensors, yadda yadda). Turns out to be a bad mistake and that reflected on my Final Year Project. Boo hoo.

Anyway I'm going to make up to that this time. God Willing.

Vizier87
 
I don't actually code in C, but use FlowCode, which uses BoostC. It is a pretty good program for writing programs for PICs or AVR whichever one you are using. I'm working on a complex Alarm program that I've actually made pretty good progress on. It allows you to run your program and see what it would do and kind of makes it a little easier to debug your program.
 
Hi guys,
For me to further my interrupt programming knowledge, I was told that the interrupt routine should be out of the main function so that the interrupt routine works while we utilize the peripherals. I tried it like below but it didn't work so hopefully I can get some clarification here. The objective is still the same; to toggle the PORTD pins.
Here's the thingy:

C:
void interrupt()   {
       if (TMR0IF_bit==1){
      PORTD=~PORTD;
      TMR0L=0XAE;
      TMR0H=0X15;
      TMR0IF_bit=0;
     
                                   }
                         }

void main() {

PEIE_bit=1;
GIE_bit=1;
TRISD=0;
T0CON= 0B00000000;         //1/2 Prescale
TMR0H=0X15;               //reset both registers
TMR0L=0XAE;                //
TMR0IF_bit=0;               //clear the Timer0 interrupt flag
TMR0IE_bit = 1;
TMR0ON_bit=1;             //start the Timer

while (1){}

                 }

Appreciate the help. :)
 
Last edited:
Your code looks fine but the interrupt will be occurring very fast and so you will not see the port flashing. Try setting the prescaler to 32 so you can see it better.

Mike.
 
I noticed that you are now indenting your code but notice you're not outdenting (is that a word?) again. You should indent at the start of a section (between braces) and outdent at the end. So your code above would be,
Code:
void interrupt() {
    if (TMR0IF_bit==1){
        PORTD=~PORTD;
        TMR0L=0XAE;
        TMR0H=0X15;
        TMR0IF_bit=0;
    }   // end of if statement aligned with if above
}       // end of interrupt aligned with start
 
void main() {
    PEIE_bit=1;
    GIE_bit=1;
    TRISD=0;
    T0CON= 0B00000000; //1/2 Prescale
    TMR0H=0X15; //reset both registers
    TMR0L=0XAE; //
    TMR0IF_bit=0; //clear the Timer0 interrupt flag
    TMR0IE_bit = 1;
    TMR0ON_bit=1; //start the Timer     
    while (1){} 
}

Hope I explained that well.

Mike.
 
Lemme see if I did it right this time:
C:
void interrupt() {
       if (TMR0IF_bit==1){
      PORTD=~PORTD;
      TMR0L=0XAE;
      TMR0H=0X15;
      TMR0IF_bit=0;
 
   }
}
 
void main() {
 
PEIE_bit=1;
GIE_bit=1;
TRISD=0;
T0CON= 0B00000000; //1/2 Prescale
TMR0H=0X15; //reset both registers
TMR0L=0XAE; //
TMR0IF_bit=0; //clear the Timer0 interrupt flag
TMR0IE_bit = 1;
TMR0ON_bit=1; //start the Timer
 
while (1){}
}

Is that ok? :)
 
Nearly right, the whole idea is that the code that is aligned is at the same depth program wise, so your if() should align with the closing brace,
Code:
void interrupt() {
   if (TMR0IF_bit==1){
      PORTD=~PORTD;
      TMR0L=0XAE;
      TMR0H=0X15;
      TMR0IF_bit=0;
 
   }
}
I also indent complete routines so I can see where they start and finish,
Code:
void main() { 
    PEIE_bit=1;
    GIE_bit=1;
    TRISD=0;
    T0CON= 0B00000000; //1/2 Prescale
    TMR0H=0X15; //reset both registers
    TMR0L=0XAE; //
    TMR0IF_bit=0; //clear the Timer0 interrupt flag
    TMR0IE_bit = 1;
    TMR0ON_bit=1; //start the Timer
     
    while (1){}
}
Once you get used to it, it will help you (and others) follow your code much easier.

Sometimes, if you mix tabs and spaces, this BB really messes up the indenting and there's not much you can do in that case.

Mike.
 
Thanks Mike. I'll be actively posting codes these times since anyway so this is really important so that in future people'll not be straining their eyes.

C:
void interrupt() {
    if (TMR0IF_bit==1){
        PORTD=~PORTD;
        TMR0L=0XAE;
        TMR0H=0X15;
        TMR0IF_bit=0;
 
    }
}
 
void main() {
 
    PEIE_bit=1;
    GIE_bit=1;
    TRISD=0;
    T0CON= 0B00000000; //1/2 Prescale
    TMR0H=0X15; //reset both registers
    TMR0L=0XAE; //
    TMR0IF_bit=0; //clear the Timer0 interrupt flag
    TMR0IE_bit = 1;
    TMR0ON_bit=1; //start the Timer
 
    while (1){}
}

Hope this is good enough. :)
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top