Interrupção periódica

Conhecimento necessário: [HW] Módulo de Interface do Utilizador, [AVR] Interrupções, [AVR] Contadores/Temporizadores,
[LIB] Pinos, [LIB] Temporizadores

Teoria

O objetivo deste capítulo é demonstrar o uso das interrupções no exemplo dos contadores. As interrupções são partes do programa que reagem aos eventos que têm lugar nos microcontroladores. São usadas normalmente ​​para uma resposta rápida a um evento, mas podem também ser usadas ​​para completar vários processos paralelos, acções precisas no tempo e de poupança energética. Por exemplo, é possível fazer um LED piscar com interrupções, de modo a que a freqüência do piscar não dependa do que acontece no programa em execução. Quando a interrupção ocorre a execução do programa principal pára e acontece a verificação da prioridade de interrupção na tabela de vectores de interrupção. Depois disso, dá-se então por concluída a função de interrupção. Depois da interrupção, o programa principal continua a partir do estado onde parou.

Prática

O programa seguinte mostra como o contador é configurado para fazer uma interrupção. Existem 2 LEDs do módulo de I/O digital no programa. O estado do LED vermelho é alterado periodicamente com uma espera por software; o estado do LED verde é alterado quando ocorrem interrupções. Existe um exercício separado para um LED piscar com espera por software que não é explicado aqui. O objetivo principal é explicar o uso da biblioteca dos contadores e interrupções.

O que se segue mostra o uso de interrupções do controlador xmega. No início do programa, o contador/temporizador de 16 bits E1 é configurado. Em primeiro lugar, o período do temporizador irá ser definido para o valor máximo da função de contagem TC_SetPeriod. O divisor do contador é de 1024 e o valor do período é de 31249, por isso, quando a frequência de relógio é de 32 MHz, o período será exatamente um segundo. Isto é fácil de calcular com seguinte fórmula:

period = (32000000 Hz / 1024 / 1) - 1 = 31249

Depois de permitir que a interrupção atinja o valor máximo do contador 1, uma interrupção deve ser permitida a nível global, o que significa ao longo de todo o microcontrolador. As interrupções globais podem ser ativadas por função sei e proíbidas com cli. Um ficheiro header avr/interrupt.h deve ser incluído na definição da parte do programa dessas funções e interrupções. A parte do programa da interrupção é definida com função macro ISR, cujo parâmetro é o nome do vetor de interrupção. Nesta configuração o valor máximo de interrupção atinjida do vetor do contador 1 é TCE1_OVF_vect. Além disso, para permitir a interrupção global, as prioridades de interrupção devem ser definidas uma a uma, usando o registo XMEGA PMIC.CTRL.

// HomeLab III example of blinking LED with counter interrupt
#include <homelab/pin.h>
#include <homelab/delay.h>
#include <homelab/timer.h>
#include <avr/interrupt.h>
 
// Interruption
ISR(TCE1_OVF_vect)
{
	// Changing the state of the green LED
	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) { }
}

Os exemplos de interrupção são bastante diferentes entre as séries de controladores ATmega (neste exemplo usamos o ATmega2561), porque os temporizadores, em comparação com os controladores da série XMEGA, também são diferentes.

No início do programa, o contador/temporizador de 16 bits 1 foi configurado com a função timer1_init_ctc. Com esta função se o contador CTC clear timer on compare match tiver sido definido para o modo em que o valor máximo do temporizador não é 216 - 1, mas pode ser selecionado. Neste caso, o valor máximo é fixado para ser igual ao valor do índice do ICR1. O divisor do contador é de 1024 e o valor da ICR1 é 14400, por isso, quando a freqüência de relógio é 14,7456 MHz, o período será exatamente um segundo. Isto é fácil de calcular com seguinte fórmula:

f = 14745600 Hz / 1024 / 14400 = 1

// 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
ISR(TIMER1_CAPT_vect)
{
	// Changing the state of the green LED
	pin_toggle(led_green);
}
 
// Main program
int main(void)
{
	// Setting the pins of the LEDs as outputs
	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 (1){ }
}

No início do programa confirma-se que, independentemente do que o microcontrolador está a executar no programa principal, as interrupções ocorrem e o LED verde pisca.

pt/examples/timer/periodic_interrupt.txt · Last modified: 2020/07/20 09:00 by 127.0.0.1
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0