Both sides previous revisionPrevious revisionNext revision | Previous revision |
en:examples:timer:periodic_interrupt [2010/03/04 17:29] – priitj | en:examples:timer:periodic_interrupt [2020/07/20 09:00] (current) – external edit 127.0.0.1 |
---|
====== Periodic interrupt ====== | ====== Periodic interrupt ====== |
| |
//Necessary knowledge: [HW] [[en:hardware:homelab:controller]], [HW] [[en:hardware:homelab:digi]], [AVR] [[en:avr:interrupts]], [AVR] [[en:avr:timers]], [LIB] [[en:software:homelab:library:pin]], [LIB] [[en:software:homelab:library:delay]], [LIB] [[en:software:homelab:library:timer]], [PRT] [[en:examples:timer:software_delay]]// | //Necessary knowledge: |
| [HW] [[en:hardware:homelab:digi]], |
| [AVR] [[en:avr:interrupts]], [AVR] [[en:avr:timers]], \\ |
| [LIB] [[en:software:homelab:library:pin]], |
| [LIB] [[en:software:homelab:library:timer]]// |
| |
===== Theory ===== | ===== Theory ===== |
| |
The goal of these practical exercises is to demonstrate the usage of the interruptions on the example of the counters. The interrupts are program parts which are reacting on the events that occur in the microcontrollers. They are used usually for quick reacting to an event, but they can be used for completing several parallel processes, precisely timed action and saving power. For example, it is possible to make a LED blinking, which’s blinking frequency does not depend on what is happening in the program at the moment. | The goal of this chapter is to demonstrate the usage of the interrupts on the example of the counters. The interrupts are program parts which are reacting to the events taking place in the microcontrollers. They are usually used for quick response to an event, but they can also be used for completing several parallel processes, precisely timed action and saving power. For example, it is possible to make a LED blinking using interruptions, so that blinking frequency does not depend on what is happening in the program at the moment. When the interrupt occur then main program execution stopped and the interrupt priority check of the interrupt vector table happen, after that the program of the interrupt function has been executed. While the interrupt program will be executed then the main program execution continues on the state where it left off. |
| |
===== Practice ===== | ===== Practice ===== |
| |
The following program shows how the counter is set up to make a interrupt. There are used 2 LED-s of the digital module in the program, the state of the red one’s is changed periodically with software delay. The green one’s state is changed when interrupts occur. There is a separate exercise about blinking LED with software delay and this is not explained here. The main goal is to explain the usage of the library of the counters and interrupts. | The following program shows how the counter is set up to make an interrupt. There are 2 LEDs of the Digital i/o module in the program, the state of the red LED is changed periodically with software delay, the state of the green LED is changed when interrupts occur. There is a separate exercise for blinking LED with software delay and it is not explained here. The main goal is to explain the usage of the library of the counters and interrupts. |
| |
In the beginning of the program, the 16-bit counter/timer 1 is been set up with the function //timer1_init_ctc//. With this function the counter CTC //clear timer on compare match// is been set to the mode where the maximum value of the timer is not 216 – 1 but elective. In the present case the maximal value is set the value of the ICR1 index. The divider of the counter is 1024 and the value of ICR1 is 14400, so when the clock frequency is 14,7456 MHz, the period will be exactly one second. It is easy to calculate: | The following shows the use of interrupts of the xmega controller. In the beginning of the program, the 16-bit counter/timer E1 has been set up. First, the timer period will be set, so the maximum value of the count function TC_SetPeriod. The divider of the counter is 1024 and the value of period is 31249, so when the clock frequency is 32 MHz, the period will be exactly one second. It is easy to calculate with following formula: |
| |
f = 14745600 Hz / 1024 / 14400 = 1 | period = (32000000 Hz / 1024 / 1) - 1 = 31249 |
| |
After allowing the interrupt to achieve the maximum value of the counter 1, allowing to make interrupt must be done at the global level also, that means in the microcontroller. For allowing global interrupts, there is the function //sei// and for forbidding function //cli//. For defining the program part of these functions and interrupts, there must be also a header file //avr/interrupt.h// included. The program part of the interrupt is defined with macro function ISR, which’s parameter is the name of the interrupt vector. The name of the vector of counter 1’s value achievement’s interrupt is //TIMER1_CAPT_vect//. | |
| |
| After allowing the interrupt to achieve the maximum value of the counter 1, an interrupt must be allowed at the global level, which means over the entire microcontroller. The global interrupts can be enabled by function sei and forbidding with cli. A header file avr/interrupt.h must be included for defining the program part of these functions and interrupts. The program part of the interrupt is defined with macro function ISR, which parameter is the name of the interrupt vector. In this set-up the vector of counter 1’s maximum value achievement interrupt is TCE1_OVF_vect. In addition, to allow the global interrupt, a different priority interrupts should be enabled one by one, using the xmega PMIC.CTRL register. |
| |
<code c> | <code c> |
// | // HomeLab III example of blinking LED with counter interrupt |
// The Homelab's example of blinking LED which blinks due to counter interruptings. | |
// For comparison to the LED blinking due to interrupts, | |
// there is a software delay blinking LED working parallel. | |
// | |
#include <homelab/pin.h> | #include <homelab/pin.h> |
#include <homelab/delay.h> | #include <homelab/delay.h> |
#include <avr/interrupt.h> | #include <avr/interrupt.h> |
| |
// | // Interruption |
// Determining the pins of the LED-s. | ISR(TCE1_OVF_vect) |
// | { |
pin led_red = PIN(C, 5); | // Changing the state of the green LED |
pin led_green = PIN(C, 3); | pin_toggle(led_green); |
| } |
| |
| // Main program |
| int main(void) |
| { |
| // Setting the pins of the LEDs as outputs |
| pin_setup_output(led_green); |
| |
| // Setting the period of timer E1 |
| // F_CPU/1024/[aeg] - 1 = periood |
| // 32000000 / 1024 / 1 - 1 = 31249 |
| TC_SetPeriod(&TCE1, 31249); |
| |
| // Setting the clock of timer E1 (F_CPU/1024) |
| TC1_ConfigClockSource(&TCE1, TC_CLKSEL_DIV1024_gc); |
| // Setting timer E1 to the normal operating mode |
| TC1_ConfigWGM(&TCE1, TC_WGMODE_NORMAL_gc); |
| |
| // Enabling high-priority overflow interruptions |
| TC1_SetOverflowIntLevel(&TCE1,TC_OVFINTLVL_HI_gc); |
| |
| // Enabling high-priority interruptions |
| PMIC.CTRL |= PMIC_HILVLEN_bm; |
| // Enabling global interruption |
| sei(); |
| |
| // Endless loop |
| while (1) { } |
| } |
| </code> |
| |
| |
| Example of interrupt is quite different between ATmega series (in this example ATmega2561) controllers, because the timers, compared to the xmega series controllers, are also different. |
| |
| In the beginning of the program, the 16-bit counter/timer 1 has been set up with the function //timer1_init_ctc//. With this function the counter CTC //clear timer on compare match// has been set to the mode where the maximum value of the timer is not 2<sup>16</sup> - 1 but can be selected. In this case the maximum value is set to equal the value of the ICR1 index. The divider of the counter is 1024 and the value of ICR1 is 14400, so when the clock frequency is 14,7456 MHz, the period will be exactly one second. It is easy to calculate with following formula: |
| |
| f = 14745600 Hz / 1024 / 14400 = 1 |
| |
| <code c> |
| // The HomeLab II example of blinking LED with counter interrupt |
| #include <homelab/pin.h> |
| #include <homelab/delay.h> |
| #include <homelab/timer.h> |
| #include <avr/interrupt.h> |
| |
// | |
// Interruption | // Interruption |
// | |
ISR(TIMER1_CAPT_vect) | ISR(TIMER1_CAPT_vect) |
{ | { |
// Changing the state of the green LED. | // Changing the state of the green LED |
pin_toggle(led_green); | pin_toggle(led_green); |
} | } |
| |
// | // Main program |
// Main program. | |
// | |
int main(void) | int main(void) |
{ | { |
// Seting the pins of the LED-s as outputs. | // Setting the pins of the LEDs as outputs |
pin_setup_output(led_red); | |
pin_setup_output(led_green); | pin_setup_output(led_green); |
| |
// Seting the timer up in the CTC mode. | // Seting the timer up in the CTC mode |
timer1_init_ctc( | timer1_init_ctc( |
TIMER1_PRESCALE_1024, | TIMER1_PRESCALE_1024, |
| |
// The maximal value of the timer is 14400, which | // The maximal value of the timer is 14400, which |
// makes the length of the period 1 s. | // makes the length of the period 1 s |
// Formula: 14,7456Mhz / 1024 = 14400 | // Formula: 14,7456Mhz / 1024 = 14400 |
timer1_set_input_capture_value(14400); | timer1_set_input_capture_value(14400); |
| |
// Allowing interruption of achieving the value. | // Allowing interruption of achieving the value |
timer1_input_capture_interrupt_enable(true); | timer1_input_capture_interrupt_enable(true); |
| |
// Allowing global interruption. | // Allowing global interruption |
sei(); | sei(); |
| |
// Endless loop. | // Endless loop |
while (true) | while (1){ } |
{ | |
// Software delay 1000 ms. | |
sw_delay_ms(1000); | |
| |
// Change of the state of the red LED. | |
pin_toggle(led_red); | |
} | |
} | } |
</code> | </code> |
| |
At the start of the program it can be seen that regardless of what the microcontroller is doing in the main program, the interrupts are happening and the green LED is blinking. | At the start of the program it is seen that regardless of what the microcontroller is doing in the main program, the interrupts are taking place and the green LED is blinking. |
| |
If we let the program to work for a couple of minutes, an aspect occurs that we just did not see during software delay exercise. Although in the cycle which blinks the red LED is the delay 1000 ms, the actual time for completing the full cycle is a little bit longer. It is because, the change of the LED’s state, callout of the function of the delay and completion of the cycle are demanding some clock cycles of time for the processor. That is the reason why it is not advised to design clocks and other precise actions with delay but with interruptions of the counter. | |