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

ATMEGA 8 - Jak wysłać bajt danych przez TWI? Samodzielnie napisane funkcje

marcin w 12 Mar 2015 18:10 1653 9
  • #1 14523314
    marcin w
    Poziom 22  
    Witam

    Mam problem z wysłaniem bajta danych przez TWI, procesor ATMEGA8. Funkcje obsługi TWI TWI pisałem samodzielnie na podstawie informacji w internecie. Zawarte są w pliku I2C

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


    Wykonuję prostą operację wysłania instrukcji resetu do układu MS5611.

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


    Podglądając na analizatorze przebiegi na magistrali I2C widać że tylko leci tylko adres SLA+W, drugi bajt danych 0x1E nie wchodzi na magistralę.

    ATMEGA 8 - Jak wysłać bajt danych przez TWI? Samodzielnie napisane funkcje

    Wydaje mi się że po bajcie zawierającym SLA+W brak potwierdzenia ACK.
    Może ktoś podpowiedzieć co jest przyczyną braku funkcjonalności ? Moduł z układem MS5611 który jest tutaj jako slave jest nowy, też inny zawierający ten układ, który jest również nowy. Raczej mało prawdopodobne by były oba uszkodzone.

    Czy ktoś może rzucić okiem na poprawność kodu ?
  • #2 14524778
    Eagle
    Poziom 24  
    Na oscylogramie w miejscu ACK, masz małą szpilkę. Nie robisz jakiś dziwnych rzeczy z PC4, jak masz zrobione pullup I2C ?
  • #3 14526186
    marcin w
    Poziom 22  
    Eagle napisał:
    Nie robisz jakiś dziwnych rzeczy z PC4, jak masz zrobione pullup I2C ?

    Piny które są używane przez uC jako TWI są wyprowadzone tylko do złącza magistrali I2C, podciągnięte do Vcc rezystorami 4,7K. Nie ma na nich nic innego co mogłoby zakłócić transmisję, moduł z układem podpinam przewodami o długości 10cm. Przy częstotliwości 100kHz w tych warunkach jak najbardziej to powinno pracować, na oscyloskopie nie widać większych zniekształceń zboczy związanych z pojemnościami magistrali.

    Procesor pracuje z częstotliwością 16MHz, TWI z częstotliwością 100kHz.
  • #4 14526545
    Andrzej__S
    Poziom 28  
    marcin w napisał:
    Wydaje mi się że po bajcie zawierającym SLA+W brak potwierdzenia ACK.

    Zgadza się, jednak powinieneś to sprawdzać, czy otrzymałeś potwierdzenie od układu slave. Można to sprawdzić w rejestrze TWSR mikrokontrolera po wysłaniu adresu na magistralę. Układ slave może być zajęty innymi operacjami i nie odpowiedzieć bitem potwierdzenia. W takim przypadku nie można kontynuować transmisji następnego bajtu. Należy wysłać na magistralę STOP i ponowić całą transmisję później lub REPEATED START i ponowić transmisję od razu (zaczynając ponownie od adresu).

    Zakładam, że pin PS układu MS5611 masz podłączony do Vcc, aby korzystać z interfejsu I2C. Istotne jest jednak także to, jak podłączyłeś CSB. Nie korzystałem nigdy z tego układu, ale z dokumentacji wynika, że jego jego adresowanie może być nieco mylące, bo w adresie jest zawarta zanegowana wartość CSB, czyli jeśli podłączyłeś go do GND, to adres będzie 0xEE, a nie 0xEC.

    marcin w napisał:
    Przy częstotliwości 100kHz w tych warunkach jak najbardziej to powinno pracować, na oscyloskopie nie widać większych zniekształceń zboczy związanych z pojemnościami magistrali.

    IMHO mimo wszystko do celów testowych lepiej używać mniejszych prędkości. Jak wszystko zagra, to zawsze można później zwiększyć.
  • #5 14526594
    excray
    Poziom 41  
    Dlaczego do rejestru TWCR dobierasz się przez OR?! Skoro nie wszystkie bity w nim są "Write"! Po co w ogóle używasz operacji OR na tym rejestrze skoro przepisywanie do niego tego co tam znajdziesz przed zapisem nowych danych to proszenie się o kłopoty?
  • #6 14527671
    marcin w
    Poziom 22  
    Andrzej__S napisał:
    Zgadza się, jednak powinieneś to sprawdzać, czy otrzymałeś potwierdzenie od układu slave.

    Wstawiłem takie pułapki po bicie startu i bajcie danych, co dziwne już po bicie startu rejestr statusu wskazuje na błąd. Być może problem leży w podwójnym podciąganiu, na moim module umieściłem rezystory podciągające, jak i również ze schematu modułu GY-86 wynika że też są rezystory podciągające.

    ATMEGA 8 - Jak wysłać bajt danych przez TWI? Samodzielnie napisane funkcje

    Te dwa rezystory dają ~2,3 kochm.

    excray napisał:
    Dlaczego do rejestru TWCR dobierasz się przez OR?

    Po wielu próbach zastosowałem OR, by sprawdzić czy tu w tym miejscu na pewno jest poprawnie, pierwotna wersja wyglądała
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W pierwszej kolejności spróbuję się połączyć z pamięcią 24C16 na I2C, ona pracuje zasilana bezpośrednio z 5V więc nie potrzebuje dodatkowych konwerterów napięć 5/3,3.
  • #7 14527767
    BlueDraco
    Specjalista - Mikrokontrolery
    A mi najbardziej podoba się użycie typu uint64_t w funkcji I2C_init. Ciekawe, jaki procent całej pamięci zajmują procedury arytmetyki 64-bitowej i z jakiego powodu do wyliczenia 8-bitowej wartości całkowitej potrzebujemy zakresu ok. 10^19... ;)

    A tak na poważnie, to błędu szukałbym najpierw w błędnym użyciu OR, a potem w sprzęcie.
  • #8 14527818
    marcin w
    Poziom 22  
    BlueDraco napisał:
    A mi najbardziej podoba się użycie typu uint64_t w funkcji I2C_init. Ciekawe, jaki procent całej pamięci zajmują procedury arytmetyki 64-bitowej i z jakiego powodu do wyliczenia 8-bitowej wartości całkowitej potrzebujemy zakresu ok. 10^19... :wink:

    Dla bit rate I2C równego 100kHz wartość rejestru TWBR powinna mieć wartość 72 przy założeniu że prescaler równy jest 1. W sytuacji kiedy do funkcja ustalająca na starcie częstotliwość miała postać
    void i2c_init(uint8_t speed)
    to do rejestru trafiała wartość 248.
    Ale użycie typu 64-bitiwego do obliczenia baud rate nie jest powodem niedziałania twi.

    BlueDraco napisał:

    A tak na poważnie, to błędu szukałbym najpierw w błędnym użyciu OR, a potem w sprzęcie.

    W pierwszej wersji tak było, nie działało więc czepiałem się wszystkiego. Zmieniłem m.in to, potem już pisząc post wrzuciłem tą właśnie zawartość. Bit startu na załączonym wyżej screenie wygląda poprawnie, SDA opada gdy SCL jest jeszcze w poziomie wysokim. A tu już po bicie startu status wskazuje na nieudany start. Bez znaczenia czy zmian dokonuję w rejestrze przez OR czy nie.
  • #9 14528518
    Andrzej__S
    Poziom 28  
    marcin w napisał:
    Bit startu na załączonym wyżej screenie wygląda poprawnie, SDA opada gdy SCL jest jeszcze w poziomie wysokim.

    Ale sprawdzałeś to po obydwu stronach konwertera?
    Najlepiej sprawdzić bezpośrednio na układzie slave.

    Po obejrzeniu schematu zaglądnąłem do datasheet modułu BMP085 i widzę coś takiego:
    Bosch napisał:
    The LSB of the device address distinguishes between read (1) and write (0) operation, corresponding to address 0xEF (read) and 0xEE (write).

    więc jednak nie 0xEC, chyba że coś zmieniałeś na module.

    marcin w napisał:
    Bez znaczenia czy zmian dokonuję w rejestrze przez OR czy nie.

    Nawet jeśli w tej chwili pozornie to nic nie zmienia, to i tak zdecydowanie popieram to, co powiedzieli Ci koledzy wcześniej - powinno być samo "=" bez OR. Wcześniej tego nie zauważyłem :( Chyba za bardzo skoncentrowałem się na samym przebiegu.

    Niezależnie od wszystkiego, jeśli przebieg na magistrali (ten występujący bezpośrednio na pinach układu slave) jest prawidłowy, to układ slave powinien wysłać bit potwierdzenia, chyba że adres jest nieprawidłowy, układ slave jest zajęty lub nieprawidłowo podłączony (np. w tym przypadku pin XCLR w stanie niskim).
  • #10 14529096
    marcin w
    Poziom 22  
    Andrzej__S napisał:
    Najlepiej sprawdzić bezpośrednio na układzie slave.

    Ale na tym układzie będzie ciężko, ze względu na miniaturyzację modułu.

    Udało mi się w końcu nawiązać komunikację po TWI, jak Andrzej napisał wyżej adres układu plus write to 0xEE. Tutaj popełniłem błąd dokładnie nie doczytując datasheetu a opierając się na informacjach zaczerpniętych z innej biblioteki. Teraz przebieg wygląda tak

    ATMEGA 8 - Jak wysłać bajt danych przez TWI? Samodzielnie napisane funkcje

    Widać odpowiedź od slave w postaci bitu ACK.

    Ale dla testu wykonałem również wysłanie adresu 0xEC, i tu jedyną różnicą było brak bitu potwierdzenia. Drugi bajt danych przeszedł po magistrali.

    ATMEGA 8 - Jak wysłać bajt danych przez TWI? Samodzielnie napisane funkcje

    Dokonałem jednej drobnej modyfikacji sprzętowej - pullupy zwiększyłem do 5,6kochm, nie wiem czy to właściwie nie rozwiązało mojego problemu, na pewno nie pozbycie się OR na TWCR, tu dla prób wstawiłem

    TWCR |= (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

    i również funkcjonalność nie zmieniła się. W poprzednim rozwiązaniu na początku drugiego bajta danych transmisja urywała się całkowicie.

    I z kontrolą statusu w TWSR po bitach startu jak i transmisji bajta danych również wykonałem wielką pomyłkę dwukrotnie negując w warunku if.
REKLAMA