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

ATmega8, ADXL345, I2C/TWI zawiesza się, nie odczytuje danych.

bart_90 20 Lis 2014 10:00 1995 11
  • #1 14148008
    bart_90
    Poziom 9  
    Witam,
    od kilku dni próbuję uporać się z problemem odczytu danych z akcelerometru ADXL345 przez standard TWI/I2C.
    W nocie katalogowej jest napisane, że jeżeli SDO podłączone jest do GND, akcelerometr przyjmuje adresy 0xA6 read i 0XA7 write. Tak też zrobiłem. Pin CS podłączony do +5V. Do ATmegi8 podłączony mam rezonator kwarcowy 16 MHz. Prędkość TWI ustawiłem na standardową prędkość 100 kHz. Wyliczyłem to za pomocą wzoru ((16 MHz/100 kHz)-16)/2= 72 => TWBR = 0x48.

    Mój problem polega na tym iż nie mogę odczytać i wyświetlić danych z akcelerometru.
    Konfiguracja ADXL345 przebiega poprawnie (przez co wnoszę, że adresy są poprawne). Kiedy program chce odczytać dane z osi X znajdujące się pod adresem 0x32, zawiesza się. W kodzie programu zaznaczyłem to miejsce dość widocznie. Gdy zaneguje tę operację program przechodzi dalej wyświetlając "odczytane dane" i wchodzi w ostatnią pętlę, migając diodą.

    Wszystko zasilane jest przy pomocy USBASP_ATB ? czy to może generować mój problemem?
    Może źle coś przeliczyłem lub podłączyłem? Bardzo proszę o pomoc!
    Schemat oraz kod programu znajduje się poniżej.

    Żeby wyprzedzić już niepotrzebne pytania. Tak, są rezystory podciągające do SCL oraz SDA, są one widoczne na schemacie.
    Jak wynika z kodu, odczytuję jeden bajt danych osi X ? być może i tu jest problem. Może powinienem od razu całą paczkę odczytywać?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    ATmega8, ADXL345, I2C/TWI zawiesza się, nie odczytuje danych. ATmega8, ADXL345, I2C/TWI zawiesza się, nie odczytuje danych.

    Żeby nie było niedomówień - na schemacie ATmegi8 piny SV1 należą do P1 na schemacie płytki ADXL345, drugi analogicznie.

    Ostatnią przyczyną błędów może byś po prostu uszkodzone urządzenie, niestety nie mam jak tego sprawdzić. Pozostaje mi jedynie zamówić kolejny...
  • #2 14148142
    Sparrowhawk
    Poziom 22  
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Kod: text
    Zaloguj się, aby zobaczyć kod


    Nie wiem, czy tylko to jest powodem, ale starasz się zapisać dane pod nieistniejący adres. Przekraczasz zakres. Jeżeli tak masz zadeklarowany bufor, to ostatnim elementem jest 15 element.

    W C/C++ indeksy tablicy n-elementowej są z zakresu 0 .. n-1.
  • #3 14153549
    bart_90
    Poziom 9  
    A nie jest przypadkiem tak, tak że jeżeli tworzymy tablice [16] to jest ona 16to komórkowa lecz indeks zaczyna się od 0 do 15?

    Zrozumiałem to w ten sposób że musiałbym tworzyć tab[15] żeby mieć 16to komórkową, a to nie prawda, tak przynajmniej mi się wydaje.

    Bez zmian.
  • #4 14153685
    hexen2k
    Poziom 16  
    bart_90 napisał:
    while ((TWCR&(1<<TWSTO))); // tu niektórzy ludzie mają wykrzyknik, inni nie, dlaczego?


    Zobacz na stronie Radosława Kwietnia:
    http://radzio.dxp.pl/twi/

    Masz opis bitu TWSTO.

    Generalnie czekasz na zakończenie transmisji sygnału STOP w pętli whiile. Gdy transmisja się zakończy bit jest automatycznie zerowany i pętla jest przerywana.

    Wykrzyknik w innych kodach w tym miejscu wydaje się najzwyklejszym błędem.
  • #5 14153687
    dondu
    Moderator na urlopie...
    bart_90 napisał:
    A nie jest przypadkiem tak, tak że jeżeli tworzymy tablice [16] to jest ona 16to komórkowa lecz indeks zaczyna się od 0 do 15?

    No przecież kolega Sparrowhawk napisał:

    Sparrowhawk napisał:
    W C/C++ indeksy tablicy n-elementowej są z zakresu 0 .. n-1.


    Skompiluj sobie poniższy program w kompilatorze CManiak: http://mikrokontrolery.blogspot.com/p/cmaniak-kompilator-jezyka-c-online.html

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    i przeanalizuj rezultat.
  • #6 14161559
    bart_90
    Poziom 9  
    Przeanalizowałem wszystko, dzięki za podpowiedzi. Doszedłem natomiast do tego, że nie można tak zapisywać danych do tablicy. To co ja chciałem zrobić jest błędem, ponieważ, po pierwsze chciałem zapisać daną liczbę do rzeczywiście nieistniejącej komórki tablicy, po drugie, nawet jeżeli bym chciał zrobić:
    Kod: C#
    Zaloguj się, aby zobaczyć kod

    to nie jest to możliwe.

    Ta linijka programu próbuje całą, 16-to bitową wartość sczytaną z ADXL345 wcisnąć w jedną ostatnią komórkę tablicy.
    Np.
    bufor[0] = 0;
    bufor[1] = 0;
    bufor[2] = 0;
    .
    .
    .
    bufor[15] = 0000111100001111; // błąd!!!
    Powinienem skorzystać ze wskaźnika i każdą cyfrę z osobna powinienem wrzucić do osobnej komórki? Nie wiem jeszcze jak tego zrobić bo nie działałem na wskaźnikach.
    Dobrze myślę?

    A może mógłbym po prostu zapisać wynik w dwóch zmiennych 8 bitowych, pierwsza by była od 0 do 7 bit druga od 8 do 15?
    Jak to zrobić programowo?
  • #7 14161688
    vonar
    Poziom 28  
    bart_90 napisał:
    Ta linijka programu próbuje całą, 16-to bitową wartość sczytaną z ADXL345 wcisnąć w jedną ostatnią komórkę tablicy.

    Nie. Nawet gdyby ta funkcja zwracała wartość 16-bitową (a tak nie jest, o ile wciąż wygląda tak, jak w pierwszym poście), to i tak wynik zostałby obcięty do jednego bajtu podczas zapisu do tablicy.
  • #8 14163297
    bart_90
    Poziom 9  
    W takim razie w jaki sposób mam przydzielić te dane do osobnych komórek?
    Może w ogóle zrezygnować z tablicowej koncepcji i tak jak napisałem wyżej, zapisać dane w dwóch zmiennych?
    Proszę o podpowiedź.
  • #9 14163352
    Sparrowhawk
    Poziom 22  
    No skoro funkcja ma zwracać wartość 16 bitową, to niech taką zwraca, ale nie robi się tego za pomocą tablicy.

    W tej chwili twoja funkcja odczytu zwraca 8 bitową wartość, nie oczekując na drugi bajt danych.
  • #10 14163366
    bart_90
    Poziom 9  
    Zrozumiałem w końcu... tak mi się wydaje.
    Trzeba z TWI/I2C odebrać dwa bajty, nie tylko jeden jak jest u mnie...
    Zaraz zabiorę się za przekształcenie kodu. Niestety nie sprawdzę tego teraz ponieważ jestem w pracy.
    Wieczorem popróbuje. Mam nadzieję, że w końcu coś się ruszy.
  • #11 14207664
    bart_90
    Poziom 9  
    Witam,
    dalej się męczę z tym tematem, co prawda nie mam zbyt wiele czasu na co dzień dlatego nie udzielam się zbyt często, a szkoda.

    Zmodyfikowałem kod programu wykorzystując przykłady z książki Pana Kardasia lecz dalej bez zmian, a nawet gorzej, teraz przy inicjalizacji ADXL345 program wchodzi do pętli STOP i już z niej nie wychodzi, nie mówiąc już o odbieraniu danych.
    Bardzo proszę o pomoc lub podpowiedź.

    Kod: C#
    Zaloguj się, aby zobaczyć kod


    Działanie programu jest bardzo podobne co do poprzedniego lecz bez wyświetlacza.
    Po udanej inicjalizacji oraz odczytaniu dwóch bajtów wchodzi w nieskończoną pętle zapalając i gasząc diodę z pewną częstotliwością, która informuje o poprawnym wykonaniu operacji.
    Jak widać zanegowałem na razie odczyt danych oraz część inicjalizacji ponieważ już podczas wysyłania pierwszego bajtu danych z konfiguracją ( adxl_init() ) program zawiesza się nie wychodząc z pętli TWI_stop(), co zaznaczyłem w kodzie programu.

    Bardzo proszę o pomoc bo już nie wiem co mam robić.
    Zamówiłem wczoraj kolejny akcelerator z tym samym czujnikiem lecz inną płytką. Może mój jest uszkodzony, może nie. Na pewno się oby dwa przydadzą o ile będą sprawne, a ja dojdę do jakiegoś konsensusu.
  • #12 14208391
    Andrzej__S
    Poziom 28  
    Zadeklarowałeś:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    później w pętli głównej wywołujesz funkcję adxl_init() w której wysyłasz bufor do ADXL345:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    a co jest w tym momencie w buforze, czyli co tak naprawdę wysyłasz?

    bart_90 napisał:
    ...ponieważ już podczas wysyłania pierwszego bajtu danych z konfiguracją ( adxl_init() ) program zawiesza się nie wychodząc z pętli TWI_stop(), co zaznaczyłem w kodzie programu.

    Jak sprawdzasz, że akurat ta linijka sprawia problem?

    Sam fakt wpisania odpowiednich wartości do TWDR i TWCR nie gwarantuje, że transmisja na magistrali przebiegnie prawidłowo. Rejestr TWSR zawiera ważne informacje o tym, co dzieje się na magistrali podczas transmisji, a Ty nawet nie sprawdzasz, czy układ slave odpowiedział bitem potwierdzenia.

    W datasheet na stronie 170 masz przykład, jak wykorzystać rejestr TWSR. Na stronie 173 są wartości TWSR informujące o statusie transmisji.
REKLAMA