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

[C][AT90CAN128][I2C] Czujnik temperatury AD7416 i komunikacja I2C

31 Maj 2011 14:12 2630 15
  • Poziom 10  
    Witam,
    Mam problem z komunikacją pomiędzy mikroprocesorem AT90CAN128, a 10-bitowym czujnikiem AD7416 od Analog Devices.

    PDF czujnika: [ Link ]
    PDF procesora: [ Link ]

    Korzystałem z książki dot. I2C, ale prosiłbym o sprawdzenie poprawności inicjalizowania komunikacji, wysyłania początkowych parametrów transmisji i całej instrukcji odczytu danych z bufora.

    Na oscyloskopie widać jedynie taktowanie zegara, a na drugim kanale (linii SDA) niestety nic.

    Jeszcze pytanie, czy korzystają z TWI muszę ustawić kierunek przepływu danych na porcie za pomcą DDRx?

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Tektronix
  • Pomocny post
    Poziom 25  
    Witam (ponownie :wink:),

    z całym szacunkiem ale czy to my mamy za kolegę czytać te datasheet-y? :roll:
    W opisie funkcji dodatkowych pinów portów jest jasno napisane:

    Cytat:
    SDA, Two-wire Serial Interface Data. When the TWEN bit in TWCR is set (one) to enable the
    Two-wire Serial Interface, pin PD1 is disconnected from the port and becomes the Serial Data
    I/O pin for the Two-wire Serial Interface. In this mode, there is a spike filter on the pin to suppress spikes shorter than 50 ns on the input signal, and the pin is driven by an open drain driver
    with slew-rate limitation

    To samo się tyczy PD0/SCL...

    Poza tym, kolega nie pokazał schematu układu (zakładam, że to ta sama płytka co ostatnio więc raczej mam odpowiednie pull-up'y zainstalowane, ale proszę to sprawdzić, jeśli nie ma można użyć wewnętrznych pull-up'ów - o tym też jest napisane w PDF'ie na pewno)


    Pozdrawiam,
    GSM
  • Tektronix
  • Poziom 10  
    GSM napisał:
    Witam (ponownie :wink:),

    z całym szacunkiem ale czy to my mamy za kolegę czytać te datasheet-y? :roll:
    W opisie funkcji dodatkowych pinów portów jest jasno napisane:

    Cytat:
    SDA, Two-wire Serial Interface Data. When the TWEN bit in TWCR is set (one) to enable the
    Two-wire Serial Interface, pin PD1 is disconnected from the port and becomes the Serial Data
    I/O pin for the Two-wire Serial Interface. In this mode, there is a spike filter on the pin to suppress spikes shorter than 50 ns on the input signal, and the pin is driven by an open drain driver
    with slew-rate limitation

    To samo się tyczy PD0/SCL...

    Poza tym, kolega nie pokazał schematu układu (zakładam, że to ta sama płytka co ostatnio więc raczej mam odpowiednie pull-up'y zainstalowane, ale proszę to sprawdzić, jeśli nie ma można użyć wewnętrznych pull-up'ów - o tym też jest napisane w PDF'ie na pewno)


    Pozdrawiam,
    GSM

    Witam :),
    dzięki za odpowiedź i zainteresowanie się tematem.

    Doczytałem w sprawie ustawiania DDRx itd. oraz sprawdziłem na oscyloskopie, że odłączany jest PD1/PD0 krótko po tym jak opublikowałem post. Nic dodatkowego nie jest podłączone aktualnie pod PD0 i PD1 które obsługują SDA i SCL, tylko sam czujnik.

    W czujniku linie SDA i SCL podpięte do mikrokontrolera, A1 i A2 do masy,
    A0 do Vcc oraz VCC i GND podłączone do zasialnia.

    Sekwencja pierwsza w odbieraniu danych do bufora wywoływana w pętli tzn. 0x96 oznacza 10011100 (1001 zawsze wystepuje, potem 11 które są zwarte oraz 00 na końcu), druga 0x00 to rejestr do odczytu temperatury, do niego muszę się dostać i wyciągnąć dane.

    Rezystory podciągające sa ustawione, tzn. obie zworki wsadzone, zatem "aktywują" rezystory pull-up 4,7k.
    Płyta z mikrokontrolerem [ Link ]
  • Pomocny post
    Poziom 25  
    Tak przy okazji, sugeruję odczyt TWSR po każdej operacji, nota też to zaleca :wink:

    Znowu muszę za kolegę czytać PDF'y :roll:
    Czujnik ma w datasheet'cie napisane, że szybciej niż 400kHz nie pociągnie (SCL), a twój program nie ustawia TWBR ani TWPS, więc w teorii zegar TWI ma wartość 500kHz.
    Nie ładnie popełniać takie błędy - proszę poprawić.

    Pozdrawiam,
    GSM
  • Poziom 10  
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Faktycznie, odczyt teraz ruszył (ustawiłem prędkość w ports() ), ale kolejny problem to to, że przychodzą dane do TWDR w następujący sposób najpierw 8 bitów ustawionych na 1F, a potem kolejne 8 bitów ustawionych na FF (z czego 2 pierwsze powinny być do temperatury). Wydaje mi się, że tym razem przczytałem dokładnie ustawienia, ale jeszcze coś mi umknęło. Co to może być?
  • Pomocny post
    Poziom 25  
    Witam,

    Rejestru ustawień kolega nie mógł odczytać, bo to oznaczałoby, że układ jest trybie Power Down.
    Jeśli się nie mylę to wynik otrzymany przez kolegę oznaczałby ~31,6C, brzmi sensownie biorąc pod uwagę ostatnie upały :D

    Taki drobny acz istotny szczegół, z PDF'a:
    Cytat:
    A stop command must be inserted at the end of the read
    communication. If a stop command is not inserted by the
    master and the AD7416/AD7417/AD7418 receive more SCL
    cycles than the maximum needed for three bytes of data,
    then the I2C interface on the AD7416/AD7417/AD7418 pulls the
    SDA line low and prevents it from going high again. To recover
    the AD7416/AD7417/AD7418 interface, the part must be
    powered off and on again.


    Pozdrawiam,
    GSM
  • Poziom 10  
    Gdzie konkretnie należy tego stop'a umieścić, bo wrzucając do funkcji odczytującej pod koniec program zatrzymuje się na linii
    Code:
    ...while (!(TWCR&(1<<TWSTO)));...

    W tej chwili gdy program przeleci cały (bo nie mam go w pętli while) otrzymuję w rejestrze TWDR kolejno 0x92 (adres czujnika - odpowiednio zwarte piny), 0x00 (oznacza rejestr odczytu z sensora), 0x93 (ustawiamy slave'a ze bedziemy czytac), 0x1F...0xFF - i tutaj ta zła temperatura. Po podgrzaniu dostaję 3F. Czyli duży przeskok. Czujnik jest na 100% sprawny.
  • Pomocny post
    Poziom 25  
    Witam,

    tak jak w zacytowanym fragmencie, po dokonaniu odczytu, czyli na końcu read_buf...

    Poza tym, raz jeszcze zasugeruję, sprawdzanie TWSR i kodów błędów, a nóż widelec coś ważnego tam jest :wink:

    Pozdrawiam,
    GSM
  • Poziom 10  
    GSM napisał:
    Witam,

    tak jak w zacytowanym fragmencie, po dokonaniu odczytu, czyli na końcu read_buf...

    Poza tym, raz jeszcze zasugeruję, sprawdzanie TWSR i kodów błędów, a nóż widelec coś ważnego tam jest :wink:

    Pozdrawiam,
    GSM


    Dodałem na samym końcu. Myślałem, że gdzieś wcześniej jeszce trzeba w funkcji odcztującej. Tylko tak jak wyżej wyedytowałem, nie ma to znaczenia, bo program przeleci raz, bo nie mam w pętli tego odczytu, więc ta funkcja stop() wykona się na samym końcu.

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 25  
    To co napisałem o STOPie nie miało związku z twoim aktualnym problemem, była to po prostu rada, która rozwiąże kolejny problem jaki byś miał - zawieszający się czujnik.

    Co do komunikacji z układem, co z odczytem/zapisem pozostałych rejestrów? Spróbuj, może to ci pomoże znaleźć źródło problemu.

    Pozdrawiam,
    GSM
  • Poziom 10  
    GSM napisał:
    To co napisałem o STOPie nie miało związku z twoim aktualnym problemem, była to po prostu rada, która rozwiąże kolejny problem jaki byś miał - zawieszający się czujnik.

    Co do komunikacji z układem, co z odczytem/zapisem pozostałych rejestrów? Spróbuj, może to ci pomoże znaleźć źródło problemu.

    Pozdrawiam,
    GSM

    Ahhhha :) No w sumie racja. Komunikację należy przerwać.

    Co do rejestru TWSR. Nie za bardzo wiem, jak mam odczytać i wywnioskować co może być nie tak na podstawie zawartości tego rejestru. Niby na stronie 218, czyli "Status Codes for Master Transmitter Mode" można coś wydedukować, ale nadal w całość tego złożyć nie mogę.

    Generalnie przebiega to tak

    START -> 0xF8
    następnie po linii
    Code:
    void TWI_start(void) {
    
              TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);

    jest 0x08,
    następnie po linii
    Code:
         void TWI_write(uint8_t bajt){
    
              TWDR = bajt;
              TWCR=(1<<TWINT)|(1<<TWEN);

    jest 0x18
    dalej w tej samej linii jest 0x28, czyli w nastepnym zapisie
    potem wywołanie kolejnego TWI_start 0x10, następnie 0x40 i 0x50

    zatem podsumowując:

    Code:
    0x08 A START condition has been transmitted
    
    0x18 SLA+W has been transmitted; ACK has been received
    0x28 Data byte has been transmitted; ACK has been received
    0x10 A repeated START condition has been transmitted
    0x40 SLA+R has been transmitted; ACK has been received
    0x50 Data byte has been received; ACK has been returned


    wydaje się ok :(
  • Poziom 25  
    Wszystko wydaje się być w porządku, wartości TWSR potwierdzają, że wszystkie operacje przebiegły prawidłowo (strona 218 i 222 noty katalogowej mikrokontrolera).

    Spróbuj odczytać/zapisać inne rejestry czujnika, np. konfiguracyjny i pokaż co zwrócił.

    Pozdrawiam,
    GSM
  • Poziom 10  
    GSM napisał:
    Wszystko wydaje się być w porządku, wartości TWSR potwierdzają, że wszystkie operacje przebiegły prawidłowo (strona 218 i 222 noty katalogowej mikrokontrolera).

    Spróbuj odczytać/zapisać inne rejestry czujnika, np. konfiguracyjny i pokaż co zwrócił.

    Pozdrawiam,
    GSM


    Odczytałem 0x01, czyli konfiguracyjny i dostaję 0x00, a z 0x02 -> 0x7F 0xFF
    [C][AT90CAN128][I2C] Czujnik temperatury AD7416 i komunikacja I2C
  • Poziom 25  
    Strona 19 dokumentacji czujnika, czy wszystko jest spełnione?

    Pozdrawiam,
    GSM
  • Poziom 10  
    0x01 -> 0x00 0x00
    0x02 -> 0x7F 0xFF
    0x03 -> 0x7F 0xFF
    0x04 -> 0xFF 0xFF
    0x05 -> 0x00 0x00

    czyli nie są default'owe.

    Przy próbie zapisu tych wartości do każdego z rejestrów zawiesza się na TWI_stop(); już przy pierwszym 0x00
  • Poziom 25  
    Przy próbie zapisu, gdy wiesza się na STOP, jakie wtedy wartości ma TWSR w trakcie przebiegu całej operacji?

    Tak nawiasem mówiąc, twój czujnik nie ma rejestru 0x05 :roll:

    Pozdrawiam,
    GSM