Quantos pinos de interrupção um Uno pode controlar?

Estou pensando em usar um receptor RC de 7 canais com o Arduino Uno R3. Na documentação, há menções de no máximo 2 pinos de interrupção, enquanto em alguns outros blogs eu vi menções do uso de até 20 pinos como interrupções, com a biblioteca PinChangeInt. Então, quantas interrupções o Arduino pode manipular nativamente? E isso é diferente de quantos podem ser tratados com suporte de software como PinChangeInt?

Resposta

Existem dois tipos de ” pin change “interrupções de tipo. As interrupções externas, das quais existem duas no Uno. Eles são chamados de 0 e 1, mas se referem aos pinos digitais 2 e 3 da placa. Eles podem ser configurados para detectar aumento, queda, mudança (aumento ou queda) ou BAIXO.

Além disso, há interrupções de “mudança de pino”, que detectam uma mudança no estado do pino em qualquer um dos 20 pinos (A0 a A5 e D0 a D13). Essas interrupções de mudança de pino também são baseadas em hardware , portanto, em si mesmas, serão tão rápidas quanto as interrupções externas.

Ambos os tipos são um pouco complicados de usar no nível de registro, mas o IDE padrão inclui attachInterrupt (n) e detachInterrupt (n) que simplifica a interface para interrupções externas. Você também pode usar a Biblioteca de alteração de pino para simplificar as interrupções de alteração de pino.

No entanto, saindo da biblioteca por um minuto, nós pode estabelecer que as interrupções de mudança de pino podem ser tão rápidas ou mais rápidas que as interrupções externas. Por um lado, embora as interrupções de mudança de pino funcionem em lotes de pinos, você não precisa habilitar o lote inteiro. Por exemplo, se você deseja detectar alterações no pino D4, isso será suficiente:

Exemplo esboço:

 ISR (PCINT2_vect) { // handle pin change interrupt for D0 to D7 here if (PIND & bit (4)) // if it was high PORTD |= bit (5); // turn on D5 else PORTD &= ~bit (5); // turn off D5 } // end of PCINT2_vect void setup () { // pin change interrupt (example for D4) PCMSK2 |= bit (PCINT20); // want pin 4 PCIFR |= bit (PCIF2); // clear any outstanding interrupts PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7 pinMode (4, INPUT_PULLUP); pinMode (5, OUTPUT); } // end of setup void loop () { }  

Meu teste indica que levou 1,6 µs para o “teste “pino (pino 5) para reagir a uma mudança no pino de interrupção (pino 4).


Agora, se você seguir a abordagem simples (preguiçosa?) e usar attachInterrupt (), você encontrará o os resultados são mais lentos, não mais rápidos.

Exemplo de código:

 void myInterrupt () { if (PIND & bit (2)) // if it was high PORTD |= bit (5); // turn on D5 else PORTD &= ~bit (5); // turn off D5 } // end of myInterrupt void setup () { attachInterrupt (0, myInterrupt, CHANGE); pinMode (2, INPUT_PULLUP); pinMode (5, OUTPUT); } // end of setup void loop () { }  

Isso leva 3,7 µs para alterar o pino de teste, muito mais do que os 1,6 µs acima. Por quê? Porque o código que o compilador deve gerar para o manipulador de interrupções “genérico” precisa salvar todos os registradores concebíveis (empurrá-los) entrada para o ISR e, em seguida, restaure-os (pop-los) antes de retornar. Além disso, há a sobrecarga de outra chamada de função.


Agora podemos contornar isso evitando attachInterrupt () e fazendo isso nós mesmos:

 ISR (INT0_vect) { if (PIND & bit (2)) // if it was high PORTD |= bit (5); // turn on D5 else PORTD &= ~bit (5); // turn off D5 } // end of INT0_vect void setup () { // activate external interrupt 0 EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags EICRA |= bit (ISC00); // set wanted flags (any change interrupt) EIFR = bit (INTF0); // clear flag for interrupt 0 EIMSK |= bit (INT0); // enable it pinMode (2, INPUT_PULLUP); pinMode (5, OUTPUT); } // end of setup void loop () { }  

Esse é o mais rápido de todos eles em 1,52 µs – parece que um ciclo de clock foi salvo em algum lugar.


Há uma ressalva, entretanto, para interrupções de mudança de pino. Eles são agrupados, então se você quiser ter interrupções em muitos pinos, você precisa testar dentro da interrupção que um mudou . Você pode fazer isso salvando o status do pino anterior e comparando-o com o novo status do pino. Isso não é necessariamente muito lento, mas quanto mais pinos você precisar verificar, mais lento será.

Os lotes são:

  • A0 a A5
  • D0 a D7
  • D8 a D13

Se você quiser apenas mais alguns pinos de interrupção, pode evitar qualquer teste apenas escolhendo usar pinos diferentes lotes (por exemplo, D4 e D8).


Mais detalhes em http://www.gammon.com.au/interrupts

Resposta

Existem dois tipos de interrupções. O que o Arduino Playground disse:

O processador no coração de qualquer Arduino tem dois tipos diferentes de interrupções: “externa” e “mudança de pino”. Existem apenas dois pinos de interrupção externa no ATmega168 / 328 (ou seja, no Arduino Uno / Nano / Duemilanove), INT0 e INT1, e eles são mapeados para os pinos 2 e 3 do Arduino. Essas interrupções podem ser configuradas para disparar em RISING ou Bordas de sinal em QUEDA ou em nível baixo. Os gatilhos são interpretados pelo hardware e a interrupção é muito rápida. O Arduino Mega tem mais alguns pinos de interrupção externa disponíveis.

Por outro lado, as interrupções de mudança de pino podem ser habilitadas em muitos outros pinos. Para Arduinos baseados em ATmega168 / 328, eles podem ser ativados em qualquer um ou em todos os 20 pinos de sinal do Arduino; nos Arduinos baseados em ATmega, eles podem ser ativados em 24 pinos. Eles são acionados igualmente em bordas de sinal EM SUBIDA ou EM QUEDA, portanto, cabe ao código de interrupção definir os pinos apropriados para receber interrupções, determinar o que aconteceu (qual pino? … o sinal aumentou ou caiu?) e manipulá-lo corretamente.Além disso, as interrupções de mudança de pino são agrupadas em 3 “portas” no MCU, portanto, existem apenas 3 vetores de interrupção (sub-rotinas) para todo o corpo de pinos. Isso torna o trabalho de resolver a ação em uma única interrupção ainda mais complicado.

Basicamente, as interrupções externas são extremamente rápidas, pois todas são baseadas em hardware . No entanto, há também as interrupções de mudança de pino, mas parecem ser muito mais lentas porque são baseadas principalmente em software.

tl; dr: os 20 pinos de interrupção juntos são muito mais lentos. Os 2 pinos de interrupção são os mais rápidos e mais eficientes.


EDITAR: Acabei de olhar a folha de dados e ela diz que uma interrupção de mudança de pino é acionada para qualquer um dos pinos selecionados sem indicação de qual pino foi alterado (embora esteja dividido em três vetores de interrupção).

  • Para interrupções externas, dirá a você o pino 3 acabou de mudar
  • Para alteração de pino, “dirá a você um pino alterado que você estava monitorando!

Como você pode ver, um A interrupção de mudança de pino adiciona muita sobrecarga ao ISR que você precisa manipular armazenando estados anteriores e ver se é o pino com o qual você está preocupado. Pode ser bom para um estado de hibernação, mas é melhor usar as interrupções externas.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *