Dlaczego mój kod przerwania nie działa?

Tło

Próbuję napisać kod odczytujący sygnały z sześciokanałowego odbiornika RC na Arduino Mega 2560 . Obecnie przechowuję kod tylko po to, aby odczytać jeden kanał, aby ułatwić rozwiązywanie problemów. Problem polega na tym, że moja zmienna współdzielona nie aktualizuje się, co prowadzi mnie do przekonania, że moje przerwanie procedura serwisowa nie wykrywa żadnych narastających krawędzi.

Wydawało mi się, że mój odbiornik jest uszkodzony, więc przetestowałem go przy użyciu standardowej funkcji przerwania połączenia Arduino . Działało doskonale, więc mój odbiornik jest w porządku.

Użyłem Serial.print () , aby sprawdzić, czy moja zmienna zmienna kanału jest aktualizowana (czyli zmień jego wartość na wartość flagi kanału 1). Nie był aktualizowany, więc mój ISR musi być nieprawidłowy. Oryginalny kod można znaleźć w post na blogu.

Co się dzieje? Brakuje mi pomysłów.

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

Komentarze

  • Spróbuj uprościć swój kod. Poproś na przykład, aby ISR zapalił diodę LED. Nie ' nie widzę niczego z natury nie tak.
  • Rozgryzłem to. Z jakiegoś powodu działa tylko na pinach 10, 11 i 12. Nie ' nie wiem dlaczego. PinchangeInt powinien działać na każdym cyfrowym pinie
  • Ale używasz styku 10? W każdym razie; cieszę się, że działa.

Odpowiedź

Tylko niektóre porty na Atmega2560 obsługują przerwania zmiany pinów, szczególnie porty B, E (bit 0), J (bity 0 do 6) i K.

Patrząc na schemat odniesienia, oznacza to, że te szpilki na płycie są obsługiwane:

 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 

Zatem widać, że na tej liście znajdują się od D10 do D12, o których mówisz, że działają. Inne przypadkowe nie.


SoftwareSerial

Możesz zobaczyć potwierdzenie na stronie SoftwareSerial , gdzie jest napisane:

Nie wszystkie piny w Mega i Mega 2560 obsługują zmiany przerwań, więc dla RX można użyć tylko następujących: 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).

Dzieje się tak, ponieważ SoftwareSerial używa przerwań ze zmianą pinów do wykrywania przychodzących danych szeregowych, a tym samym zastrzeżenia na tej stronie dotyczące pinów, z którymi będzie współpracować.


Wyprowadzenia Atmega2560

Wyprowadzenia Atmega2560


PinchangeInt powinien działać na każdym cyfrowym pinie

Zwróć uwagę, że Atmega328P (używany w Uno) ma mniej portów i wszystkie są dostępne dla przerwań zmiany pinów na tej płycie.

Komentarze

  • To nie może ' nie mieć racji. Strona połączona jako pierwsza przez OP twierdzi, że piny 2, 3, 18, 19, 20 i 21 mogą być używane do przerwań. Są one mapowane na PE4, PE5, PD3, PD2, PD1 i PD0, zgodnie z goo.gl/DvHEUA i goo.gl/xAwBGM Ze swojej strony ' bardziej zgadzam się z tym, czy można używać PORTC, jak w ros_arduino_bridge: goo.gl/rq6yQO
  • Strona, do której prowadzi łącze, odnosi się do zewnętrznych przerwań, jednak OP używa przerwań zmiana pinów jako możesz zobaczyć na #include <PinChangeInt.h>. Wymieniłem piny przerwania zmiany pinów.
  • Widzę. Miałem podejrzenie, że może to być różnica, ale założyłem, że wszystkie piny zdolne do zewnętrznych przerwań będą również zdolne do zmiany pinów, ale nie na odwrót.

Odpowiedź

W ATmega1280 / 2560 tylko porty B, J, F i K mają możliwość przerywania zmiany pinów. Są one odwzorowywane w przybliżeniu na piny od 10 do 15, od 50 do 53 i od A6 do A15 (chociaż część portu J nie jest przypisana do pinów Arduino, dlatego PCINT11 do PCINT15 są niedostępne w Arduino Mega / Mega 2560).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *