Hvorfor fungerer min afbrydelseskode ikke?

Baggrund

Jeg prøver at skrive kode for at læse signaler fra en seks-kanals RC-modtager på en Arduino Mega 2560 . I øjeblikket holder jeg koden for bare at læse en kanal for at gøre det let at foretage fejlfinding. Problemet er, at min delte variabel ikke opdateres, hvilket får mig til at tro, at min afbrydelse servicerutine registrerer ikke stigende kanter.

Jeg troede, at min modtager var brudt, så jeg testede det ved hjælp af standard Arduino attach interrupt-funktion . Det fungerede perfekt, så min modtager er i orden.

Jeg brugte Serial.print () for at se, om min ustabile kanalvariabel opdateres. (det vil sige ændre dens værdi til værdi for kanal 1-flag). Den opdaterede ikke, så min ISR må være forkert. Du kan finde den originale kode i blogindlægget.

Hvad er der galt? Jeg er ude af ideer.

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

Kommentarer

  • Prøv at forenkle din kode. Få ISR til at tænde en ledning, for eksempel. Jeg kan ikke ' ikke se noget i sig selv forkert.
  • Jeg fandt ud af det. Af en eller anden grund fungerer det kun på ben 10,11 og 12. Jeg ved ' dog ikke hvorfor. PinchangeInt skal arbejde på enhver digital pin
  • Men du bruger pin 10? Alligevel; glad for at du fik det til at fungere.

Svar

Kun nogle porte på Atmega2560 understøtter pin-change interrupts, specifikt porte B, E (bit 0), J (bits 0 til 6) og K.

Ser man på referenceskematikken, der betyder, at disse ben på tavlen understøttes:

 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 

Således du kan se, at D10 til D12, som du siger fungerer, er på listen. Andre tilfældige ville ikke være.


SoftwareSerial

Du kan se bekræftelse på siden for SoftwareSerial , hvor der står:

Ikke alle ben på Mega og Mega 2560 understøtter ændringer, så kun følgende kan bruges til 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).

Dette skyldes, at SoftwareSerial bruger afbrydelser med pin-skift til at registrere indgående serielle data, og dermed ansvarsfraskrivelsen på den side om, hvilke ben den skal arbejde med.


Atmega2560 pin-outs

Atmega2560 pin-outs


PinchangeInt skal fungere på enhver digital pin

Bemærk, at Atmega328P (som brugt i Uno) har færre porte, og alle er tilgængelige til pin-change-afbrydelser på dette kort.

Kommentarer

  • Dette kan ' ikke være rigtigt. Den side, der først er linket med OP-krav, ben 2, 3, 18, 19, 20 og 21 kan bruges til afbrydelser. Disse kortlægges til PE4, PE5, PD3, PD2, PD1 og PD0 i henhold til goo.gl/DvHEUA og goo.gl/xAwBGM Jeg for min del ' er mere koncentreret om, hvorvidt PORTC kan bruges, som i ros_arduino_bridge: goo.gl/rq6yQO
  • Den sammenkædede side henviser til eksterne afbrydelser, men OP bruger pin-ændring afbrydelser som kan du se fra #include <PinChangeInt.h>. Pin-skift-afbrydestifterne er dem, jeg nævnte.
  • Jeg kan se. Jeg havde en forståelse, der måske var forskellen, men antog, at alle ben, der var i stand til eksterne afbrydelser, også ville være i stand til at skifte pin, men ikke omvendt.

Svar

På ATmega1280 / 2560 er det kun porte B, J, F og K, der har pin-ændringsafbrydelsesfunktion. Disse kortlægges omtrent til ben 10 til 15, 50 til 53 og A6 til A15 (selvom en del af port J ikke er tilknyttet Arduino-ben, er PCINT11 til PCINT15 derfor ikke tilgængelig på Arduino Mega / Mega 2560).

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *