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

[C]Odczyt kilku kolejnych bajtów przez I2C

kulpina 28 Sty 2010 17:36 2431 10
REKLAMA
  • #1 7606394
    kulpina
    Poziom 14  
    Mam śmieszny problem.
    Korzystam z biblioteki I2C z tej strony:
    http://mikrokontrolery.net/avr_c_09.htm

    I praca w moim układzie wygląda tak, że odczytywany jest pierwszy bajt z układu slave, natomiast wszystkie kolejne są odczytywane jako 255. Jeśli każdy bajt odczytuje pojedynczo poprzedzając odczytanie startem i zaadresowaniem układu itd. to odczytują się prawidłowo...
    Przypuszczam, ze problem wygląda tak, że pierwszy bajt jest odczytywany poprawnie, ale potem mój mikroprocesor nie wysyła slave'owi sygnału ack zrywając przez to transmisję :( Dlatego kolejne bajty są odczytywane jako 255.


    Chciałbym zwrócić uwagę konkretnie na ten fragment:
    unsigned char i2cread(unsigned char ack)
    {
    unsigned char count = 8, temp = 0;
    SET_SDA; SDA_IN;
    do
    {
    delay();
    SET_SCL;
    delay();
    temp <<= 1;
    if (GET_SDA) temp++;
    CLR_SCL;
    } while (--count);
    if(ack) SET_SDA;    // <----- to miejsce mnie zastanawia
    delay();
    SET_SCL;
    delay();
    CLR_SCL;
    return (temp);
    }


    W oznaczonym miejscu wykonywana jest operacja wystawienia jakiegoś stanu na SDA, jednak to SDA nie jest tam wtedy wyjściem a wejściem, jak więc można coś na nie wpisać? Z drugiej strony mój problem polega na tym, że jak dodałem przed tą linijką polecenie SDA_OUT; to nic ono nie zmieniło...
    Ma ktoś jakiś pomysł? Zajmuje się tą głupotą już któryś tydzień i wszystko zawodzi...
  • REKLAMA
  • #2 7607710
    morson
    Poziom 14  
    Podaj co oznaczają (z źródła) te SET_SDA, CLR_SDA itp, bo jeśli to co nazwa znaczy to cały kod jest wątpliwej jakości.

    Sprawdź jak masz z ustawianiem Ack, bo w każdym kolejnym czytanym bajcie Ack powinno być 1, a w ostatnim 0.
  • #3 7607725
    kulpina
    Poziom 14  
    W podanym linku jest opisane to znaczenie.
    Jest tak:
    
    #include <avr/io.h>
    //
    #define I2CDir DDRD
    #define I2COut PORTD
    #define I2CIn  PIND
    //
    #define SDA 6
    #define SCL 5
    //
    #define SET_SDA I2COut |= (1 << SDA)
    #define CLR_SDA I2COut &= ~(1 << SDA)
    //
    #define SET_SCL I2COut |= (1 << SCL)
    #define CLR_SCL I2COut &= ~(1 << SCL)
    //
    #define SDA_OUT I2CDir |= (1 << SDA)
    #define SDA_IN  I2CDir &= ~(1 << SDA)
    //
    #define SCL_OUT I2CDir |= (1 << SCL)
    #define SCL_IN  I2CDir &= ~(1 << SDA)
    //
    #define GET_SDA (I2CIn & (1 << SDA))
    //
    #define ACK 0
    #define NOACK 1
    
  • REKLAMA
  • #4 7607945
    morson
    Poziom 14  
    Spróbuj dodać
    
    if(ack) SET_SDA;    // <----- to miejsce mnie zastanawia
    else CLR_SDA;
    

    powinno pomóc, chociaż itak w I2C powinno się sterować rejestrami DDRx i podwiesić rezystorem do plusa nóżkę
  • REKLAMA
  • #5 7610966
    kulpina
    Poziom 14  
    No właśnie taką poprawkę już wprowadzałem i nic to nie dało :(
    DDRx? Tzn ustawić cały czas jako wejscia i tylko podciągać programowo wewnętrzny rezystor?
  • #6 7611178
    Konto nie istnieje
    Poziom 1  
  • #7 7611554
    kulpina
    Poziom 14  
    Z programu wynika, że warunek jest spełniony dla ack=1 czyli tak naprawdę noack (jest odwrotnie, więc to jest dobrze). No ale właśnie, czyli mam sterować rejestrem ddr? a jak mam to zrobić?
  • REKLAMA
  • #8 7611567
    zumek
    Poziom 39  
    atom1477 napisał:
    Powinno byc odwrotnie. ACK to stan niski. NACK to stan wysoki.
    A po drugie to sterować trzeba rejestrem DDR a nie PORT.
    
    CLR_SDA;
    
    if(ack) SDA_OUT;
    else SDA_IN;
    

    Po trzecie, niewłaściwa funkcja i2cwrite.Funkcja powoduje, że master wysyła 9 bitów do slave'a, a powinien wysłać 8, a dziewiąty(ACK) odczytać.
  • #9 7611656
    kulpina
    Poziom 14  
    Próbowałem ją tak przerobić, ale coś mi nie wyszło. Narazie próbuję zapoznać się z atmelowskimi funkcjami, a może ktoś ma jeszcze jakieś proste funkcje do i2c?
REKLAMA