Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[STM32F4][C] - Brak odpowiedzi z urządzenia I2C.

16 Mar 2013 11:31 1905 12
  • Poziom 15  
    Witam,

    Próbuję uruchomić komunikację po magistrali I2C z akcelerometrem LSM303DLM.
    Niestety próba wysłania czegokolwiek kończy się zatrzymaniem programu w któreś pętli while. Podejrzewam, że nie otrzymuję potwierdzenia ACK od urządzenia slave.

    Poniżej przedstawię funkcje, które wykorzystuję do tego celu.

    Konfiguracja I2C:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Funkcja zapisu na magistralę:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Inicjalizacja akcelerometru:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Powyższa funkcja powinna wysłać na adres 0x30, adres rejestru 0x20, a potem jego wartość 0x27. Czy w ogóle poprawnie wykorzystuję funkcję i2c_write?

    Taką właśnie sekwencję używałem na ATmedze i działała poprawnie, a więc same wartości wysyłane są OK.
  • Poziom 15  
    Właśnie to sprawdziłem.
    Program zatrzymuje się w

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Sprawdziłem jeszcze poprawność podłączenia, wszystko wydaje się być w porządku.

    Moduł, z którym próbuje się komunikować to:
    Link
  • Specjalista - Mikrokontrolery
    Twoja funkcja od I2C to jest wariacja na temat mojej, która po pierwsze postała dla STM32F1, więc nie wiem czy dla STM32F4 nie są konieczne jakieś zmiany, a po drugie korzystała z bit-bandingu, stąd te dziwne odczyty rejestrów statusowych (bo nie byłem pewny czy odczyt przez bit-band liczy się jako odczyt rejestru) - z tego względu u Ciebie powtórzone odczyty po pętlach są zbędne, np tu:

    Code:
    while (!(I2C1->SR1 & I2C_SR1_ADDR));   // wait for address transfer
    
       dummy = I2C1->SR1;                  // clear the flag <= zbędny - odczytane w pętli
       dummy = I2C1->SR2;


    No i dobrze byłoby jednak wiedzieć CO KONKRETNIE się dzieje, jakie dziwne wartości w rejestrach statusowych, gdzie dokładnie się zawiesza itd.

    A pinów chyba nie ustawiasz na open-drain, bez tego raczej nie zadziała (;

    4\/3!!
  • Poziom 15  
    Tzn. piny powinny być jako open-drain, czy nie? (próbowałem i tak i tak - nie działa)

    Ok, odczyt z rejestru, który wskazałeś usunę, ale do tego miejsca nawet nie dochodzę. Zatrzymuje się podczas oczekiwania na ustawienie bitu ADDR w rejestrze SR1.

    Z tego co rozumiem bit ADDR nie jest ustawiany w 1, ponieważ nie otrzymuję ACK od slave'a. Pytanie tylko dlaczego? Może to wina konfiguracji pinów, a może samego I2C.
  • Poziom 15  
    Hmm no to chyba tak mam.
    Nie wpisuje nic do rejestru PUPDR.
  • Specjalista - Mikrokontrolery
    mkot123 napisał:
    Hmm no to chyba tak mam.

    Chyba nie.

    mkot123 napisał:
    Nie wpisuje nic do rejestru PUPDR.

    Nikt nie mówi nic o pull-upach...

    4\/3!!
  • Poziom 20  
    A takie proste pytanko. Widzę że nie wiesz czy piny powinny być push pull czy open drain (oczywiście open drain) Więc czy wiesz że linie SCL i SDA powinny być podciągnięte do VDD przez rezystory ??
  • Poziom 15  
    Ok, zgodnie z sugestiami dodałem w konfiguracji pinów:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Rezystory 4k7 są już na płytce z modułem akcelerometru.

    Inicjalizacja się wykonała.

    Teraz nadszedł moment na odczytanie czegoś. Znowu stoi :-(
  • Poziom 20  
    Freedi w przykładach wstawił dość przyjazne biblioteki do gpio może użyj ich zamiast maglować rejestry będzie o wiele prościej i mniejsza szansa na błędy.
  • Specjalista - Mikrokontrolery
    mkot123 napisał:
    Teraz nadszedł moment na odczytanie czegoś. Znowu sto

    Tylko skąd mamy wiedzieć jak chcesz to odczytywać, skoro pokazałeś tylko funkcje do zapisu...

    4\/3!!
  • Poziom 15  
    Dzięki Wam jestem o krok dalej :-)

    Teraz próbuje odczytać 6 rejestrów zawierających dane o przyśpieszeniu z każdej z osi (dla każdej z nich po 2 bajty.

    Funkcja odczytu:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wykorzystanie tej funkcji:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    0x30 to adres urządzenia, 0x8a adres pierwszego z sześciu rejestrów.

    Debugowałem program. Wygląda na to, że odczytuje pierwszy rejestr - pętla while(len) wykonuje się jednokrotnie, a po drugim razie zatrzymuje się na oczekiwaniu na RXNE.


    Czy po odebraniu bajtu, program nie powinien generować sygnału ACK? Z tego co widzę można to zrobić poprzez ustawienie bitu ACK w rejestrze CR1.

    Dopisek:
    Nieco zmodyfikowałem funkcję odczytu. Teraz po wejściu w pętlę while(len) mam takie coś:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czyli dla 6,5,4,3,2 bajtu wysyłam ACK, a po otrzymaniu 1 już nie, czyli kończę transmisję. Program już nie zatrzymuje się na pętli while, ale odbieram same zera.




    No i znalazłem błąd. Szukałem linijka po linijce, znak po znaku.
    Pierwszy adres, od którego powinienem czytać to 0xA8, a nie 0x8A.
    Znalazłem to dopiero za 2 albo 3 razem. Naprawdę było ciężko.

    Bardzo dziękuję za pomoc!!!