Warum funktioniert mein Interrupt-Code nicht?

Hintergrund

Ich versuche, Code zu schreiben, um Signale von einem Sechs-Kanal-RC-Empfänger auf einem Arduino Mega 2560 . Derzeit behalte ich den Code, um nur einen Kanal zu lesen, um die Fehlerbehebung zu vereinfachen. Das Problem ist, dass meine gemeinsam genutzte Variable nicht aktualisiert wird, was mich glauben lässt, dass mein Interrupt vorliegt Die Serviceroutine erkennt keine ansteigenden Flanken.

Ich dachte, mein Empfänger sei defekt, und habe ihn daher mit der Standard-Arduino-Attach-Interrupt-Funktion getestet Es hat perfekt funktioniert, daher ist mein Empfänger in Ordnung.

Ich habe Serial.print () verwendet, um festzustellen, ob meine flüchtige Kanalvariable aktualisiert wurde (Das heißt, ändern Sie den Wert in den Flag-Wert für Kanal 1). Es wurde nicht aktualisiert, daher muss mein ISR falsch sein. Sie finden den Originalcode in der Blog-Beitrag.

Was ist los? Ich habe keine Ideen mehr.

 #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; } }  

Kommentare

  • Versuchen Sie, Ihren Code zu vereinfachen. Lassen Sie den ISR beispielsweise eine LED aufleuchten. Ich sehe ‚ nichts, was von Natur aus falsch ist.
  • ch habe es herausgefunden. Aus irgendeinem Grund funktioniert es nur an den Pins 10, 11 und 12. Ich weiß jedoch nicht, warum.

warum. PinchangeInt sollte an jedem digitalen Pin funktionieren

  • Aber Sie verwenden Pin 10? Wie auch immer, ich bin froh, dass Sie es zum Laufen gebracht haben.
  • Antwort

    Nur einige -Ports des Atmega2560 unterstützen Pin-Change-Interrupts, insbesondere die Ports B, E (Bit 0), J (Bits) 0 bis 6) und K.

    Betrachtet man das Referenzschema, bedeutet dies, dass diese Pins auf der Platine unterstützt werden:

     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 

    Also Sie können sehen, dass D10 bis D12, von denen Sie sagen, dass sie funktionieren, in dieser Liste enthalten sind. Andere zufällige wären dies nicht.


    SoftwareSerial

    Auf der Seite für SoftwareSerial wird die Bestätigung angezeigt:

    Nicht alle Pins der Mega und Mega 2560 unterstützen Änderungsinterrupts, daher kann für RX nur Folgendes verwendet werden: 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).

    Dies liegt daran, dass SoftwareSerial Pin-Change-Interrupts verwendet, um eingehende serielle Daten zu erkennen, und damit den Haftungsausschluss auf dieser Seite, mit welchen Pins es funktioniert.


    Atmega2560-Pinbelegung

    Atmega2560-Pinbelegung


    PinchangeInt sollte auf jedem digitalen Pin

    funktionieren Beachten Sie, dass der Atmega328P (wie im Uno verwendet) weniger Ports hat und alle für Pinwechselwechsel-Interrupts auf dieser Karte verfügbar sind.

    Kommentare

    • Dies kann ‚ nicht richtig sein. Die Seite, die zuerst durch die OP-Ansprüche der Pins 2, 3, 18, 19, 20 und 21 verknüpft wurde, kann für Interrupts verwendet werden. Diese werden PE4, PE5, PD3, PD2, PD1 und PD0 gemäß goo.gl/DvHEUA und goo.gl/xAwBGM Ich für meinen Teil ‚ bin mehr besorgt darüber, ob PORTC verwendet werden kann, wie in ros_arduino_bridge: goo.gl/rq6yQO
    • Die verlinkte Seite bezieht sich auf externe Interrupts, das OP verwendet jedoch Pinwechsel-Interrupts als Sie können von #include <PinChangeInt.h> sehen. Die Pin-Wechsel-Interrupt-Pins sind die, die ich aufgelistet habe.
    • Ich sehe. Ich hatte eine Ahnung, die die Unterscheidung sein könnte, ging aber davon aus, dass alle Pins, die zu externen Interrupts fähig sind, auch zum Pinwechsel fähig sind, wenn auch nicht umgekehrt.

    Antwort

    Auf dem ATmega1280 / 2560 können nur die Ports B, J, F und K den Pinwechsel unterbrechen. Diese werden ungefähr den Pins 10 bis 15, 50 bis 53 und A6 bis A15 zugeordnet (obwohl ein Teil von Port J nicht den Arduino-Pins zugeordnet ist, sind PCINT11 bis PCINT15 auf dem Arduino Mega / Mega 2560 nicht verfügbar).

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.