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

[M32][C] TWI zawiesza się na TWCR i nie wszystko wysyła

Pawel1812 18 Sty 2010 01:23 1788 3
REKLAMA
  • #1 7552545
    Pawel1812
    Poziom 26  
    Witam
    Piszę program wpółpracujący z kilkoma urządzeniami I2C min z DS3232 i PCF8574. Obsługuję je za pomocą sprzętowego TWI. Program niestety okresowo się zawiesza, tym częściej im szybsze taktowanie MCU. Przy 1MHz czasem, przy 8MHz za każdym razem.
    Zbadałem, że zawieszanie następuje w pętli while w funkcji twistop()


    Znalazłem następujący tekst o tym zjawisku
    "Gdy ze względu na stan magistrali AVR nie potrafi wygenerować sygnału STOP, program zawiesza się w tym fragmencie. Zjawisko to nie występuje w sprawnym układzie, pod warunkiem nie wygenerowania zbędnych sygnałów stop przez samego użytkownika, dlatego nie rozwiązywałem go na poziomie biblioteki - wystarczający będzie Watchdog lub ręczne ograniczenie ilości obiegów pętli oczekującej."


    niestety, wyeliminowanie pętl while a wstawienie zamiast niej _delay_ms(10); powoduje nie wykonywanie wszystkich poleceń do pcf8574 szczególnie jak następuja szybko po sobie. Z kolei wprowadzenie powoduje zawieszanie. Na początku programu ustawiam TWBR=72; - bez rezultatu. Czy ktoś spotkał sie z takim problemem?

    Czy sama komenda

    na początku programu dostatecznie przy 4MHz spowolni i2C?
    Z góry dzięki za zainteresowanie tematem.
    Pozdrawiam


    
    #include "TWI.h"
    
    // procedura transmisji sygnału START
    void twistart(void)
    {
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    }
    
    // procedura transmisji sygnału STOP
    void twistop(void)
    {
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
    while ((TWCR & (1<<TWSTO)));
    }
    
    // procedura transmisji bajtu danych
    void twiwrite(char data)
    {
    TWDR = data;
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    }
    
    //procedura odczytu bajtu danych
    char twiread(char ack)
    {
    TWCR = ack 
    ? ((1 << TWINT) | (1 << TWEN) | (1 << TWEA)) 
    : ((1 << TWINT) | (1 << TWEN)) ;
    while (!(TWCR & (1<<TWINT)));
    return TWDR;
    }
    
  • REKLAMA
  • #2 7552973
    Kabuto15
    Poziom 19  
    Ogólnie nie powinno być takiego efektu przy obsłudze TWI (I2C). Ono ma działać i działa w odpowiednich warunkach niezawodnie. Najlepiej byłoby oczywiście obsługiwać TWI w przerwaniach. Wtedy uniknąłbyś pollingu (brak pętli czekających while).
    Możesz to obejść na około - zamiast while wstawić pętlę for z jakimś tam licznikiem timeoutu. Jeśli nie ustawi się dana flaga a przekroczony zostanie timeout generujesz błąd i wychodzisz z funkcji.
    Ale tak jak pisałem już wcześniej to wszystko powinno działać bez jakichkolwiek problemów. Jak możesz to napisz jeszcze jaką prędkością taktujesz TWI.
  • REKLAMA
  • #3 7555147
    Pawel1812
    Poziom 26  
    W tej chwili sttawione jest TWBR=64; a procesor 4MHz. Zjawisko to przeszkadza przy sterowaniu buzzera przez ekspander, który ma tylko piknąć. Bywa że buzzer przy szybkim pikaniu się nie załączy lub się nie wyłązy. Na tej podstawie twierdzę, że nie wszystkie polecenia do PCFa są dostarczane.

    Zawieszanie się ma miejsce szczególnie gdy od razu po operacji zapisu na I2C następuje odczyt.
  • #4 9061091
    ba2niedz
    Poziom 10  
    Po odczczytaniu danych wyślij dwukrotnie sygnał STOP() i powinno śmigać
REKLAMA