Varför fungerar min avbrottskod inte?

Bakgrund

Jag försöker skriva kod för att läsa signaler från en sexkanals RC-mottagare på en Arduino Mega 2560 . För närvarande håller jag koden för att bara läsa en kanal för att göra det enkelt att felsöka. Problemet är att min delade variabel inte uppdateras, vilket får mig att tro att min avbrott servicerutinen upptäcker inga stigande kanter.

Jag trodde att min mottagare var trasig, så jag testade den med standard Arduino attach interrupt-funktion . Det fungerade perfekt, så min mottagare är bra.

Jag använde Serial.print () för att se om min flyktiga kanalvariabel uppdaterades (det vill säga ändra sitt värde till flaggvärdet för kanal 1). Det uppdaterades inte, så min ISR måste vara fel. Du hittar originalkoden i blogginlägget.

Vad är fel? Jag har inga idéer.

 #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

  • Försök att förenkla din kod. Låt ISR tända en ledning, till exempel. Jag ser ' inte att se något som är fel.
  • Jag tänkte på det. Av någon anledning fungerar det bara på stiften 10,11 och 12. Jag vet inte ' varför. PinchangeInt borde fungera på alla digitala stift
  • Men du använder pin 10? Hur som helst, glad att du fick det att fungera.

Svar

Endast några -portar på Atmega2560 stöder pin-switch-avbrott, särskilt portar B, E (bit 0), J (bitar 0 till 6) och K.

Tittar på referensschemat som innebär att dessa stift på kortet stöds:

 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 att D10 till D12, som du säger fungerar, finns i listan. Andra slumpmässiga skulle inte vara.


SoftwareSerial

Du kan se en bekräftelse på sidan för SoftwareSerial där det står:

Inte alla stift på Mega och Mega 2560-stödet byter avbrott, så endast följande kan användas för 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).

Detta beror på att SoftwareSerial använder avbrytningsavbrott för att upptäcka inkommande seriell data, och därmed ansvarsfriskrivningen på den sidan om vilka stift den kommer att fungera med.


Atmega2560 pin-outs

Atmega2560 pin-outs


PinchangeInt ska fungera på alla digitala stift

Observera att Atmega328P (som används i Uno) har färre portar, och alla är tillgängliga för avbrytningar av stift på det kortet.

Kommentarer

  • Detta kan ' inte vara rätt. Sidan som först länkas av OP-påståenden stift 2, 3, 18, 19, 20 och 21 kan användas för avbrott. Dessa kartläggs till PE4, PE5, PD3, PD2, PD1 och PD0 enligt goo.gl/DvHEUA och goo.gl/xAwBGM Jag för min del ' är mer koncentrerad om huruvida PORTC kan användas, som i ros_arduino_bridge: goo.gl/rq6yQO
  • Den länkade sidan hänvisar till externa avbrott men OP använder stiftbyte avbrott som du kan se från #include <PinChangeInt.h>. Stiftbytestopparna är de jag listade.
  • Jag förstår. Jag hade en aning som kan vara skillnaden, men antog att alla stift med externa avbrott också skulle kunna byta stift, men inte tvärtom.

Svar

På ATmega1280 / 2560 är det bara portarna B, J, F och K som har stiftförändringsfunktion. Dessa kartläggs ungefär till stiften 10 till 15, 50 till 53 och A6 till och med A15 (även om en del av port J inte är mappad till Arduino-stift, är därför PCINT11 till PCINT15 inte tillgängliga på Arduino Mega / Mega 2560).

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *