Timers and Interrupts

Post here to teach people how to do something.

Moderators: Chuckt, Garth, bitfogav

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Timers and Interrupts

Post by sdudley » Sun May 30, 2010 5:56 am

Description:
This tutorial does exactly the same thing as Brad's LED flasher tutorial 2 (it makes an LED blink). However, it uses an interrupt routine to do the job.

Purpose:
To show how to implement a software interrupt using a timer. NOTE: In this program I chose Timer 1 which is a two register timer. This allows for longer cycles between interrupts. There are multiple timer modules in the PIC16f648a and each have special purposes for handling different tasks. I suggest you read up on all the timers and their capabilities prior to implementing one into your own program.

What you can expect to learn in this tutorial:
Get a basic understanding of a PIC interrupt and how it can be implemented.
Learn how to setup and use a timer to cause an interrupt.
Learn how to save and restore data in the working and status registers.

What you will need:
The same as in Brad's tutorial 2 (LED Flasher).
The .asm file:
http://www.bradsprojects.com/phpBB2/upl ... ky_482.zip

The Circuit:
Follow the instructions for connecting your LED and resistor exactly as you would in Brad's tutorial 2 (LED Flasher) with one exception – the end of the resistor that connects to PORTB pin 0, will be connected to PORTA pin 1 (pin 18 of the PIC16f648a). Sorry, I started this tutorial and made the pictures before I realized that I could have just used the same port pin as Brad. DUH!

Understanding how an interrupt and the timer work:
If you are doing something in your house and the phone rings, or “interrupts” you, you stop what you are doing to answer the phone, then at the end of the phone conversation you return to what you were doing. An interrupt using a PIC is exactly that.
PIC's have multiple interrupt sources (timers, input pins, comparators, etc.). It doesn't matter what causes the interrupt but more-so how to handle an interrupt once it occurs. That is completely up to the programmer.
The Program Counter (PC - the thing that keeps track of which line of code is next in the program) automatically jumps to address “0x04” when any interrupt occurs. This program uses timer 1 (TMR1) to cause that interrupt. I recommend reading about the TMR1 module starting on page 50 of the PIC16f648a datasheet AFTER completing this tutorial. There is a lot to understand about timers and how they work. One purpose of this tutorial is to cut through much of that so when you read the datasheet you will already have a basic understanding of what is going on.

The Program:
Lines 1-24 in the picture below are really no different than in the original LED flasher except we only need two variables. A temporary status register, and a temporary working register. Anytime an interrupt is used it is a good idea to store the current values in both the status and working registers so when you return from the interrupt, everything is the same as before the interrupt.

Image

Lines 25-61 contain the interrupt routine but I will skip over that and explain the setup routine first.

Lines 62-95 in the picture below show the setup. The TMR1 enable bit (PIE1, 0) must be set in BANK 1. PIE stands for “Peripheral Interrupt Enable” which is a register that contains various interrupt enable bits. On lines 81 & 82 you will notice INTCON which is the interrupt “control” register. This can be found on page 24 of the PIC16f648a datasheet. Bit 7 is the “global” interrupt enable and bit 6 is the “peripheral” interrupt enable. Both of these must be set for TMR1 to cause an interrupt.
Line 83 clears the timer 1 interrupt overflow flag so the timer will be able to cause an interrupt. Any flag that causes an interrupt must be cleared in software (by the programmer), otherwise it will stay set and never trigger an interrupt. It is good practice to clear flags such as this before the program begins. The timer 1 interrupt overflow flag (TMR1IF) is located in the PIR1 (Peripheral Interrupt Register 1) register - “bit 0”. The PIR1 register contains several interrupt flags and is explained on page 26 of the PIC16f648a datasheet.

Image

Lines 88-92 set the appropriate bits in the TMR1 control register (T1CON). This is explained on page 50 in the PIC16f648a datasheet. This is where it can get a little confusing because the timer can be adjusted to count every clock cycle as well as the second, fourth, or eighth cycle. There are also multiple clock sources that can be used to make the timer count. This is beyond the scope of this tutorial so I will suggest that you read through the comments of the program while referencing the datasheet and hopefully I have explained it well enough to understand what is happening in the code.
You will notice I did not do anything with bits 2,6, & 7. That should be self explanatory after looking through the datasheet.

Lines 97-127 in the picture below show the main program and the subroutine that turns on and off the LED. The main program does absolutely nothing! It is an infinite loop and simply waits for the timer to reach 0 where it will trigger the interrupt.
The LED routine simply checks the status of a bit. If it is set, it clears it, if it is clear it sets it (in this case - PORTA, bit 1).

Image

Now then, let's get to the core of this tutorial... THE INTERRUPT!
Lines 25-61... You will notice this program has an additional “org” directive (org h'04'). This tells the PC that this is where we want to jump to when an interrupt occurs (remember the PC jumps to address 0x004 upon any interrupt). I could have simply added three “NOP” instructions following the “goto setup” as follows to achieve the same result:

Code: Select all

	org  h'0000”
		
	goto setup
	nop
	nop
	nop

	“begin interrupt here”
	.
	.
	.
	“return from interrupt”
Image

As noted earlier, it is necessary to preserve the data within the working and status registers upon handling an interrupt. The comments withing the program explain this a little, however it is best to read about handling this in the PIC16f648a datasheet on page 111 section 14.6. Lines 35-38 handle the preservation of this data. Line 41 simply calls the LED subroutine to turn on or off the LED. I could have placed this code within the interrupt but I thought it would be useful to leave it in a separate routine and show how you can jump in and out of the interrupt just as you do any other routine. However, make note that it would not be good to use a GOTO instruction that makes the PC jump outside the interrupt or you will never return from the interrupt.
Lines 44-47 reload the TMR1 high and low registers with the values needed to retrigger the interrupt, and line 50 resets the TMR1 interrupt overflow flag (remember this has to be reset by the programmer). Lines 54-57 simply restores the working and status registers original data, and line 59 tells the PC to return to the place it was before the interrupt occurred.

Well that's it... an “over-explanation” of a very simple program! I hope I wasn't too confusing and that it is beneficial to someone who is interested in knowing how an interrupt can be used. Below is a picture and link to a great little program that will help with calculating timer values so you don't need to rack your brain trying to calculate prescaler settings, etc. Just select which timer you want to use, pick a frequency or time you would like to use for the interrupt cycle and BAM, it's done.

Image

(You can download the fullsize image here)
http://www.bradsprojects.com/phpBB2/upl ... or_155.gif

http://pictimer.picbingo.com/

Enjoy, and please feel free to comment or ask questions if I wasn't clear enough!

Stacy

PS> Play around with the values that are loaded in the TMR1 high and low registers and watch how the LED blinks faster / slower. Also, experiment with the picbingo timer calculator to set the frequency of the flash times. The values I have chosen will create a 500ms interrupt cycle (the LED will stay on for 500ms then turn off for 500ms).
Attachments
pic_timer_calculator.jpg
pic_timer_calculator.jpg (74.42 KiB) Viewed 25502 times
interrupt_blinky.zip
(2.61 KiB) Downloaded 782 times
List_Variables.gif
List_Variables.gif (8.23 KiB) Viewed 25514 times
Setup.gif
Setup.gif (16.52 KiB) Viewed 25514 times
Main_LED_routines_end.gif
Main_LED_routines_end.gif (15.77 KiB) Viewed 25514 times
PIC_Timer_Calculator.gif
PIC_Timer_Calculator.gif (44.36 KiB) Viewed 25514 times
Interrupt_Routine.gif
Interrupt_Routine.gif (16.75 KiB) Viewed 25514 times

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by brad » Sun May 30, 2010 8:35 am

That is a fantastic tutorial! Good job buddy :)

I would even like to upload this tutorial (one day...) to the tutorials section of the site since it is such an indepth tutorial.

Timers and Interupts are both features I have NEVER used!

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Sun May 30, 2010 10:59 am

brad wrote:That is a fantastic tutorial! Good job buddy :)

I would even like to upload this tutorial (one day...) to the tutorials section of the site since it is such an indepth tutorial.

Timers and Interupts are both features I have NEVER used!
Thanks.

Funny how something seems "different" than when I originally posted it. Hmmm... :roll:

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by brad » Sun May 30, 2010 10:01 pm

I don't know what you are talking about. Just because I have the power to do what ever I want in this little world of bradsprojects, doesn't mean that I will go around resizing images and providing links to the original.

Oh wait, I've said too much...

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Mon May 31, 2010 6:33 am

brad wrote:...blah, blah, blah...I have the power to do what ever I want in this little world of bradsprojects... blah, blah, blah...

Oh wait, I've said too much...
AH HA! So you're saying CHUCK did it! :wink:

maybe it was bitfogav?

User avatar
bitfogav
Moderator
Moderator
Posts: 915
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Tue Jun 01, 2010 12:39 am

HA! HA! Brads GOD on this little website :)

And thats a great tutorial matey!! :)

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Tue Jun 01, 2010 1:50 am

bitfogav wrote:...And thats a great tutorial matey!! :)
Thank you kindly mister.

I am hoping to expand it a little and show how to implement PWM. Or possibly how to handle multiple interrupts since any interrupt on the PIC16f648a will jump to the same address (0x0004).

Chuckt
I practically live here!
I practically live here!
Posts: 1127
Joined: Sun Mar 28, 2010 1:36 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by Chuckt » Tue Jun 01, 2010 2:24 pm

sdudley wrote:
brad wrote:...blah, blah, blah...I have the power to do what ever I want in this little world of bradsprojects... blah, blah, blah...

Oh wait, I've said too much...
AH HA! So you're saying CHUCK did it! :wink:

maybe it was bitfogav?
Are you talking about the pictures being cut off? It is probably in your best interests to protect your content because Amazon allows the selling of Wikipedia articles and things on the internet that aren't copyrighted are unethical to be copied but some people feel it is fair game:

http://www.neowin.net/news/amazoncom-al ... a-articles

http://scholarlykitchen.sspnet.org/2010 ... ublishing/

http://en.wikipedia.org/w/index.php?tit ... =Main+Page

I feel that people are already trolling the internet and copying other's work.

User avatar
bitfogav
Moderator
Moderator
Posts: 915
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Wed Jun 02, 2010 2:59 am

sdudley wrote:
bitfogav wrote:...And thats a great tutorial matey!! :)
Thank you kindly mister.

I am hoping to expand it a little and show how to implement PWM. Or possibly how to handle multiple interrupts since any interrupt on the PIC16f648a will jump to the same address (0x0004).

I was going to use an interrupt to refresh a 7 seg display on that eeprom project that I have posted on the forum, the thing is though, is that you have to turn interrupts off when you write data to eeprom, according to the datasheet I will only have to change a few lines in my souce code :)

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Wed Jun 02, 2010 3:57 am

bitfogav wrote:I was going to use an interrupt to refresh a 7 seg display on that eeprom project that I have posted on the forum, the thing is though, is that you have to turn interrupts off when you write data to eeprom, according to the datasheet I will only have to change a few lines in my souce code :)
If you are using the PIC16f648a you should simply need to add one line of code before the write and one line after:

Code: Select all

bcf  INTCON, 7   ;Disables all interrupts
.
call code to write to EEPROM
.
bsf  INTCON, 7  ;Re-enable interrupts
That should be all you need to do!

:)

User avatar
bitfogav
Moderator
Moderator
Posts: 915
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Wed Jun 02, 2010 4:00 am

Yeah I think your spot on!! :)

thanks

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Wed Jun 02, 2010 4:10 am

Correction...

I forgot the note on page 24 of the datasheet:
Note: Interrupt flag bits get set when an interrupt
condition occurs regardless of the state of
its corresponding enable bit or the global
enable bit, GIE (INTCON<7>).
So... you will need to add another line after the write so it would look more like this:

Code: Select all

bcf  INTCON, 7   ;Disables all interrupts 
. 
call code to write to EEPROM 
. 
bsf  INTCON, 7  ;Re-enable interrupts 
bcf  PIR1, 0    ;Reset TMR1 overflow flag
If you are using a different timer that last line would be different (i.e. TMR0 interrupt flag would read - bcf INTCON, 2)

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by brad » Thu Jun 03, 2010 5:57 am

Hmm, interesting!

You said that any interrupt will jump to the same address. How then do you distinguish between them?

User avatar
sdudley
Moderator
Moderator
Posts: 337
Joined: Sun Mar 28, 2010 1:33 pm
Location: Florida, U.S.A.
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by sdudley » Thu Jun 03, 2010 6:02 am

brad wrote:Hmm, interesting!

You said that any interrupt will jump to the same address. How then do you distinguish between them?
The programmer has to handle that by bit testing the interrupt flags.

Some PICs have multiple interrupts vectors...

On the 24-bit core devices (PIC24/dsPIC) there can be up to 118 interrupt vectors at 014h to 0FEh.
Last edited by sdudley on Thu Jun 03, 2010 6:19 am, edited 1 time in total.

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Post by brad » Thu Jun 03, 2010 6:05 am

But if I am understanding the post correctly (and I don't think that I am) you have multiple interupts and no matter which one of those is flagged, it just jumps to a certain location in program memory - is that right?

I would have thought that if say external interrupt 1 was flagged, then it would jump to a certain part of the program which would be different to it external interrupt 2 was flagged...

Post Reply
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Who is online

Users browsing this forum: No registered users and 12 guests