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][C] SPI - przerwanie w master

dturczak 04 Kwi 2010 15:46 2260 4
REKLAMA
  • #1 7919620
    dturczak
    Poziom 19  
    Witam.
    Problem jest nastepujacy.
    mam dzialajacy kod komunikacji miedzy atmegami po SPI.
    Odbior danych po stronie slave w przerwaniu ,po stronie master w funkcji :
    
    char SPI_MasterReceive(void)
    {
    SPDR = 0xFF;
    /* Wait for reception complete */
    while(!(SPSR & (1<<SPIF)))
    ;
    /* Return data register */
    return SPDR;
    }
    

    Dla wygody postanowilem rowniez w przerwaniu zrobic odbior danych po stronie master:

    
    void SPI_MasterInit(void)
    {
    /* Set MOSI and SCK output, all others input */
    DDRB = (1<<DDB5)|(1<<DDB7);
    /* Enable SPI, Master, set clock rate fck/16 */ + interrupt
    SPCR = ((1<<SPE)|(1 <<SPIE)|(1<<MSTR)|(1<<SPR0));
    }
    



    
    SIGNAL (SIG_SPI) {
    
    	
    	znak=SPDR;
    	if (znak==0x05) { cyfra(3); }
    
    }
    

    w main wlaczone sei();

    jednak zglaszanie przerwania przychodzacych danych po stronie master nie dziala....
  • REKLAMA
  • #2 7920033
    zerpo
    Poziom 22  
    Pamiętaj, że w celu wywołania przerwania w Masterze musisz najpierw gdzieś w programie Mastera wysłać coś do SPDR. Przerwanie nastąpi po wysłaniu danych (co jest równoznaczne z odebraniem danych od Slave'a).
    W swojej funkcji SPI_MasterReceive wysłałeś najpierw 0xFF i potem czekałeś na odbiór (a dokładnie na zakończenie równolegle przebiegającego przesyłania/odbierania danych). I tak samo należy zrobić, aby wywołać przerwanie...
  • REKLAMA
  • #3 7921061
    dturczak
    Poziom 19  
    Probuje tak:

    Inicjuje master.
    wysylam cos (SPDR),czekam na odbior w SIGNAL

    Inicjuje slave ,czekam na odbior w SIGNAL,jezeli przyjdzie moja dana to odsylam

    master:
    
    main:
    /* Set MOSI and SCK output, all others input */
    DDRB = (1<<DDB5)|(1<<DDB7);
    /* Enable SPI, Master, set clock rate fck/16 */
    SPCR = ((1<<SPE)|(1 <<SPIE)|(1<<MSTR)|(1<<SPR0));
    
    sei();
    
    SPDR = 0x02; //juz bez while(!(SPSR & (1<<SPIF))) ,przez zastosowanie przerwania ?
    
    //czekam na odbior w SIGNAL (SIG_SPI)
    SIGNAL (SIG_SPI) {
    	
    	znak=SPDR;
    	if (znak==0x05) { //JEST ODPOWIEDZ SLAVE }
    
    }
    
    
    


    slave:
    
    DDRB = (1<<DDB6);
    /* Enable SPI */
    SPCR = (1<<SPE)|(1 <<SPIE);
    
    //czekam na odbior i odsylam znak:
    SIGNAL (SIG_SPI) {
    
    	
    	znak=SPDR;
    	if (znak==0x02) { PORTD |= _BV(7); SPI_SlaveTransmit(0x05); }
    
    }
    
    
    void SPI_SlaveTransmit(char cData)
    {
    
    SPDR = cData;
    
    //juz bez while(!(SPSR & (1<<SPIF))) ?
    ;
    }
    
    
    


    gubic sie w tym zaczynam
  • REKLAMA
  • Pomocny post
    #4 7921095
    zerpo
    Poziom 22  
    W Slave wpisujesz bajt do SPDR dopiero, gdy wchodzisz do przerwania. Czyli w momencie, gdy transmisja została już zakończona! (Nastąpiła wymiana danych DO i Z)
    To jest trochę dziwne, ale w przypadku Slave, w momencie wejścia do przerwania od SPI dane z bufora SPDR już zostały wysłane.
    Oznacza to, że w pewnym sensie trzeba przewidzieć co chcesz wysłać, zanim wystąpi przerwanie.

    Proponuję, abyś wysyłał MASTERem 2 bajty i dopiero po drugim wysłanym bajcie sprawdził, czy == 0x05. Programu SLAVE'a nie zmieniaj.
  • #5 7921176
    dturczak
    Poziom 19  
    OK,juz wiem o co chodzi ;)
    W takim razie jezeli chce to zrobic na przerwaniach i miec komunikacje w postaci :
    pytanie - odpowiedz to musze poswiecic dodatkowy bajt zeby przeladowac SPDR.
    Tez mnie to bardzo dziwi ze po wejsciu do przerwania odrazu dane sa wysylane...
    dzieki ze ten fakt odkryles przedemną ! ;)
    pdr
REKLAMA