logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega16][rfm12b][c] Odbiór danej przy użyciu przerwania

kormikez 01 Cze 2009 22:02 1996 2
REKLAMA
  • #1 6604832
    kormikez
    Poziom 10  
    Witam.

    Mój drugi temat na tym forum zacznę od przypomnienia, że jestem noobem w dziedzinie mikrokontrolerów i z tegoż względu proszę o wyrozumiałość...

    Mój AVR jest połączony z modułem RF12B tak jak na schemacie http://www.hoperf.com/pdf/rf12_code.pdf (strona 10).

    Chcę aby wszystkie układy AVR+RF (docelowo większa ich ilość) komunikowały się ze sobą jako autonomiczne węzły - mają więc zarówno nadawać, jak i odbierać dane. Udało mi się zrobić namiastkę tego na bazie przykładu z linka powyżej. Był to taki ping-pong (moduł wysyłał bajt, po czym czekał aż drugi moduł mu odpowiedział i tak w kółko). Jest to o tyle złe rozwiązanie, że dopóki moduł nie odbierze danej, czeka. I jeśli dana nie przyjdzie - czeka w nieskończoność. To oczywiście nie to, czego oczekuję.

    Poczytałem i już wiem, że muszę skorzystać z mechanizmu przerwań. Napisałem coś takiego:

    
    #define RX_ON 0x8299
    #define TX_ON 0x8239
    volatile unsigned int received;
    //...
    ISR(SIG_INTERRUPT0)
    {
                    Cmd(0x0000);
                    received = Cmd(0xB000);
                    received &= 0x00FF;
    }
    //...
    
    int main(void)
    {
    //...
    
            GICR |= 1<<INT0;
            MCUCR |= 1<<ISC01;
    
    //...
    
                                    if(odebrał_znak)
                                    {
                                            Cmd(TX_ON); 
                                            LEDR_ON();
                                            delay(70);
                                            Cmd(0x0000); 
                                            Send(0xAA); // PREAMBLE
                                            Send(0xAA);
                                            Send(0xAA);
                                            Send(0x2D); // SYNC
                                            Send(0xD4);
                                            Send(bajt);
                                            LEDR_OFF();
                                            Cmd(RX_ON);
                                    }
    
    //...
                    if (received)
                    {
                            LEDG_ON();
                            delay(30);
                            rsSend(received);
                            LEDG_OFF();
                            received=0x00;
                     }
    }


    gdzie Cmd to odpowiednik RFXX_WRT_CMD (strona 18).

    Niestety tak skompilowany program w efekcie po wysłaniu kilku znaków (co ciekawe dopiero po kilku reaguje) nagle zaczyna masowo odbierać jakieś śmieci :(.

    Walczę z tym od trzech dni i już po prostu nie mam ani siły, ani pomysłów.

    Wydaje mi się, że problem w nieumiejętnym wykorzystaniu przerwania (choć głowy nie dam). Stąd mam nadzieję na jakieś wskazówki także od osób, które być może nie znają RF12B, ale mają doświadczenie z innym sprzętem; jak mniemam wszystko to działa w jakiś sposób podobnie.

    Dorzucę jeszcze kod działającej funkcji odbierającej (jak w opisie na początku):

    unsigned char RF12_RECV(void){
      unsigned int FIFO_data;
      WAIT_IRQ_LOW();
      RFXX_WRT_CMD(0x0000);
      FIFO_data=RFXX_WRT_CMD(0xB000);
      return(FIFO_data&0x00FF);
    }


    Za wszelkie wskazówki i sugestie, które pomogą mi rozwiązać problem ofiaruję swoje wszystkie punkty ;)
  • REKLAMA
  • #2 6605499
    rpal
    Poziom 27  
    Nie wiem czy dobrze to pojąłem ale chyba chcesz aby przerwanie wykoanało odczyt z zegara ?Transmisja po I2C jest stosunkowo wolna i cały ten gips wywali się tobie przy wykonaniu przerwania. Zastosuj flagi (jeśli chcesz koniecznie użyć przerwania) które program sprawdzi i w zależności od ich stanu wykona w głownej pętli. Transmisja I2C w przerwaniu kłóci się z zasadą przerwania czyli wykonaj jak najszybciej i sp.... :)
  • #3 6605901
    kormikez
    Poziom 10  
    Nie ma to jak wsparcie kogoś z doświadczeniem :)

    Rzeczywiście, wywalenie instrukcji poza makro przerwania sprawiło, że mój program zachowuje się rozsądnie. Nie rozwiązało to co prawda do końca mojego problemu (aktualnie program odbiera tylko jeden znak i to po uprzednim wysłaniu innego - czyli znów mam ping-pong:), ale jest to już jakiś krok naprzód, a z tym będę już sobie radzić sam. No chyba, że ktoś mi coś zasugeruje i tym samym zaoszczędzi godzin dłubania ;). [EDIT: już nieaktualne :)]

    Przy okazji, czy jest jakiś sposób, żeby ocenić, czy instrukcja w przerwaniu trwa dostatecznie krótko? Czy jedynie empirycznie - działa, znaczy, że OK, nie działa - za długo :)
REKLAMA