Por que meu código de interrupção não está funcionando?

Histórico

Estou tentando escrever código para ler sinais de um receptor RC de seis canais em um Arduino Mega 2560 . Atualmente estou mantendo o código para apenas ler um canal para facilitar a solução de problemas. O problema é que minha variável compartilhada não está atualizando, o que me leva a acreditar que minha interrupção a rotina de serviço não está detectando nenhuma borda ascendente.

Achei que meu receptor estava quebrado, então testei usando a função de interrupção de anexação padrão do Arduino . Funcionou perfeitamente, então meu receptor está bom.

Usei Serial.print () para ver se minha variável de canal volátil estava sendo atualizada (ou seja, altere seu valor para o valor do sinalizador do canal 1). Ele não estava atualizando, então meu ISR deve estar errado. Você pode encontrar o código original em a postagem do blog.

O que há de errado? Estou sem ideias.

 #include <PinChangeInt.h> //Pin assignment #define channel1PIN 10 //Bit flags #define Channel1FLAG 1 //Flag holder volatile uint8_t bFLAGUPDATESHARED; //Shared variables: Accessed by the interrupt service routine and read in "void loop". volatile uint16_t unCHANNEL1SHARED; //Start time variables: These are used to set the start time of the rising edge of //a pulse. They are only accessed by the ISR, and thus they are unsigned integers and //not volatiles. uint32_t ulCHANNEL1START; void setup() { Serial.begin(9600); Serial.print("RC Channel PWM Read Interrupt Test"); //PinChangInt library function. Used to set attach interrupts. PCintPort::attachInterrupt(channel1PIN, calcCHANNEL1, CHANGE); } void loop() { //In-loop variables to hold local copies of channel inputs. //This is static so it retains values between call loops. static uint16_t unCHANNEL1IN; //The in-loop copy of the bSHAREDFLAGUPDATE volatile flag holder static uint8_t bFLAGUPDATELOCAL; //Check to see if any channels have received signals. If so, copy //shared variables to local in loop variables. if (bFLAGUPDATESHARED) { //Switch off interrupts when I copy shared variables to local variables noInterrupts(); bFLAGUPDATELOCAL = bFLAGUPDATESHARED; if (bFLAGUPDATELOCAL & Channel1FLAG) { unCHANNEL1IN = unCHANNEL1SHARED; } bFLAGUPDATESHARED = 0; interrupts(); } Serial.println(unCHANNEL1IN); //Clear local update flags copy as all values have been copied to local variables bFLAGUPDATELOCAL = 0; } void calcCHANNEL1() { if (digitalRead(channel1PIN) == HIGH) { //If pin goes high, start timer and set ulCHANNEL1START to timer start ulCHANNEL1START = micros(); } else { //If it is not rising, it must be falling so set shared //variable to current time-start time unCHANNEL1SHARED = (uint16_t)(micros() - ulCHANNEL1START); //Tell that channel 1 has received a signal bFLAGUPDATESHARED |= Channel1FLAG; } }  

Comentários

  • Tente simplificar seu código. Faça o ISR acender um led, por exemplo. Eu não ‘ não vejo nada inerentemente errado.
  • Eu descobri. Por algum motivo, ele só funciona nos pinos 10,11 e 12. Eu não ‘ não sei por quê. O PinchangeInt deve funcionar em qualquer pino digital
  • Mas você está usando o pino 10? De qualquer forma, fico feliz que tenha funcionado.

Resposta

Apenas algumas portas no Atmega2560 suportam interrupções de mudança de pino, especificamente as portas B, E (bit 0), J (bits 0 a 6) e K.

Olhando para o esquema de referência, isso significa que esses pinos na placa são suportados:

 Chip Name Pin Pin on board ----------------------- Port B PB0 - 19 - D53 (SS) PB1 - 20 - D52 (SCK) PB2 - 21 - D51 (MOSI) PB3 - 22 - D50 (MISO) PB4 - 23 - D10 PB5 - 24 - D11 PB6 - 25 - D12 PB7 - 26 - D13 Port E PE0 - 2 - D0 (RXD0) Port J PJ0 - 63 - D15 (RXD3) PJ1 - 64 - D14 (TXD3) PJ2 to PJ6 - not connected on board Port K PK0 - PK7 - (89 - 82) - A8 - A15 

Assim você pode ver que D10 a D12, que você diz que funciona, estão nessa lista. Outros aleatórios não estariam.


SoftwareSerial

Você pode ver a confirmação na página de SoftwareSerial onde diz:

Nem todos os pinos no Mega e Mega 2560 suportam interrupções de alteração, portanto, apenas o seguinte pode ser usado para RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).

Isso ocorre porque o SoftwareSerial usa interrupções de mudança de pino para detectar dados seriais de entrada e, portanto, a isenção de responsabilidade nessa página sobre com quais pinos ele funcionará.


Pinagens do Atmega2560

Pinagens do Atmega2560


PinchangeInt deve funcionar em qualquer pino digital

Observe que o Atmega328P (como usado no Uno) tem menos portas e todas estão disponíveis para interrupções de troca de pinos nessa placa.

Comentários

  • Isso pode ‘ não estar certo. A primeira página ligada por OP reivindica os pinos 2, 3, 18, 19, 20 e 21 podem ser usados para interrupções. Estes mapeiam para PE4, PE5, PD3, PD2, PD1 e PD0, de acordo com goo.gl/DvHEUA e goo.gl/xAwBGM De minha parte, ‘ estou mais preocupado se o PORTC pode ser usado, como em ros_arduino_bridge: goo.gl/rq6yQO
  • A página vinculada refere-se a interrupções externas , no entanto o OP está usando interrupções de mudança de pino como você pode ver em #include <PinChangeInt.h>. Os pinos de interrupção de mudança de pino são os que listei.
  • Entendo. Tive a impressão de que poderia ser a diferença, mas presumi que todos os pinos capazes de interrupções externas também seriam capazes de alterar o pino, embora não o contrário.

Resposta

No ATmega1280 / 2560, apenas as portas B, J, F e K têm capacidade de interrupção de mudança de pino. Eles mapeiam aproximadamente para os pinos 10 a 15, 50 a 53 e A6 a A15 (embora parte da porta J não esteja mapeada para os pinos do Arduino, portanto, PCINT11 a PCINT15 não estão disponíveis no Arduino Mega / Mega 2560).

Deixe uma resposta

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