Jump to content

How To Play With The Timers And Isr


Recommended Posts

Hi all,

Before posting this thread I have gone through the topic "pic Micro Programming In Boostc For Beginners" by Mr. Raghunathan. Its really good for the beginers (Not to mention I am one of the beneficiaries of this thread and Thanks to Mr. Raghunathan or "ra68gi" for that). The 1 sec delay between switching LEDs program using timer 0 interrupt is where I am stuck a bit, not that I didnt get the idea behind it but, I didnt get the exact working of ISR. While learning software programming I was always taught to imagine the flow of the program and exactly this is what I am not getting correctly! e.g. Mr. Raghunathan has written the ISR as:

void interrupt( void )
{
unsigned char tick;
unsigned char tick1;

// writing 9 onto tmr0 will generate interrupts at 250us interval.
  tmr0 +=9;	
  tick++;	   //increment variable tick. 
  if(tick>19)   //if tick equals 20, increment tick1 & reset tick.
  {
  tick=0;
  tick1++;	  //if tick1 equals 200,we have counted 4000 ticks
if(tick1>199)	//in total, which equals 1 second(4000*250us).
  {
  tick1=0;		//reset tick1.
portb.0=~portb.0;   //toggle the led to show that 1sec has elapsed. 
}
}
intcon.2=0;  //clear TMR0 overflow flag
}
void main()
{
trisb = 0;		 //configure port B
portb = 0;		 //clear port B

option_reg = 8;	 //no prescaler & start tmr0

// enable interrupts
intcon.5=1;	 //enable tmr0 overflow interrupt	 
intcon.7=1;	 //enable global interrupt

/*simply write 6 to tmr0 counter value.This line will not alter
the accuracy of the clock, so it can be removed if you wish.
*/
tmr0=6;   


while( 1 ); //do nothing & wait for tmr0 interrupt.

 

First: Where exactlyin the program is timer0 activated? Secondly, Here I think that once a timer 0 is loaded with value 9, it will count upto 255 from 9 (i.e. 250 uSec, ya I understood how this was calculated), the varaible tick is incremented to x+1 (Here I assume that for the first time x=0). Now 'tick' is less then 19 so it would not execute the instruction in the braces below if(tick>19) and goes to intcon.2=0 to clear timer 0 overflow flag. Now it must again go to the main routine and must start executing while(1) instruction or is it doing something else? My confusion is how the 'tick' is incremented or rather how is timer 0 made to count again and again? The other form of my question may be if I want to use different amounts of time (1sec / 5 Sec / 10 Sec user selectable)using timer0 what will have to be done?

I hope I have not puzzled all you wizards there with my inapt questioning and that I am actually been able to present my confusion clearly. I hope to get my answers soon from all the gr8 & noble ppl around here, so thanx in advance

Regards

Shree

Link to post
Share on other sites

Hi Shree,

 

Timer 0 is set to run continuously and is being clocked by Fosc/4 or 1MHz if your PIC is running with a 4MHz osc. The timer 0 is set up using the option_reg = 0x08. Check out the bit settings.

 

You can change the led change time by changing the tick and tick1 compare values. tick is running at 5ms per cycle and tick1 every 1s or 200 x tick. You may have to use unsigned int's to get some of the longer times.

 

tick and tick1 probable should have been initialised = 0 during main for correctness but may have been cleared by startup code. See the -Su compile line option. The default for C is to clear static variables. tick and tick1 may be internally declared as static as they are within an interrupt, but don't hold me to that :)

 

Cheers

 

Reynard

Link to post
Share on other sites

I have written a tutorial on interrupts at http://www.opencircuits.com/A_Tutorial_on_...xample_Programs It may help.

I am not sure that everything is right ( but my programs seem to do what I want ) and would love review, comment, improvement from anyone on this forum.

 

Part of what make interrupt programming hard for most of us is that there is not a linear flow. It jumps around from here to there. To keep track of what is going on you normally

need some global variables which track the progress of the program. The main line of the program can often do other tasks, or just wait in a loop ( often testing the golbal variable to see when to exit the loop).

 

 

Russ

Link to post
Share on other sites
Hi all,

Before posting this thread I have gone through the topic "pic Micro Programming In Boostc For Beginners" by Mr. Raghunathan. Its really good for the beginers (Not to mention I am one of the beneficiaries of this thread and Thanks to Mr. Raghunathan or "ra68gi" for that). The 1 sec delay between switching LEDs program using timer 0 interrupt is where I am stuck a bit, not that I didnt get the idea behind it but, I didnt get the exact working of ISR. While learning software programming I was always taught to imagine the flow of the program and exactly this is what I am not getting correctly! e.g. Mr. Raghunathan has written the ISR as:

void interrupt( void )

{

unsigned char tick;

unsigned char tick1;

 

// writing 9 onto tmr0 will generate interrupts at 250us interval.

tmr0 +=9;

tick++; //increment variable tick.

if(tick>19) //if tick equals 20, increment tick1 & reset tick.

{

tick=0;

tick1++; //if tick1 equals 200,we have counted 4000 ticks

if(tick1>199) //in total, which equals 1 second(4000*250us).

{

tick1=0; //reset tick1.

portb.0=~portb.0; //toggle the led to show that 1sec has elapsed.

}

}

intcon.2=0; //clear TMR0 overflow flag

}

void main()

{

trisb = 0; //configure port B

portb = 0; //clear port B

 

option_reg = 8; //no prescaler & start tmr0

 

// enable interrupts

intcon.5=1; //enable tmr0 overflow interrupt

intcon.7=1; //enable global interrupt

 

/*simply write 6 to tmr0 counter value.This line will not alter

the accuracy of the clock, so it can be removed if you wish.

*/

tmr0=6;

 

 

while( 1 ); //do nothing & wait for tmr0 interrupt.

 

First: Where exactlyin the program is timer0 activated? Secondly, Here I think that once a timer 0 is loaded with value 9, it will count upto 255 from 9 (i.e. 250 uSec, ya I understood how this was calculated), the varaible tick is incremented to x+1 (Here I assume that for the first time x=0). Now 'tick' is less then 19 so it would not execute the instruction in the braces below if(tick>19) and goes to intcon.2=0 to clear timer 0 overflow flag. Now it must again go to the main routine and must start executing while(1) instruction or is it doing something else? My confusion is how the 'tick' is incremented or rather how is timer 0 made to count again and again? The other form of my question may be if I want to use different amounts of time (1sec / 5 Sec / 10 Sec user selectable)using timer0 what will have to be done?

I hope I have not puzzled all you wizards there with my inapt questioning and that I am actually been able to present my confusion clearly. I hope to get my answers soon from all the gr8 & noble ppl around here, so thanx in advance

Regards

Shree

Sree,

You can build this program in the sourceboost IDE and check how the code gets executed using the debugger/simulator. You can also see the Special function reg-

gisters & their values change while stepping thro' the code. Especially watch the tmr0 register and intcon register.

 

1) The register that contols tmr0 is the option register. learn more about it by down loading the datasheet of your chip from microchip.com

2) Its interrupts are controlled by the bits 5 & 7 of the intcon register(also in datasheet).

3) Its interrupt flag is activated by bit 2 of intcon register.

4) while(1); is infinite loop where the micro does nothing. It sits here waiting for the next interrupt flag to go hi.

5)The beginner program also has a clock program to display hours minutes & seconds. You can use the same as template & modify it to suit your need.

 

Its good practice to initialize variables, but if it does not affect the outcome you needn't write those extra code.

 

Regards

Raghunathan.

Link to post
Share on other sites

Hello All,

Thanks a million Raynard (your short explaination was great!), Russ Hensel (there are many things that I can learn about interrupts from those fine tutorials) and ofcourse our own Mr. Raghunathan. Well certainly I am 100 steps ahead of what I was the day before. Thanks again all of you. Though I got most of my queries answered, few things still remain stuck in my mind as the gum in the teeth. I will be obliged if any of you would care to explain me the same.

1. What is the method for coming out of ISR? Or does it automatically jumps to main program when all the code in it is executed. But if that is so, there might be more code about other interrupts also!

2. Why in the above code in main program the timer0=6 is written? What would happen if I skip it or enter some other value?

3. What statement actually calls ISR in the above program? or rather where in the program does the execution jumps to ISR?

4. In ISR, must not the statement intcon.2=0 come before if tick>19? As the first thing that must be done in ISR is to activate the interrupt again and I suppose it wont get activated unless the flag is reset.

Regards

Shree

Link to post
Share on other sites

Hi Shree,

 

First of all I am going to recommend a good book for you.

 

"The Quintessential PIC Microcontroller" by Sid Ketzen, published by Springer. ISBN 1-85233-942-X

 

This is an excellent book for learning the ins and outs of the PIC.

 

An ISR is a procedure that is called automatically by the PIC when an interrupt flag is being waved at it. The ISR procedure will return to the point left from when it runs out of instuctions and hits the closing brace. Just like any other procedure or function does.

 

When timer0 rolls over from 0xff to 0x00 the TOIF flag will be set. Assuming TOIE and GIE are enabled the ISR will be entered, the return program address will be saved on the stack for use when the ISR has ended. The compiler will add in some extra code to save specific registers like W and status bits. These will be restored upon exit of the ISR.

 

With alot of PICs, 12 and 16 series, there is only one interrupt vector so so another interrupt occuring will be ignored until the current interrupt is processed. Now if you want to handle multiple interrupt flags (from different peripherals) you can do a poll of interrupt flags and process then one after the other. There are various ways of handling interrupts. The PIC will enable it to be interrupted again when it exits the interrupt procedure by execution of the "Return from interrupt" instruction which turns on some internal flags.

 

The timer0 will overflow every 256 counts, which is 256us if clocked at 1MHz. The tick = 6 makes the timer overflow after 250us i.e. the timer countes from 6 to 255 before setting the interrupt flag. In reality this is not true because there is an overhead of around 5-6 instructions before any ISR instructions are executed (vectoring to the ISR procedure, saving register).

 

Hope this clears thing up a little. Remember to get a good book.

 

Cheers

 

Reynard

Link to post
Share on other sites

Hii Reynard,

Thanks alot again! I dunno what would had happened if I wont had been using BoostC, because then I wont had been using this forum and how could I had managed without all of you! Well, I will surely find out if I am getting that book out here in Mumbai (Bombay that is) and ya most of my queries are answered. Thanks for that!

Now beware world here comes one more extremely talented programmer (thats me!;)). Thanks for your help raynard. Although all of them here cared to answer my queries, but your answers were made for me. Do you take tutions? So I can take few classes from you! :lol: Anyways Thanks again and would bother you the next time I am stuck.

Regards

Shree

Link to post
Share on other sites
Hii Reynard,

Thanks alot again! I dunno what would had happened if I wont had been using BoostC, because then I wont had been using this forum and how could I had managed without all of you! Well, I will surely find out if I am getting that book out here in Mumbai (Bombay that is) and ya most of my queries are answered. Thanks for that!

Now beware world here comes one more extremely talented programmer (thats me!;)). Thanks for your help raynard. Although all of them here cared to answer my queries, but your answers were made for me. Do you take tutions? So I can take few classes from you! :lol: Anyways Thanks again and would bother you the next time I am stuck.

Regards

Shree

 

I have a pdf of the book I think I got on the net. Think it was legal, but do not rember where I got it. Google and perhaps you can find it. If it looks legal download it. This could save you time and money. You could let us know what you find.l

Link to post
Share on other sites

Hello All,

Is something wrong in the following code, it doesnt seem to be working. I physically assembled the circuit having 8 LED's. My aim was to blink the LEDs (from RB0 to RB7) one each at a time after a gap of 1 second each time. When the program runs only first LED glows and thats all! Please help me.

The code:

#include <system.h>

#pragma CLOCK_FREQ 4000000

#pragma DATA_CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF

void interrupt(void)

{

unsigned char tick=0;

unsigned char ticky=0;

tmr0 +=9;

tick++;

if(tick>19)

{

tick=0;

ticky++;

if(ticky>199)

{

ticky=0;

portb=portb<<01;

}

}

intcon.2=0;

}

 

void main()

{

trisb = 0X00;/* Setting Port B to output*/

portb=0X01;/*initialising Port B*/

option_reg = 0x08; /*configuring option register for prescaler as 1:1 and timer0 selected*/

intcon.5=1; /* timer0 overflow interrupt enabled */

intcon.7=1; /* Global interrupt enabled */

while(1){}

}

Link to post
Share on other sites

Hi Shree,

 

You are almost there.

 

The variables tick and ticky will be initialised to zero every time the interrupt function is called. Just like any other function.

 

If you make them "static" variables then they will only be initialised once. i.e. static unsigned char tick = 0;

 

Rather than use static variable you could just make them global and initialise them in main(). This will save some overhead time wise in the interrupt function by not having to test the initialise static flag. Static variables are usually cleared by the startup routine unless told not to by -Su in the compiler command line.

 

You may have to adjust the tmr0 += 9 to get an exact 250us. Use the debugger and use the tick counter on the status line to fine tune the value. Use the LED block plug-in as well to help you.

 

Cheers

 

Reynard

 

ps. Use bit names like intcon.GIE rather than intcon.7 so that they are easier to read and remember. You may want to test out the bit set and clear macros set_bit(intcon, GIE);

Edited by Reynard
Link to post
Share on other sites
  • 1 month later...

Hello Technocrats,

Had to go for a business trip so couldnt get ahead. Anyways back to work, here I was just trying to play more with the timers, I am gradually getting a hang of it. I would be really grateful if any of you could just go through the code and let me know whats wrong. In the IDE debugger mode the output seems to be what I intended (I was intending to serialy light LED or Make each pin of port B high for 1 Sec serially one after other), but when I actully connected it to the LED's physically, all the LEDs just flashed ones and thats all! I tried to Light the LEDs in binary order and was successful, but this one isnt working. Also in the binary light program, what I observed is the time intervel between each glow was not constant. The rest of the program body except the LED ON/OFF statement were the same as in the program below. I dont know why might that happen. Thanks a lot in advance for all you help

TC

Shree

The program:

 

#include <system.h>

#pragma CLOCK_FREQ 4000000

#pragma DATA_CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & PWRTE_OFF

unsigned char frstcnt=0;

unsigned char scndcnt=0;

unsigned char blink=128;

void interrupt (void)

{

tmr0 +=9;

frstcnt++;

if(frstcnt>19)

{

frstcnt=0;

scndcnt++;

if(scndcnt>199)

{

scndcnt=0;

portb=blink;

blink=blink>>01;

if(blink==0)

{

blink=128;

}

}

}

intcon.2=0;

}

 

 

void main()

{

trisb=0;

portb=0;

option_reg=8;

intcon.5=1;

intcon.7=1;

tmr0=6;

while(1);

}

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...