0% found this document useful (0 votes)
668 views

Bascom and AVR, Interrupts

This document discusses using interrupts in Bascom programs for the AVR microcontroller. It explains that interrupts allow a program to react to external events without pausing the main program loop. The document provides an example of using an interrupt on pin 2 to stop a blinking LED when a button is pressed. It then discusses issues with button bouncing and provides a solution using debouncing. Finally, it gives an overview of the different interrupt sources on the AT90S2313 microcontroller and best practices for writing interrupt routines.

Uploaded by

kondoritocl
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
668 views

Bascom and AVR, Interrupts

This document discusses using interrupts in Bascom programs for the AVR microcontroller. It explains that interrupts allow a program to react to external events without pausing the main program loop. The document provides an example of using an interrupt on pin 2 to stop a blinking LED when a button is pressed. It then discusses issues with button bouncing and provides a solution using debouncing. Finally, it gives an overview of the different interrupt sources on the AT90S2313 microcontroller and best practices for writing interrupt routines.

Uploaded by

kondoritocl
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Bascom and AVR, Interrupts

http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Bascom and AVR, Interrupts
Suppose you have a Bascom program that is in a Loop doing something complicated and time-consuming. You want to be
able to stop this task and switch the program to do someting else. The obvious hardware solution is to add a STOP button to
your AVR:
You would normally test if this button is pressed with the following program fragment:
. . .
Conf i g Pi nd. 2 as I nput
. . .
Do
. . .
. . . somet i ng compl i cat ed. . .
. . .
I f Pi nd. 2 = 0 Then
Lcd " St op! "
Got o Ot her t ask
End I f
Loop
. . .
Ot her Task:
. . .
The fundamental problem with this example is that we might spend so much time doing the complicated task that pressing the
STOP button will often not be noticed once the program arrives at the Pind.2 test. Obviously we need another mechanism to
react to pressing the STOP button in an independant way from the main program.
This is where interrupts are for. Interrupts are a to change the program flow to react to external as well as internal controller
events. We could modify the example above to:
interrupt-stopbutton.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nd. 2 = I nput
Conf i g I nt 0 = Fal l i ng
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Di mWt i me As Byt e
On I nt 0 St opbut t on
Cl s
Wt i me = 255
Enabl e I nt er r upt s
Enabl e I nt 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
St opbut t on:
Lcd " st op! "
Ret ur n
End
Pind.2 is configured as input, don't forget the 10k pull-up resistor!
Config Int0 Falling: Int0 is to happen only when the voltage level on Pind.2 is going from high to low.
When the Int0 interrupt occurs, the program will jump to the Stopbutton label.
Interrupts in general and the Int0 interrupt in particular are enabled.
In the Do Loop, the 'complicated task' is flashing a Led.
The Stopbutton routine will write "stop!" to the Lcd, then return to the program at the the point where is was interrupted.
What will happen is that the Led flashes on and off, most of the time will be spent in the Waitms commands. When the button
is pressed, the program will jump to the Stopbutton label and write "stop!" to the Lcd and return to flashing the Led.
Is that what happens? Alas, no. You will see "stop!" on the Lcd, but that is not all. Why? You will find out later, first an
overview of AT90S2313 interrupts:
The AT90S2313 interrupts
A. Interrupts with an external source:
Int0 external interrupt on PortD.2, pin 6
Int1 external interrupt on PortD.3, pin 7
Counter0 overflow interrupt, PortD.4, pin 8
Counter1 overflow interrupt, PortD.5, pin 9
Timer1 capture interrupt, PortD.5, pin 9
Timer1 output compare A interrupt, PortD.5, pin 9
Serial Rx complete interrupt
Analog comparator0 interrupt, PortB.0, pin 12
Analog comparator1 interrupt, PortB.1, pin 13
B. Interrupts with an internal source:
Timer0 overflow interrupt
Timer1 overflow interrupt
Serial data register empty interrupt
Serial Tx complete interrupt
AVR interrupts all have the same priority. This is different from a lot of other controller types where you can specify which
interrupts get priority over others.
If you use another type of AVR controller, use the Bascom *.def file to check which types of interrupts are available. Also
check the controller datasheet of course.
Interrupts on or off
If you start a Bascom program all interrupts are off. They have to be enabled. With the command:
Enabl e I nt er r upt s
interrupts are enabled as a group. They can be disabled as well:
Di sabl e I nt er r upt s
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
This can be useful if you have a program segment where you do want to be interrupted at all:
Enabl e I nt er r upt s
Enabl e I nt 0
Enabl e Ti mer 0
. . .
Di sabl e I nt er r upt s
. . .
Somet hi ng ver y i mpor t ant her e. . .
. . .
Ok, r eady. . .
. . .
Enabl e I nt er r upt s
. . .
Here, all interrupts are enabled or disabled as a group. Individual interrupts must be enabled separately:
Enabl e I nt er r upt s
Enabl e I nt 0
Enabl e RX0
Enabl e Count er 0
. . .
And they can be disabled individually:
. . .
Di sabl e Count er 0
. . . no count er 0 i nt er r upt s her e. . .
Enabl e Count er 0
. . .
Interrupt routines
Every interrupt has to be handled in a seperate routine. A routine is a program fragment with a label, program lines and a
Return statement. For every interrupt you enable, you must specifiy which routine it has to jump to:
On I nt 0 St opbut t on
On I nt 1 LcdMenu
On Count er 0 Revcal c
. . .
Enabl e I nt er r upt s
Enabl e I nt 0
Enabl e I nt 1
Enabl e Count er 0
. . .
Mai n pr ogr am
. . .
St opbut t on:
Lcd " st op! "
. . .
Ret ur n
LcdMenu:
Cl s
Lcd " Cal i br at e: pr ess A"
. . .
Ret ur n
Revcal c:
Revs = Count er 0 * Revf act or
Count er 0 = 0
. . .
Ret ur n
Note that all interrupt routines start with a label, a name ending with the ":" character.
No interrupts in an interrupt routine
As soon as the program is interrupted and jumps to the relevant interrupt routine, all enabled interrupts are disabled as long as
the routine is busy. Once the routine reaches the Return statement and jumps back to the place where it left the main program,
disabled interrupts are enabled again. This is to avoid routines from interrupting themselves and thus ending as the snake that
ate himself. This behaviour that differs from most other controller brands, is in the AVR architecture, not in Bascom.
Keep it short
Keep all your interrupts routines as short and simple as you can. Remember that your program is >interrupted< from what is
was doing and that it should probably not be interrupted for too long. Try to do not more in interrupt routines than keeping
track of counters or flags that are processed in the main program once the program is ready to do so.
Compare this program:
On I nt 0 St opbut t on
Enabl e I nt er r upt s
Enabl e I nt 0
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Do
. . .
Loop
End
St opbut t on:
Lcd " st op! "
. . .
Do somet hi ng compl i cat ed. . .
Ret ur n
with this program:
Di mSt opf l ag as Bi t
On I nt 0 St opbut t on
Enabl e I nt er r upt s
Enabl e I nt 0
Do
. . .
I f St opf l ag = 1 Then
Reset St opf l ag
. . .
Do somet hi ng compl i cat ed. . .
. . .
End I f
Loop
End
St opbut t on:
Set St opf l ag
Ret ur n
The Stopbutton routine is now kept to its minimum, only bit Stopflag is set. This is handled in the main program. Be aware
though, that in this way you may react later to an interrupt than desired.
More on Int0/Int1
Into and Int1 are external interrupts. They are typically generated by a pushbuttons, switches or pulses or level changes from
other circuits. You can select how these interrupts are honoured:
Conf i g I nt x = Low Level
Conf i g I nt x = Fal l i ng
Conf i g I nt x = Ri si ng
So, interrupts are generated as long as the Intx pin is low, for any level going high to low, or for any level going low to high.
Note that Low Level keeps generating interrupts for as long as the level is low. As an example:
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Di mCnt r As I nt eger
On I nt 0 But t on
Conf i g I nt 0 = Low Level
Cl s
Enabl e I nt er r upt s
Enabl e I nt 0
Do
Locat e 1 , 1
Lcd Cnt r
Wai t ms 250
Loop
But t on:
I ncr Cnt r
Ret ur n
End
In the interruptroutine a counter is incremented, the value of the counter is displayed four times per second on the Lcd.
Not documented in the Bascom help files (as far as I know) is the fact that Low Level seems to be the default for the Intx
configuration.
Generating interrupts on the Falling or Rising edge of an input pulse is much more common.
Bouncing buttons
A perfect pushbutton will switch directly from open to close and back to open when released. Alas, real world pushbuttons
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
have a phenomenon called 'bounce'. When pressed, a button may 'oscillate' between open a close for a short while before
settling in the closed position. The 'short while' may take as long as 50 milliseconds for some types. I made a 'snaphot' of a
button being pushed, pulling Vcc low through a 10k pull-up:
Actually this is a very good pushbutton: it takes only 0.5 milliseconds for the button to settle in the closed position.
Now, if your program would react to every falling edge, you would have to handle a lot of interrupts. The better approach is
to use 'debouncing'. What we could do is simply add a wait in the interrupt routine:
interrupt-debounce-self.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nd. 2 = I nput
Conf i g I nt 0 = Fal l i ng
Conf i g Debounce = 50
Di mWt i me As Byt e
Const Debouncet i me = 75
On I nt 0 St opbut t on
Cl s
Wt i me = 255
Enabl e I nt er r upt s
Enabl e I nt 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
St opbut t on:
Lcd " st op! "
Wai t ms Debouncet i me
Gi f r = 64
Ret ur n
End
In the interrupt routine a simple wait is added. In the routine, interrupts are disabled, so the program will only react once to
the button being pressed. Choose the value of Debouncetime so that is longer than the longest 'bounce' time of the pushbuttons
you use.
Bascom also has a Debounce command which you can use in the interrupt routine.
What is this strange Gifr?
In the example above, the interrupt routine has a strange command: Gifr = 64. What is its purpose? Remove this command
and see what happens: Almost always the text "stop!" is written twice on the Lcd. How is that possible?
Examine this program:
interrupt-deb-pre.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nd. 2 = I nput
Conf i g I nt 0 = Fal l i ng
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Di mWt i me As Byt e
On I nt 0 St opbut t on
Cl s
Set Por t d. 6
Wai t ms 3000
Reset Por t d. 6
Wt i me = 255
Enabl e I nt er r upt s
Enabl e I nt 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
St opbut t on:
Lcd " st op! "
Wai t ms 75
Ret ur n
End
After the Lcd is cleared, the Led is switched on. A 3 second wait follows, the Led is switched off, and the interrupts are
enabled. Now, reset the controller and try to press the stop button during the time the Led is on. You have three seconds to do
that, so that should be no problem. After the Led is off, Int0 is enabled and you will observe that immediately the program
jumps to the Stopbutton routine. So, even if you press the button >before<the interrupt is enabled, the interrupt is apparently
stored somewhere and when interrupts are enabled, it is immediately processed.
And that is what happens in the AT90S2313 controller (and in all the other AVR's). Even if the relevant interrupt is not
enabled, the moment an Int0/Int1 interrupt occurs it is stored in the General Interrupt Flag Register. This is one of the rare
moments where even Bascom users have to delve into the inner architecture of the AVR's. The Gifr register has eight bits
where bits six and seven are reserved for Int0 and Int1 respectively:
And this is also what happens in our interrupt-debounce-self.bas program. In the interrupt routine, when interrupts are
disabled, new interrupts arrive due to button 'bounce'. The interrupts are flagged as zero bit in the Gifr register. Int0 interrupts
in bit six, Int1 in bit seven. All we have to do to solve the problem is 'set' the relevant bit in the Gifr register just before the
Return statement in the interrupt routine. In this way, if the program resumes its normal course, no further (old) interrupts are
honoured.
Reserved register names
We now notice, that apparently there are a number of 'special' register names. Avoid using these names in your Bascom
programs. Consult the Bascom help (start Bascom help, choose find and type 'AVR internal registers') and the AT90S2313
datasheet (table 1, page 15 and 16)>
Reading a rotary encoder or keyboard on interrupt
Rotary encoders and small keyboards are typically read on interrupt. This is described separately in the encoder and keyboard
chapters.
Timers and Counters
The AT90S2313 has two timer/counters (make sure you read from page 27 onwards). Timer0 is an eight-bit timer/counter.
We can use it to measure time (by counting clock pulses) or to count external events on the T0 pin. As it is an eight-bit
timer/counter, the value can be from 0 to 255.
With Config we can choose from all the possibilities:
Conf i g Ti mer 0 = Ti mer , Pr escal e = 1| 8| 64| 256| 1024
Here, Timer0 is configured as timer with the controllerclock as input. It counts the clock pulses as they are output by a
prescaler with a division ratio of 1, 8, 64, 256 or 1024. With the division ratio you can controller the time it takes for Timer0
to go from 0 to 255 counts. Let us assume a 4MHz clock and a prescale ratio of 1024. Timer0 will be incremented every
Prescaler-ratio/Fclock or 1024/4.000.000 = 0.256 milliseconds. It will overflow in 255 * 0.256 = 65 milliseconds.
Timer1 is identical to Timer0 but it as it is a 16-bit counter it can count to 65535 before overflowing to zero.
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Timer0 and Timer1 start running as soon as they are configured.
An example of a free-running Timer0: (you only need an Lcd attached to the AT90S2313)
interrupt-timer0-free.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nb. 1 = Out put
Conf i g Ti mer 0 = Ti mer , Pr escal e = 1024
Di mWt i me As Byt e
Di mTi mer count er As Byt e
Wt i me = 100
Ti mer count er = 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Cl s
Ti mer count er = Ti mer 0
Lcd " t mr cnt r : " ; Ti mer count er
Loop
End
And a free running Timer1:
interrupt-timer1-free.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nb. 1 = Out put
Conf i g Ti mer 1 = Ti mer , Pr escal e = 1024
Di mWt i me As Byt e
Di mTi mer count er As Wor d
Wt i me = 100
Ti mer count er = 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Cl s
Ti mer count er = Ti mer 1
Lcd " t mr cnt r : " ; Ti mer count er
Loop
End
Of course the main difference is that here Timercounter is dimensioned as Word.
The actual value of Timer0 and Timer1 can be read at any time and copied into a properly dimansioned variable.
The two examples above used free-running timers. They can be started and stopped at any time:
St ar t Ti mer 0
St op Ti mer 0
St ar t Ti mer 1
St op Ti mer 1
And as these are just normal AVR registers, you can not only read the current value but also write a value into the registers.:
St op Ti mer 1
. . .
Ti mer 1 = 132
. . .
St ar t Ti mer 1
Timer interrupts
One of the more common applications of timers is to interrupt the program at regular intervals to do something else. For
example checking if an input pin has changed level, generate an output pulse etc.
An example for generating output pulses: (use the stopbutton schematic, monitor output on pin Portb.1)
interrupt-timer0-pulse.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Conf i g Pi nb. 1 = Out put
Conf i g Ti mer 0 = Ti mer , Pr escal e = 64
Di mWt i me As Byt e
On Ti mer 0 Pul se:
Wt i me = 100
Enabl e I nt er r upt s
Enabl e Ti mer 0
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
Pul se:
Toggl e Por t b. 1
Ret ur n
End
The prescaler ratio is set at 64, so Timer0 will be incremented every 16 microseconds. As it can count to 255, it will overflow after 256 * 16 =4096
microseconds. At every overflow, a Timer0 interrupt occurs and Pulse: is called. In the interrupt routine the state of Portb.1 is 'toggled', meaning that if it
was high, it is made low and v.v.
The result is a nice square wave with an on and off time of app. 4 milliseconds on Portb.1:
The AT90S2313 is pretty fast! Try a prescale value of 1 and observe the result on Portb.1. The on and off time is app. 60
microseconds:
All this is working fine as long as the time spent in the interrupt routine is smaller than the on/off time of the output! Try this
out by inserting an Cls command in the interrupt routine. You will see that the on/off time jumps from 60 microseconds to 6
milliseconds!
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Other timings
In the examples shown thus far, the interrupt was generated on a timer overflow. This means that the timings we can realise
are limited to certain number dependant on clock speed, prescaler ratio and timer register width. One way of choosing exact
timings is to not let the timer run free from zero to maximum to zero etc., but to preload the timer register after every
overflow with a certain value. We can choose this value such that the time it takes to get from this value to overflow is
exactly the time we need:
interrupt-timer1-preload.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Pi nb. 1 = Out put
Conf i g Ti mer 1 = Ti mer , Pr escal e = 1
Const Ti mer 1pr e = 65100
Di mWt i me As Byt e
St op Ti mer 1
Ti mer 1 = Ti mer 1pr e
On Ti mer 1 Pul se:
St ar t Ti mer 1
Wt i me = 100
Enabl e I nt er r upt s
Enabl e Ti mer 1
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
Pul se:
St op Ti mer 1
Ti mer 1 = Ti mer 1pr e
Toggl e Por t b. 1
St ar t Ti mer 1
Ret ur n
End
Timer1 is loaded with the value 65100 after every overflow. Timer1 will thus count from 65100 to 65535 before overflowing
and generating an interrupt. This will take (65536 - 65100) * 0.25 = 109 microseconds. Using the constant Timer1pre you can
time the on/off time of the output pulse exactly in 0.25 microsecond resolution.
Counting external pulses
Timer0 and Timer1 can be configured to count external pulses on the T0 and T1 input pins:
Conf i g Ti mer 0 = Count er , Pr escal e = 1| 8| 64| 256| 1024, Edge = Ri si ng| Fal l i ng
Conf i g Ti mer 1 = Count er , Pr escal e = 1| 8| 64| 256| 1024, Edge = Ri si ng| Fal l i ng
You can choose to count pulses on the falling or rising edge of an input pulse. You can also choose to have the input pulses
prescaled before counting.
Especially Timer1 is interesting to act as external pulse counter as it can count to 65535 before overflowing.
The names Timerx, Counterx and Capturex in Bascom programs all refer to the same registers, so for example the names
Timer1 and Counter1 can be mixed in a program, although that would not be good programming practice.
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Note that when Timer0 and Timer1 are used to count external pulses, the controller will sample the input the level on the
input pin at the controller clock rate. This means that to accurately count input pulses, the pulse frequency must never be
higher than half the controller clock frequency. (Nyquist) To be on the safe side, keep the input pulse frequency below 40% of
the controller clock. So, for a clock of 4MHz, do not try to count faster than 1.6MHz.
Try this out with a TTL pulse generator attached to T1 (PortD.5, pin 9 of the AT90S2313):
counter1.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Ti mer 1 = Count er , Edge = Fal l i ng , Pr escal e = 1
St op Count er 1
Set Por t d. 6
Wai t ms 1000
Reset Por t d. 6
Wai t ms 1000
Cl s
Do
Count er 1 = 0
St ar t Count er 1
Wai t ms 25
St op Count er 1
Cl s
Lcd " Count er 1: " ; Count er 1
Wai t ms 100
Loop
End
In the Do Loop, Counter1 is cleared and started. After a 25 millisecond wait, Counter1 is stopped and its value is written to the Lcd. Note that timing with a
Waitms command is not very accurate, there are better ways.
Slowly increase the pulse generator frequency and observe what happens above 1.6MHz.
Timer1 can count to 65535. If that is not enough, you can generate an interrupt on Timer1 overflow and keep track of the
number of overflows in an interrupt routine:
counter2.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Ti mer 1 = Count er , Edge = Fal l i ng , Pr escal e = 1
Di mWt i me As Byt e
Di mTi mer count er As Wor d
Di mOver f l count er As Wor d
Di mTot al count er As Long
On Count er 1 Uphi gh
Wt i me = 100
Ti mer count er = 0
Tot al count er = 0
Enabl e I nt er r upt s
Enabl e Count er 1
Do
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Cl s
Ti mer count er = Count er 1
Lcd Ti mer count er ; " " ; Over f l count er
Lower l i ne
Tot al count er = Over f l count er
Shi f t Tot al count er , Lef t , 16
Tot al count er = Tot al count er + Ti mer count er
Lcd " t ot al : " ; Tot al count er
Loop
Uphi gh:
I ncr Over f l count er
Ret ur n
End
Three variables are dimensioned:
Overflowcounter (16-bit Word) keeps track of the number of Timer1 overflows
Timercounter (16-bit Word) has the actual value of Timer1
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Totalcounter (32-bit Long) gets the value of Overflowcounter shifted 16 places to the left plus the value of Timercounter.
Timer1 Capture
Timer1 can be configured in the 'Capture' mode. This means that Timer1 counts the controller clock through a prescaler, and
when on the ICP input (PortD.6, pin 11) a pulse arrives, the contents of the Timer1 register is copied to the input capture
register. In this way it is possible to measure the time between two pulse edges exactly:
Conf i g Ti mer 1 - Ti mer , Pr escal e = 1| 8| 64| 256| 1024, Capt ur e Edge = Ri si ng| Fal l i ng
interrupt-timer1-capture.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
' Conf i g Pi nd. 6 = Out put
Conf i g Ti mer 1 = Ti mer , Pr escal e = 64 , Capt ur e Edge = Ri si ng
Di mWt i me As Byt e
Di mTi mer count er As Wor d
On Capt ur e1 Capt mr
Wt i me = 100
Ti mer count er = 0
Enabl e I nt er r upt s
Enabl e Capt ur e1
Do
' Set Por t d. 6
Wai t ms Wt i me
' Reset Por t d. 6
Wai t ms Wt i me
Cl s
Lcd " pwi dt h: " ; " " ; Capt ur e1
Loop
Capt mr :
Ti mer count er = Capt ur e1
Ti mer 1 = 0
Ret ur n
End
In the interrupt routine the value of Timer1 (Capture1 is just another name for this register) is copied to Timercounter. Timer1 is then reset. The next time
that a pulse on the ICP input arrives the same happens. So, Timercounter is a measure of the time between pulses on ICP.
Timer1 Compare
Timer1 has a compare register: CompareA. (Bascom also mentiones CompareB, but that register is not in the AT90S2313)
This register can be loaded with a certain value. When the Timer1 value equals that of CompareA, a previously defined action
can be performed on OC1. (PortB.3, pin 15):
Conf i g Ti mer 1 = Ti mer , Pr escal e = 1| 8| 64| 256| 1024, Compar e A = Cl ear | Set | Toggl e| Di sconnect , Cl ear Ti mer
= 0| 1
Actions are:
- Set OC1
- Clear OC1
- Toggle OC1
- Disconnect OC1
With Clear Timer you can reset Timer1 when the CompareA occurs.
Especially the toggle function is much used to generate precise frequencies on OC1.
compare.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
Conf i g Pi nd. 6 = Out put
Conf i g Ti mer 1 = Ti mer , Pr escal e = 1 , Compar e A = Toggl e , Cl ear Ti mer = 1
Di mWt i me As Byt e
Di mCompval As Wor d
Wt i me = 100
Do
For Compval = 100 To 10000 St ep 100
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
Compar e1a = Compval
Wai t ms 10
Next Compval
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
End
In the Do Loop, the Compare1A register is preloaded with Compval, which varies between 100 and 10000. When Timer1 equals Compare1A, the pin OC1
is toggled and Timer1 is cleared.
Connect a small loudspeaker through a series resistor of several hundred ohm's to OC1 (PortB.3, pin 15) and listen to the
music...
UART interrupts
The AT90S2313 UART has three interrupt possibilities:
1. Tx ready. When the last Tx bit has been sent and no more data is in the data buffer. This interrupt can be used when
working half-duplex and you must know when to change from send to receive. In the default full-duplex mode this interrupts
has no use.
2. Tx data buffer empty. This interrupt is generated when a character is written from the data buffer to the Tx buffer. It can be
used to signal that the next character can be written in the data buffer. You will not often need this interrupt because Bascom
arranges everything when sending a string to the UART.
3. Rx ready. When a complete character has been received by the UART and has been placed in the data buffer this interrupt
is generated.This character has to be read from the data buffer as soon as possible so that the next character can be received.
Bascom also deals with receiving strings through the UART, but it can be useful to interrupt a program when a character
arrives, for example to change the course of the program:
interrupt-rs232rx.bas
$r egf i l e = " 2313def . dat "
$cr yst al = 4000000
$baud = 9600
Conf i g Pi nd. 6 = Out put
On Ur xc Get char
Di mWt i me As Wor d
Di mI nchar As St r i ng * 1
Const Fast bl i nk = 100
Const Sl owbl i nk = 500
Wt i me = Sl owbl i nk
Enabl e I nt er r upt s
Enabl e Ur xc
Do
Pr i nt Wt i me
Set Por t d. 6
Wai t ms Wt i me
Reset Por t d. 6
Wai t ms Wt i me
Loop
Get char :
I nchar = I nkey( )
Sel ect Case I nchar
Case " f " : Wt i me = Fast bl i nk
Case " s" : Wt i me = Sl owbl i nk
End Sel ect
Ret ur n
End
When a character is received, Getchar is called. If the character is a "f", in the Do Loop the Led will flash fast, if a "s" is received it will flash slowly. All
other characters are ingnored.
Analog Comparator
The AT90S2313 has an analog comparator on Ain0 (pin 12) and Ain1 (pin 13). The comparator can be configured such that
when it triggers, the Timer1 Capture function is started. It is also possible to generate an interrupt:
Conf i g ACI = On| Of f , Compar e = On| Of f , Tr i gger = Ri si ng| Fal l i ng| Toggl e
When Compare is configured On, the Timer1 Compare is started when the comparator triggers. With Trigger the trigger
moment can be set to rising (Ain0 > Ain1), falling (Ain0 < Ain1) or toggle (Ain0 > Ain1 and Ain0 < Ain1).
Bascom and AVR, Interrupts
http://www.qsl.net/p/pa3ckr/bascom%20and%20avr/interrupts/index.html[06-01-2014 17:03:26]
A possible application of the analog comparator is an eight-bit DAC, but then you need the complete PortB to construct a R-
2R DAC. This is rather wasteful, a better solution would be an outside chip such as the I
2
C PCF8591 which has one DAC
and four ADC's, all eight-bit.
TOC

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy