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.
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
}
}
}
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.
Yes, still gets me from time to time (I blame the basic people). 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.
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...
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.
Thanks for all the replies guys... let me drill down the code first and I'll get back to you.
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
}
}
}
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.
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.
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){}
}
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.
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){}
}
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){}
}