lar - Configuração da Internet
Interrupções no atmega8. Curso de treinamento

Uma das vantagens do microcontrolador ATmega8 é sua ampla gama de diferentes interrupções.

Interromperé um evento em cuja ocorrência a execução do programa principal é suspensa e é chamada uma função que trata uma interrupção de um determinado tipo.

As interrupções são divididas em internas e externas. As fontes de interrupções internas incluem módulos microcontroladores integrados (temporizadores, transceptor USART, etc.). As interrupções externas ocorrem quando sinais externos chegam aos pinos do microcontrolador (por exemplo, sinais nos pinos RESET e INT). A natureza dos sinais que levam à ocorrência de uma interrupção é definida no registrador de controle MCUCR, em especial nos bits - ISC00 (bit 0) e ISC01 (bit 1) para entrada INT 0; ISC10 (bit2) e ISC11 (bit3) para entrada INT1.

No microcontrolador ATmega8, cada interrupção possui seu próprio vetor de interrupção(endereço no início da área de memória do programa onde está armazenado o comando para saltar para a rotina de interrupção especificada). No mega8, todas as interrupções têm a mesma prioridade. Se ocorrerem várias interrupções simultaneamente, a interrupção com o número de vetor mais baixo será processada primeiro.

Vetores de interrupção em Atmega8

Endereço Fonte de interrupção Descrição
0x0000 REINICIAR Sinal de reinicialização
0x0001 INT0 Solicitação de interrupção externa na entrada INT0
0x0002 INT1 Solicitação de interrupção externa na entrada INT1
0x0003 T/C1 Captura temporizada T/C1
0x0004 T/C1 Corresponder T/C1 Temporizador Comparar Registro A
0x0005 T/C1 Combine com o registro de comparação B do temporizador T/C1
0x0006 T/C1 Estouro do contador T/C1
0x0007 T/C0 Estouro do contador T/C0
0x0008 IPS Transferência de dados SPI concluída
0x0009 UART O transceptor UART concluiu o recebimento de dados.
0x000A UART O registro de dados UART está vazio
0x000B UART A transmissão de dados pelo transceptor UART é concluída
0x000C ANA_COMP Interrupção do comparador analógico

Gerenciamento de interrupções

4 registros são responsáveis ​​por gerenciar interrupções no ATmega8:

GIMSK(também conhecido como GICR) - proíbe/habilita interrupções com base em sinais nas entradas INT0, INT1

GIFR- gerenciamento de todas as interrupções externas

TIMSK, TIFR- gestão de interrupções de temporizadores/contadores

Registro GIMSK(GICR)

INTFx=1: ocorreu uma interrupção na entrada INTx. Ao entrar na rotina de tratamento de interrupções, o INTFx é automaticamente redefinido para o estado de log. 0

Registro TIMSK

7 6 5 4 3 2 1 0
TOIE1
OCIE1A
OCIE1B
-
TICIE
-
TOIE0
-

TOIE1=1: Interrupção de overflow T/C1 habilitada

OCIE1A=1: interrompe quando o registro de comparação A corresponde ao conteúdo do contador T/C1 habilitado

OCIE1B=1: interrompe quando o registro de comparação B corresponde ao conteúdo do contador T/C1 habilitado

TICIE=1: interrupção habilitada quando a condição de captura for atendida

TOIE0=1: Interrupção de overflow T/C0 habilitada

Registro TIFR

7 6 5 4 3 2 1 0
TOV1
OCF1A
OCF1B
-
CIF1
-
TOV0
-

TOV1=1: Ocorreu estouro de T/C1

FCO1A=1: registro de comparação A coincidiu com o conteúdo do contador T/C1 permitido

FCO1B=1: registro de comparação B corresponde ao conteúdo do contador T/C1 permitido

CIF=1: condições de captura atendidas

TOV0=1: Ocorreu estouro de T/C0

Ao entrar na sub-rotina de tratamento de interrupções, o sinalizador de registro TIFR correspondente à interrupção é automaticamente redefinido para o estado de log. 0

As interrupções só funcionam quando as interrupções gerais estão habilitadas no registro de status SREG (bit 7 = 1). Quando ocorre uma interrupção, este bit é automaticamente redefinido para 0, desativando interrupções subsequentes.

Neste exemplo, o pino INT0 está habilitado no modo de entrada pull-up. Quando o pino é curto-circuitado com o aterramento por meio de um botão, a lógica 0 é colocada nele (a borda do sinal cai da tensão de alimentação para 0) e o manipulador de interrupção é acionado, acendendo a lâmpada conectada ao pino zero da porta B

lâmpada vaziaON()
{
PORTB.0=1;
DDRB.0=1;
}

interromper vazio ext_int0_isr(void)
{
lâmpadaON();
}

DDRD.2=0;
PORTD.2=1;

SREG|= (1 enquanto(1) (

O exemplo acima também mostra como os vetores de interrupção são definidos no Code Vision AVR (interrupt void ext_int0_isr(void)). Os vetores de interrupção são definidos de forma semelhante para outros casos:

EXT_INT02
EXT_INT13
TIM2_COMP4
TIM2_OVF5
TIM1_CAPT6
TIM1_COMPA7
TIM1_COMPB8
TIM1_OVF9
TIM0_OVF10
SPI_STC11
USART_RXC12
USART_DRE 13
USART_TXC14
ADC_INT15
EE_RDY 16
ANA_COMP17
TWI 18
SPM_READY 19

Em primeiro lugar, o que é uma interrupção?
Interrupção é um tipo de função que será executada quando um sinal chegar em alguma entrada do controlador.
Ao trabalhar no AVR Studio, as interrupções são criadas usando macros RIS() , SINAL() E INTERROMPER(). Eles marcam alguma função como manipulador de interrupções. A diferença deles é que INTERROMPER() E RIS() definir uma função de manipulador para o caso em que a interrupção geral está habilitada (o manipulador pode ser interrompido), e SINAL() para o caso em que a interrupção geral está desabilitada.

Com isso, vamos encerrar a teoria e passar à prática (embora haja mais teoria a seguir).
Vamos montar o seguinte diagrama no ISIS:

Como você provavelmente já adivinhou, escreveremos uma interrupção (gerada por um botão) que acenderá e desligará o diodo.
Então, abra o estúdio e crie um projeto padrão.
Para usar interrupções, inclua o arquivo de cabeçalho:

#incluir

Vamos concordar que a interrupção (fisicamente) não ligará ou desligará a alimentação da perna do controlador (como já considerei que isso é feito), mas apenas alterará o sinalizador. Em certos valores dos quais o diodo ligará e desligará.
Vamos definir este sinalizador globalmente:

Número interno = 1;

Agora vamos declarar uma interrupção:

ISR(SIG_INTERRUPT1)( if (num == 1) num = 0; senão num = 1; )

Como você pode ver, o chamado vetor de interrupção é indicado entre colchetes da macro. Este vetor informa ao compilador para qual entrada a interrupção será gerada. Para INT1 é SIG_INTERRUPT1. Para um ADC, por exemplo, é SIG_ADC. (a lista completa está perfeitamente descrita no livro “Shpak Yu.A. Programação em C para microcontroladores AVR e PIC.”)
Agora vamos passar para a função principal do nosso “programa”.
Precisamos habilitar interrupções em geral e para INT1 em particular:

Sei(); // em geral GIMSK |= (1<

Feito isso, você precisa configurar o comportamento da interrupção. Ele pode ser gerado de diferentes maneiras.
Baixe a ficha técnica (há um link ao criar o projeto) e encontre a seguinte tabela na seção de interrupção:

Acho que você entenderá como traduzir isso.
Vamos definir o estado de geração de interrupção para cada "mudança lógica para INT1".

MCUCR = (0<

Agora vamos definir toda a porta C como saída:

DDRC = 0xff; //porta C - saída

Bem, isso já deve estar claro:

While (1)( if (num == 1) PORTC |= 1; // liga a primeira saída C else PORTC &= ~1; // desliga a primeira saída C _delay_ms(100); // espera 100ms )

Não há necessidade de esperar. Além disso, isso reduz o desempenho. Mas eu quero assim.
Programa completo:

#define F_CPU 8000000UL // 8MHz #include #incluir #incluir int num = 1; ISR(SIG_INTERRUPT1)( if (num == 1) num = 0; else num = 1; ) int main (void)( sei(); GIMSK |= (1<

Compilamos hexadecimal e montamos o circuito no Proteus. Gostamos da função de interrupção ao alterar a posição do botão.

Muitas vezes acontece que um microcircuito deve funcionar, funcionar silenciosamente e, para algum evento, largar tudo e fazer outra coisa. E então - retorne à tarefa original novamente... É como um relógio, por exemplo - mostra a hora até chegar a hora do despertador. E parece que não há influências externas - apertar um botão, reiniciar - e o microcircuito muda sozinho.

Isso pode ser implementado por meio de interrupções - sinais que informam o processador sobre a ocorrência de um evento.

Aqui está um exemplo da vida cotidiana - você está sentado na cozinha, tomando chá com geléia de framboesa e guloseimas deliciosas, esperando pelos convidados. Como você sabe que alguém chegou? As opções são duas: ou fazemos uma pausa na geléia, quero dizer, no chá, a cada cinco minutos e corremos para ver se tem alguém na porta, ou compramos uma campainha e esperamos calmamente em local aquecido até que alguém toque.

Então, quando um convidado liga, isso é um evento. Conseqüentemente, paramos e corremos para a porta.

Então, o microcircuito tem interrupções. E não apenas um. As interrupções são divididas em externas - são acionadas em uma determinada tensão em alguns pinos do microcircuito (INT0, INT1 e às vezes também em toda a porta PCINT) - e internas - quando o contador transborda, o temporizador watchdog é acionado, ao usar USART, quando um comparador analógico, ADC e outros periféricos são interrompidos.

Assim, surge um problema prioritário. É como se ainda estivéssemos sentados tomando chá, mas eles não só tocassem a campainha, mas também ao telefone... E você não pode ficar despedaçado, algo precisa ser feito primeiro. Portanto, a folha de dados contém uma tabela de vetores de interrupção. Quanto menor o número de interrupção, maior prioridade ela terá.

Existem várias sutilezas aqui...

Ocorreu um evento - foi enviada uma solicitação de interrupção, ou seja, o chamado “sinalizador de solicitação de interrupção” está definido. Se tudo estiver bem, a interrupção for resolvida, então a vida é maravilhosa e se processa.

Mas se uma interrupção for desabilitada - por exemplo, uma interrupção de prioridade mais alta já está sendo processada - então esse sinalizador de solicitação permanecerá suspenso até que as interrupções sejam habilitadas. Depois disso, o chip verifica o registro da solicitação em ordem de prioridade e, se houver flag, processa-a.

MAS! Acontece que mesmo que a interrupção seja processada, não é fato que o evento que a causou ainda esteja vivo... É como se a campainha e o telefone tocassem ao mesmo tempo, você atendesse o telefone, e os convidados já decidiu que não havia ninguém em casa e foi embora. E parecia que havia um acontecimento - a campainha tocou, mas não havia ninguém atrás da porta.

Outro problema é que enquanto outra interrupção está sendo processada e o sinalizador de solicitação já foi levantado, o evento pode ocorrer várias vezes. Atendemos o telefonema, abrimos a porta - e já tinha um monte de convidados lá! Apavorante? Apavorante...

Outra característica do uso de interrupções – e não apenas interrupções: a reentrância (ou reentrada).

Um programa reentrante é aquele que pode ser chamado por vários usuários (ou processos) sem, no mínimo, causar um erro e, no máximo, sem desperdiçar computação – por exemplo, outro usuário não precisa executar o código novamente.

Ou seja, se na cozinha enquanto você cumprimenta os convidados ninguém rouba algumas guloseimas, então tudo é reentrante)

Em geral, é uma coisa séria - se você não levar isso em consideração, você pode sofrer por muito tempo com “por que não funciona?!” Precisa ser levado em consideração, por exemplo, se diversas interrupções forem processadas, e cada uma delas alterar alguma variável global...

As interrupções geralmente NÃO são reentrantes. Ou seja, no momento em que a interrupção está em execução, você não pode chamar a mesma interrupção novamente. É para proteger contra entradas repetidas no manipulador que as interrupções são automaticamente proibidas no momento de seu processamento (caso você queira habilitar interrupções na interrupção). procedimento de manuseio, você precisa pensar dez, vinte vezes antes de dar um passo tão precipitado).

Consideremos trabalhar com interrupções externas: precisamos, em primeiro lugar, configurar qual evento irá desencadear a interrupção e, em segundo lugar, permitir que o chip processe essa mesma interrupção.

O registro MCUCR é responsável pelos primeiros bits do chip ATmega8 - ISC11-ISC10, responsável por INT1, e ISC01-ISC00, responsável por INT0.

Tabela 1. Definição de eventos para geração de interrupção via INT1

Assim, o mesmo com INT0.

Agora só falta habilitar as interrupções no pino que precisamos - o registrador GIGR possui os bits INT0 e INT1; definido como “1” desejado - e a interrupção externa está habilitada! Mas é muito cedo para se alegrar - além das interrupções externas, as interrupções em geral devem ser habilitadas - defina o bit I mais à esquerda do registro SREG para “1”. O mesmo pode ser feito com o comando assembler: asm sei;

Vejamos um exemplo simples: um botão é anexado ao pino INT0 (D.2) do chip ATmega8 (ao pino e ao zero); pressione - ocorre uma interrupção e o LED no pino B.0 acende. O LED, respectivamente, está conectado à perna e à unidade:

//programa para ATmega8 ao pressionar um botão no pino INT0 (D.2) - conectado em 0 - //acende o LED no pino B.0 por interrupção externa - conectado em 1 //redefine tipos typedef unsigned char byte; sbit ddrButton em ddD2_bit; //botão de geração sbit pinButton at pinD2_bit; sbit portButton em portD2_bit; sbit ddrLight em ddB0_bit; //saída para o LED, para a saída pull-up, ligue 0 no botão sbit portLight em portB0_bit; byte flagButton = 0; //sinalizador de clique no botão; pressionado - 1 void INT0_interrupt() org IVT_ADDR_INT0 //você precisa escrever pelo menos uma função vazia - //porque o compilador não a cria sozinho. Caso contrário não funciona ( flagButton = 1; ) //processando o pressionamento do botão - levando em consideração o salto void buttonLight() ( if(flagButton) //se o botão for pressionado ( portLight = 0; //liga o LED delay_ms(500); portLight = 1; //desliga o LED flagButton = 0; ) ) void main() ( //inicializando todas as portas usadas ddrB = 0; portB = 0; ddrD = 0; portD = 0; // inicializando o botão - para a entrada com pull-up portButton = 1; //inicializa o LED, que é ligado por 0 e pressionando o botão - para saída e para 1 portLight = 1; interrupções externas MCUCR.ISC00 = 0; //a interrupção é gerada pelo 0 lógico em INT0 MCUCR.ISC01 = 0; //habilita a interrupção externa INT0 asm sei;//SREG.B7 = 1; interrompe em princípio (bit I os comandos são iguais a while(1) ( buttonLight() ; ) )

Um pouco sobre a sintaxe. A função de interrupção é escrita assim: void function_name() org IVT_ADDR_INT0.

A palavra-chave org indica que o endereço de interrupção da folha de dados virá em seguida. Temos o nome da interrupção da biblioteca: digitamos IVT e depois pressionamos Ctrl + Espaço (adoro essas coisas ˆˆ). Você também pode usar iv em vez da palavra org, a julgar pela ajuda do compilador.

Outra pequena observação: em primeiro lugar, a interrupção nunca deve ser incômoda - algumas linhas e pronto. Isso se deve ao fato de que durante o processamento de uma interrupção, o microcircuito não pode se distrair com mais nada, o que significa que se tivermos várias interrupções, podemos perder a ocorrência de algum evento.

Também pode acontecer que não precisemos de nenhum processamento de interrupção - por exemplo, basta que o circuito tenha saído do modo de hibernação. Mas neste caso, você ainda precisa escrever uma função de interrupção, mesmo que vazia - o chamado “stub”. Em princípio, alguns compiladores escrevem automaticamente funções vazias para cada interrupção, mas este não é o nosso caso - temos que fazer isso manualmente.

Hoje veremos o conceito de interrupção e como utilizá-lo. Naturalmente não dispensaremos um programa de treinamento, mas desta vez não piscaremos os LEDs. Já está bom. Vamos fazer algo parecido com uma campainha.

Tarefa: faça o microcontrolador emitir um bipe ao pressionar um botão.
Diagrama para nosso exemplo. Arquivos de projeto.

Criamos um projeto de anel no antigo espaço de trabalho.
Defina as configurações do projeto para a configuração Release:

Selecione o tipo de microcontrolador.
Opções Gerais > Destino > Configuração do processador
Eu tenho esse ATmega8535.

Permitir o uso de nomes de bits definidos no arquivo de cabeçalho
Em Opções Gerais > Sistema, marque a caixa Habilitar definições de bits em arquivos de E/S-Incluir
Ainda não usamos nomes de bits, mas hoje precisaremos deles.

Altere o tipo de arquivo de saída.
Vinculador > Saída.
No campo Arquivo de saída, marque a caixa Substituir padrão e substitua a extensão d90 por hexadecimal
No campo Formato, selecione Outro e no menu suspenso Formato de saída, selecione o tipo de arquivo intel-standart

Salve o projeto e o espaço de trabalho.

______________________________ Interromper ___________________________

Imagine a situação. Você está sentado no trabalho e debruçado sobre outro programa de microcontrolador. O chefe chega até você e diz: “Escute, Pash, compramos osciloscópios para o nosso departamento - Tektronix, quatro canais. Ajude Vasya a arrastá-los.” Você pensa: “Bem, que coisa, só o pensamento atrapalhou... e em você.” E o chefe olha para você assim, e seus olhos são tão gentis, tão gentis. Como você pode recusá-lo? Bom, você larga tudo e vai com um amigo comprar osciloscópios. Eles trouxeram isso. Nós relatamos. E eles voltaram ao programa. Esta é aproximadamente a aparência do mecanismo de interrupção.

Bastante simples, mas há vários pontos fundamentais.
Primeiramente:
- você fez seu trabalho
- ao mesmo tempo, alguém estava comprando osciloscópios
- na ocorrência do evento “osciloscópios adquiridos” - você interrompe seu trabalho
- já faz algum tempo que você faz outros trabalhos - carregando osciloscópios
- então você retorna ao seu local de trabalho e continua fazendo seu trabalho de onde parou

Em segundo lugar:
- você poderia facilmente mandar seu chefe e não ir a lugar nenhum
- depois de sair para os osciloscópios, você pode ficar lá por muito tempo, ou até mesmo nem voltar
- quando você retornar ao seu local de trabalho, talvez já tenha esquecido suas ideias brilhantes

Tudo isso é muito semelhante ao que acontece em um microcontrolador. Os microcontroladores AVR incluem vários dispositivos periféricos (temporizadores/contadores, conversor analógico-digital, comparador analógico, transceptor assíncrono... etc.). O poder do microcontrolador é que todos esses dispositivos podem funcionar em paralelo e independentemente uns dos outros, bem como em paralelo ao programa que está sendo executado. Cada dispositivo periférico pode disparar uma interrupção quando ocorre um evento específico. A interrupção só ocorrerá se estiver habilitada. A ativação de interrupção é definida para cada dispositivo separadamente. Além disso, há um sinalizador global de ativação/desativação para todas as interrupções - este é o sinalizador I no registro SREG. Quando ocorre uma interrupção, o microcontrolador armazena o conteúdo do contador do programa do PC na pilha, ou seja, lembra o local onde foi interrompido. Carrega o endereço do vetor de interrupção correspondente no contador do programa e salta para esse endereço. Ele atinge um comando de salto incondicional, que vai para a sub-rotina de processamento de interrupção. Desativa interrupções redefinindo o sinalizador I e executa a sub-rotina. Executada a rotina de tratamento de interrupções, o microcontrolador habilita as interrupções configurando o flag I e restaura o conteúdo do contador do programa, ou seja, retorna ao mesmo local do programa em que foi interrompido.

Em teoria, o manipulador de interrupções não deveria danificar o conteúdo dos registradores do microcontrolador, pois eles podem conter dados do programa que está sendo executado naquele momento. Para isso, no início da sub-rotina de tratamento de interrupções, o conteúdo dos registradores do microcontrolador é armazenado na pilha e, no final da sub-rotina, eles são restaurados. Assim, após sair da interrupção, o microcontrolador poderá continuar executando o programa como se nada tivesse acontecido. Ao programar em assembler, o próprio programador prescreve o salvamento de registros em C, isso é feito pelo compilador.

_______________________________________________________________

Agora vamos falar sobre o cronômetro. O ATmega8535 possui três temporizadores/contadores integrados - dois de oito bits (T0, T2) e um de dezesseis bits (T1). Usaremos um temporizador/contador T0 de oito bits. Este temporizador consiste em três registros - o registro de controle TCCR0, o registro de contagem TCNT0 e o registro de comparação OCR0. Quando o temporizador é iniciado, o registrador contador TCNT0 aumenta seu valor em um para cada transição de clock. A frequência do clock é selecionada entre vários valores possíveis no registro de controle TCCR0. Além disso, usando este registro, o modo de operação do temporizador é definido. O temporizador T0 pode disparar uma interrupção na ocorrência de um evento de “overflow” - é quando o registrador de contagem TCNT0 transborda, e na ocorrência de um evento de “coincidência” - é quando o valor do registrador de contagem TCNT0 se torna igual ao valor do registro de comparação OCR0. Os flags que habilitam essas interrupções estão localizados no registrador TIMSK.
Configuraremos o temporizador/contador T0 para acionar uma interrupção de evento de “correspondência” em 5 kHz. Na função handler inverteremos o estado da saída do microcontrolador à qual o alto-falante piezoelétrico está conectado. Assim, a frequência do som piezo será igual a 2,5 kHz. (É o piezo alto-falante que está conectado! Não confunda. A resistência de um piezo alto-falante depende da frequência e em 2,5 KHz geralmente são unidades de Com, portanto pode ser conectado diretamente à saída do microcontrolador, sem resistor limitador) .

Agora sobre o programa. Não é mais possível escrever o programa linha por linha, então darei imediatamente o seu texto. A seguir analisaremos todas as suas linhas uma por uma, e tudo ficará claro. Eu deliberadamente não usei macros; o programa é pequeno e não quero desordená-lo.

interno principal( vazio )
{
//configura portas de E/S
DDD = (0<PORTD = (1<

//configura o temporizador T0
TCCR0 = (1<TCNT0 = 0;
OCR0 = 0xc8;

//habilita interrupções
__enable_interrupt();

//loop do programa principal – pesquisando o botão
enquanto(1){
se((PIND & (1<TIMSK = (1<outro
TIMSK = 0;
}
retornar 0;
}

//manipulador de interrupção para o temporizador T0

__interromper vazio Timer0CompVect( vazio)
{
PORTD ^= (1<}

Configurações de porta

Em nosso circuito, um botão e um alto-falante piezoelétrico estão conectados à porta D. O pino ao qual o botão está conectado deve ser configurado como entrada e o resistor pull-up deve estar ligado. O pino ao qual o alto-falante piezoelétrico está conectado deve ser definido como saída.

DDD = (0<PORTD = (1<

Configurando o cronômetro

O modo de operação do temporizador T0 é CTC (reset em coincidência), o sinal do relógio é clk/8. Refletimos isso no registro TCCR0

TCCR0 = (1<

Por precaução, zeramos o registro de contagem TCNT0

Escreva 0xc8 no registro de comparação OCR0. Por que? Porque eu contei com isso calculadora. Bem, no papel esse cálculo é assim.
Frequência de clock do microcontrolador 8 MHz
O sinal do relógio do temporizador é 8.000.000 Hz/8 = 1.000.000 Hz.
Tempo de um temporizador 1/1000000 = 1 µs
O tempo de um ciclo da frequência que precisamos é 1/5000 Hz = 200 μs
Quantos tiques do temporizador cabem em 200 µs? 200/1 = 200 ticks
200 em hexadecimal = 0xс8

Para uma descrição detalhada do temporizador T0, consulte a documentação do ATMega8535.

Configuramos o temporizador e habilitamos uma interrupção geral usando a função integrada.

__enable_interrupt();

Botão de enquete

Quando o botão não é pressionado, a saída do microcontrolador é conectada à alimentação através de um resistor pull-up interno, ou seja, há um na saída quando o botão é pressionado, a saída está em curto com o terra, ou seja, existe; é um zero na saída. Para determinar se um botão está pressionado, você precisa ler o conteúdo do registro PIND e verificar o valor do bit zero (um botão está conectado ao PD0). Pesquisaremos o botão em um loop infinito.

enquanto (1)
{
se((PIND & (1<//se o botão for pressionado, o microcontrolador deverá chiar
}
outro {
//se não, fique em silêncio como um peixe
}
}

Não esqueça que == não é um operador de atribuição =.

Manuseio de pressionar/soltar o botão

Ao pressionar o botão habilitaremos a interrupção do temporizador T0, e ao soltá-lo iremos desabilitá-lo. Para fazer isso, manipularemos o bit OCIE0 do registrador TIMSK

TIMSK = (1<//permite a interrupção do timer T0 devido ao evento coincidente

TIMSK = 0; //desativa a interrupção

Como estamos usando apenas um temporizador, não há necessidade de definir ou redefinir bits individuais.

Função de interrupção

_____________________ Sintaxe da função de interrupção _____________________

A função de interrupção é especificada usando a diretiva #pragma vector= e uma palavra de função __interromper. A função deve ser do tipo void e não deve aceitar nenhum parâmetro.

#pragma vetor = Endereço
__interromper vazio Nome( vazio)
{
//nosso código está localizado aqui
}

Nome– nome da função, escolha a nosso critério
Endereço– endereço do vetor de interrupção, pode ser especificado por número ou por nomes definidos no arquivo de cabeçalho do microcontrolador (iom8535.h – seção Definições do vetor de interrupção)

______________________________________________________________

Para nossa tarefa, a função do manipulador de interrupção se parece com isto

#pragma vetor = TIMER0_COMP_vect
__interromper vazio Timer0CompVect( vazio)
{
PORTD ^= (1<//inverte o sinal no pino PD1
}

Bom, isso é tudo. Espero que tudo esteja claro.
No próximo artigo faremos o microcontrolador tocar uma melodia.

Interrupção - um evento que requer uma resposta imediata do processador. A resposta é que o processador interrompe o processamento do programa atual ( programa interrompido) e prossegue para executar algum outro programa ( interrompendo programa), especialmente desenhado para este evento. Após a conclusão deste programa, o processador volta a executar o programa interrompido.

Cada evento que requer uma interrupção é acompanhado por sinal de interrupção, notificando o computador sobre isso e ligou solicitação de interrupção.

Status do programa representa um conjunto de estados de todos os elementos de armazenamento no momento correspondente (por exemplo, após a execução do último comando). Quando ocorre uma interrupção, o microcontrolador armazena o conteúdo do contador do programa na pilha e carrega nele o endereço do vetor de interrupção correspondente. O último comando da rotina de serviço de interrupção deve ser um comando que retorne ao programa principal e restaure o contador do programa armazenado anteriormente. Enquanto o manipulador de interrupção está em execução, algumas informações podem mudar. Portanto, ao passar para o manipulador de interrupções, é necessário salvar os elementos que estão sendo alterados. O conjunto de tais elementos é vetor de estado do programa. Nesse caso, outras informações sobre o estado das células de memória não são significativas ou podem ser restauradas programaticamente.

Vetor de estado inicial contém todas as informações necessárias para o lançamento inicial do programa. Em muitos casos, o vetor de estado inicial contém apenas um elemento - o endereço inicial do programa que está sendo iniciado.

Vetor de interrupçãoé o vetor do estado inicial do programa que interrompe (manipulador) e contém todas as informações necessárias para passar para o manipulador, incluindo seu endereço inicial. Cada tipo de interrupção possui seu próprio vetor de interrupção, que inicia a execução do manipulador correspondente. Normalmente, os vetores de interrupção são armazenados em locais de memória fixa especialmente alocados com endereços curtos, que representam tabela de vetores de interrupção. Para saltar para o programa de interrupção apropriado, o processador deve ter um vetor de interrupção e o endereço desse vetor. Neste endereço, via de regra, existe um comando de salto incondicional para a sub-rotina de tratamento de interrupções.

Via de regra, o controle de armazenamento e retorno é atribuído ao manipulador de interrupções. Neste caso, o manipulador é composto por três partes - preparatória (prólogo) e final (epílogo), que garantem a troca do programa, e o próprio programa de interrupção, que realiza as operações solicitadas pela solicitação. O tempo de resposta é definido como o intervalo de tempo desde o momento em que uma solicitação de interrupção é recebida até o início da execução do programa que está interrompendo.


tp– tempo de resposta do sistema à interrupção;
t z– tempo para armazenar o estado do programa interrompido;
t ppr– hora do programa de interrupção real;
lata– tempo para restaurar o estado do programa interrompido

Se houver diversas fontes de solicitações, uma determinada ordem de atendimento das solicitações recebidas deve ser estabelecida, chamada relacionamentos prioritários ou disciplina de serviço. O conjunto de todos os tipos possíveis de interrupção do processador é sistema de interrupção microcontrolador. A disciplina de serviço determina qual das várias solicitações recebidas simultaneamente é processada primeiro e se este ou aquele manipulador de interrupção tem o direito de interromper essa solicitação.
Se uma solicitação de interrupção de prioridade mais alta for recebida enquanto uma interrupção estiver sendo processada, o controle será transferido para o manipulador de interrupções de prioridade mais alta e o manipulador de interrupções de prioridade mais baixa será suspenso. Surge interromper aninhamento. O número máximo de programas que podem suspender uns aos outros é chamado profundidade das interrupções.

Se a solicitação de interrupção não for atendida no momento em que uma nova solicitação chegar da mesma fonte (mesma prioridade), então interromper a saturação do sistema. Neste caso, algumas solicitações de interrupção serão perdidas, o que é inaceitável para o funcionamento normal do microcontrolador.

Características do sistema de interrupção são:

  • número total de solicitações de interrupção número de fontes de solicitações de interrupção;
  • tipo de representação de interrupção - via de regra, uma solicitação de interrupção é representada por um nível de sinal lógico;
  • prioridade de interrupção – determina a ordem em que cada solicitação de interrupção é processada; quanto maior a prioridade, menor o atraso na execução do programa de interrupção da mesma;
  • tempo de resposta – intervalo de tempo entre o aparecimento da solicitação de interrupção e o início da execução do programa interrompidor;
  • atraso de interrupção – determinado pelo tempo total de armazenamento e restauração do programa;
  • profundidade, geralmente coincide com o número de níveis de prioridade no sistema de interrupção;
  • interromper a saturação do sistema;
  • momentos permitidos de interrupção do programa (geralmente o final da execução do próximo comando).

Mascaramento de interrupção usado para dizer ao microcontrolador para responder a cada tipo de interrupção ou ignorá-la. A máscara de interrupção representa um código binário cujos bits são atribuídos às fontes da solicitação de interrupção. O único bit no código binário informa ao microcontrolador para lidar com esse tipo de interrupção. Um bit zero, ao contrário, não permite que o microcontrolador proceda ao processamento de interrupções do tipo especificado.
Via de regra, além de mascarar interrupções, há também um bit de habilitação de interrupção global, cujo valor zero desabilita todos os manipuladores de interrupção (exceto reinicialização de hardware e salto para o início do programa em execução).
Além do código binário da máscara de interrupção, há também um código binário sinalizadores de interrupção, que permite ao manipulador de interrupção definir a origem da interrupção se houver várias fontes com a solicitação especificada no microcontrolador.



 


Ler:



O que é um SSD e como instalá-lo?

O que é um SSD e como instalá-lo?

O desempenho e a vida útil de um SSD dependem principalmente da memória flash NAND e do firmware do controlador. Eles são os principais componentes...

Como colocar acento em uma letra no Word

Como colocar acento em uma letra no Word

Ao trabalhar no Word, um dia você terá que enfrentar a necessidade de adicionar um acento. Você pode, é claro, destacar a vogal tônica em negrito...

Como converter imagens para o formato PNG?

Como converter imagens para o formato PNG?

O formato de imagem JPG possui uma taxa de compactação maior que o PNG e, portanto, as imagens com esta extensão têm menos peso. A fim de reduzir...

Problemas técnicos e suas soluções v

Problemas técnicos e suas soluções v

Muito bem, espero que ajude. Blockhead de fato permaneceu estabelecido desde os dias de OCO... Bons estudiosos da tradição estão em contato próximo com o universo....

imagem de feed RSS