====== Interruption périodique ====== //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]]// //Connaissances nécessaires: [HW] [[fr:hardware:homelab:controller]], [HW] [[fr:hardware:homelab:digi]], [AVR] [[fr:avr:interrupts]], [AVR] [[fr:avr:timers]], [LIB] [[fr:software:homelab:library:pin]], [LIB] [[fr:software:homelab:library:delay]], [LIB] [[fr:software:homelab:library:timer]], [PRT] [[fr:examples:timer:software_delay]]// ===== Théorie ===== Le but de ces exercices pratique est de montrer l'utilisation des interruptions à travers l'utilisation d'un compteur. Les interruptions sont des parties de programme qui réagissent aux évènements du micro-contrôleur. Ils sont habituellement utilisés pour répondre rapidement à un évènement, mais ils peuvent aussi être utilisés pour réaliser des fonctions en parallèle, pour réaliser une action à un moment précis et pour économiser de l'énergie. Par exemple, il est possible de faire clignoter une LED en utilisant des interruptions, la fréquence de clignotement ne dépend donc pas de ce qui se passe au même moment dans le programme principal. ===== Pratique ===== Le programme suivant montre comment initialiser un compteur pour utiliser une interruption. On utilisera deux LEDs du module numérique dans le programme, l'état de la LED rouge est inversé périodiquement avec une temporisation matérielle, quant à la LED verte son état est inversé en utilisant une interruption. Il existe un autre exercice concernant l'utilisation de la temporisation, nous n'en parlerons donc pas ici. L'objectif principal est d'expliquer l'utilisation de la librairie des compteurs et interruptions. Au départ, le compteur 16-bits est initialisé grâce à la fonction ''timer1_init_ctc''. Avec cette fonction, le compteur CTC //clear timer on compare match// est initialisé dans le mode où la valeur maximale n'est pas 216 – 1 mais peut être sélectionnée. Dans ce cas la valeur maximale est égale à la valeur de l'index ICR1. Le diviseur du compteur est de 1024 et la valeur de ICR1 est 14400, donc quand la fréquence de l'horloge est de 14,7456 MHz, la période est égale à une seconde. Il est facile de la calculer avec la formule suivante: f = 14745600 Hz / 1024 / 14400 = 1 After allowing the interrupt to achieve the maximum value of the counter 1, an interrupt must be allowed also at the global level, that means in the microcontroller. For allowing global interrupts, there is a function //sei// and for forbidding //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 //TIMER1_CAPT_vect//. // // 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 #include #include #include // // Determining the pins of the LED-s. // pin led_red = PIN(C, 5); pin led_green = PIN(C, 3); // // Interruption // ISR(TIMER1_CAPT_vect) { // Changing the state of the green LED. pin_toggle(led_green); } // // Main program. // int main(void) { // Seting the pins of the LED-s as outputs. pin_setup_output(led_red); pin_setup_output(led_green); // Seting the timer up in the CTC mode. timer1_init_ctc( TIMER1_PRESCALE_1024, TIMER1_CTC_TOP_ICR); // The maximal value of the timer is 14400, which // makes the length of the period 1 s. // Formula: 14,7456Mhz / 1024 = 14400 timer1_set_input_capture_value(14400); // Allowing interruption of achieving the value. timer1_input_capture_interrupt_enable(true); // Allowing global interruption. sei(); // Endless loop. while (true) { // Software delay 1000 ms. sw_delay_ms(1000); // Change of the state of the red LED. pin_toggle(led_red); } } 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 important aspect occurs, that was not so easily noticeable during software delay exercise. Although the delay in red LED blinking is 1000 ms, the actual time for completing the full cycle is a little bit longer. This 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. As a result the blinking of the red LED is always behind from the blinking of the green LED. This is why it is not advised to design clocks and other precise actions with delay but with interruptions of the counter.