Pozadí
Snažím se psát kód pro čtení signálů ze šestikanálového RC přijímače na Arduino Mega 2560 . V současné době nechávám kód, aby pouze četl jeden kanál, aby bylo možné snadno vyřešit potíže. Problém je v tom, že moje sdílená proměnná se neaktualizuje, což mě vede k přesvědčení, že moje přerušení servisní rutina nedetekuje žádné vzestupné hrany.
Myslel jsem, že můj přijímač je rozbitý, a tak jsem ho otestoval pomocí standardní funkce přerušení připojení Arduino . Fungovalo to perfektně, takže můj přijímač je v pořádku.
Použil jsem Serial.print () , abych zjistil, zda se moje proměnlivá proměnná kanálu aktualizuje (to znamená změnit jeho hodnotu na hodnotu příznaku kanálu 1). Neaktualizovalo se, takže moje ISR se musí mýlit. Původní kód najdete v příspěvek na blogu.
Co se děje? Už jsem z myšlenek.
#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; } }
Komentáře
- Zkuste zjednodušit svůj kód. Nechte například ISR rozsvítit LED. Nevidím ' nic neodmyslitelně špatného.
- Přišel jsem na to. Z nějakého důvodu to funguje pouze na piny 10,11 a 12. Nevím ' ale proč. PinchangeInt by měl fungovat na jakémkoli digitálním pinu
- Ale používáte pin 10? Každopádně; jste rádi, že to funguje.
Odpověď
Pouze některé porty Atmega2560 podporují přerušení pin-change, konkrétně porty B, E (bit 0), J (bity 0 až 6) a K.
Podíváme-li se na referenční schéma, znamená to, že jsou podporovány tyto piny na desce:
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
Tedy můžete vidět, že D10 až D12, o kterých si myslíte, že fungují, jsou v tomto seznamu. Jiné náhodné by nebyly.
SoftwareSerial
Na stránce SoftwareSerial můžete vidět potvrzení, kde je uvedeno:
Ne všechny piny na Mega a Mega 2560 podporují změnu přerušení, takže pro RX lze použít pouze následující: 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).
Důvodem je, že SoftwareSerial používá k detekci příchozích sériových dat přerušení pin-change, a tedy odmítnutí odpovědnosti na této stránce, s kterými piny bude pracovat.
Doplňky Atmega2560
PinchangeInt by měl fungovat na jakémkoli digitálním kolíku
Všimněte si, že Atmega328P (použitý v Uno) má méně portů a všechny jsou k dispozici pro přerušení pinů na této desce.
Komentáře
- Toto nemůže být ' správné. Stránka, na kterou nejprve odkazují OP nároky, kolíky 2, 3, 18, 19, 20 a 21 lze použít pro přerušení. Tyto mapy se mapují na PE4, PE5, PD3, PD2, PD1 a PD0 podle goo.gl/DvHEUA a goo.gl/xAwBGM Pokud jde o mě, já ' m více souvisí s tím, zda lze použít PORTC, jako v ros_arduino_bridge: goo.gl/rq6yQO
- Propojená stránka odkazuje na externí přerušení, ale OP používá přerušení PIN přerušení jako můžete vidět z
#include <PinChangeInt.h>
. Připínací piny pro změnu PIN jsou ty, které jsem uvedl. - Rozumím. Měl jsem tušení, které by mohlo být rozdílem, ale předpokládal jsem, že všechny piny schopné externích přerušení budou také schopné změny pinů, i když ne naopak.
Odpověď
Na ATmega1280 / 2560 mají schopnost přerušení změny PIN pouze porty B, J, F a K. Mapují se přibližně na piny 10 až 15, 50 až 53 a A6 až A15 (ačkoli část portu J není namapována na piny Arduino, proto PCINT11 až PCINT15 nejsou na Arduino Mega / Mega 2560 k dispozici).