-
        

Ergebnis 1 bis 7 von 7

Thema: I2C Funktioniert nicht mit Atmega8

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    17.07.2005
    Ort
    Oberwil
    Alter
    36
    Beiträge
    131

    I2C Funktioniert nicht mit Atmega8

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hallo

    Mein I2C Bus tut nicht so wie er sollte. Hardwaremässig sollte alles I.o. sein. Habe die beiden Leitungen SDA/SCL via je 10kOhm Widerstände gegen 1% Volt gezogen. Meinen I2C Bus benötige ich um meine RTC PCF8583 zu steuern.

    Aber da will überhaupt nichts gehen.


    Hier mein Code:
    /************************************************** ********
    Function: Initialisiert die I2C Schnittstelle:
    - TWI enable
    - Baud-Rate: 25kHz
    Input: NOP
    Output: NOP
    ************************************************** ********/
    void init_I2C(void)
    {

    TWBR = 12; //Baud-Rate
    TWSR = 0; /* no prescaler */

    }

    /************************************************** ********
    Function: wait for TWINT Flag set. This indicates that
    the START condition has been transmitted
    Input: NOP
    Output: NOP
    ************************************************** ********/
    void wait_for_ACK(void)
    {
    while (!(TWCR & (1<<TWINT)));
    }

    /************************************************** ********
    Function: Send one byte to I2C device

    Input: byte to be transfered
    Output: 0 write successful
    1 write failed
    ************************************************** *********/
    unsigned char i2c_write( unsigned char data )
    {
    uint8_t twst;

    // send data to the previously addressed device
    TWDR = data;
    TWCR = (1<<TWINT) | (1<<TWEN);

    // wait until transmission completed
    wait_for_ACK();

    // check value of TWI Status Register. Mask prescaler bits
    twst = TW_STATUS & 0xF8;
    if( twst != TW_MT_DATA_ACK) return 1;

    return 0;
    }

    /************************************************** ***********************
    Function: Terminates the data transfer and releases the I2C bus

    Input: NOP
    Output: NOP
    ************************************************** ***********************/
    void i2c_stop(void)
    {
    /* send stop condition */
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

    // wait until stop condition is executed and bus released
    wait_for_ACK();

    }/* i2c_stop */

    /************************************************** **************************************
    Function: Issues a start condition and sends address and transfer direction.

    Input: Device Address + Direction
    Output: return 0 = device accessible,
    1= failed to access device
    ************************************************** **************************************/
    unsigned char i2c_start(unsigned char address)
    {
    uint8_t twst;

    // send START condition
    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

    // wait until transmission completed
    wait_for_ACK();

    // check value of TWI Status Register. Mask prescaler bits.
    twst = TW_STATUS & 0xF8;
    if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

    // send device address
    TWDR = address;
    TWCR = (1<<TWINT) | (1<<TWEN);

    // wail until transmission completed and ACK/NACK has been received
    wait_for_ACK();

    // check value of TWI Status Register. Mask prescaler bits.
    twst = TW_STATUS & 0xF8;

    if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

    return 0;

    }/* i2c_start */

    Was ist an meiner Software falsch? Wie kann ich mit dem Osziloskop überprüfen ob mein I2C Bus funktioniert? Als vielleicht über den SCL Pin
    Wie muss ich die Datenrichtungsregister für den Atmega8 konfigurieren wenn ich den I2C benutze?

    Danke.

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Alter
    48
    Beiträge
    2.731
    Hallo,
    wenn Du TWI benutzt, musst Du dich nicht um die Richtungsregister kümmern, das TWI-Modul macht das alles selber.

    Damit der Leitungspegel passt, muss das TWI-Modul immer in einem bestimmten Status sein, bzw. auf die richtige Aktion reagieren damit es weitergeht, und der AVR nicht den Bus blockiert.

    Wenn Du was messen willst,
    wenn nix los ist, müssen beide Leitungen high sein, wenn Daten übertragen werden kann man auf der Taktleitung SCL alle Bits incl. ACK/NACK rauszählen, also 9 Takte pro Byte. Auf der Datenleitung sieht man das entsprechende Datenbyte, wenn mehrere 0-Bits kommen, ist die Leitung eben solange low.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    17.07.2005
    Ort
    Oberwil
    Alter
    36
    Beiträge
    131
    Ok ich habe das heute Abend noch kurz überprüft und wenn nichts läuft, so scheint es, sind sowohl SCL und SDA beide auf Hight. Vielleicht muss ich mal eine Datenübertragung mittels Logic Analyser messen.

    Dann kann ich wahrscheinlich davon ausgehen, dass mein I2C Bus also funktioniert. Hast du keine Fehler in meinem Code entdeckt?

    Dann habe ich aber noch mein Problemchen mit der RTC.

    Wenn ich nun etwas auf die RTC schreiben will mache ich das folgendermassen:

    i2c_start(RTC_sla_addr+I2C_Write);
    i2c_write(Alarm_Control_Register_addr);
    i2c_write(0x4A);
    i2c_stop();

    wobei RTC_sla_addr die Adresse des RTC ist.

    Oder sitmmt hier noch etwas nicht?

    Vielen Dank!!!

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Alter
    48
    Beiträge
    2.731
    Vom Prinzip her sollte es gehen, Du hast aber keine Funktion um vom Slave zu lesen !
    Beim InitI2C sollte TWI schon mal aktiviert werden, sonst kann's evtl. passieren, das der Pegel rauf- oder runtergezogen wird, was sich aber nur negativ auswirkt, wenns mehr als einen Master gibt.

    Bei einem Fehler nicht einfach die Funktion mit return verlassen, sondern das TWI-Modul in einen definierten Zustand bringen, auch wenn ein Start nicht geklappt hat, muss man irgendwelche Flags setzen damit der Bus nicht blockiert wird.

    Du kannst das Prinzip aber auch mit dem Bascom Programm vergleichen aus dem Wiki (-> TWI-Praxis).
    Man kann auch auf diversen Seiten abschauen wie zB.
    http://www.nongnu.org/avr-libc/user-...twi__demo.html

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    17.07.2005
    Ort
    Oberwil
    Alter
    36
    Beiträge
    131
    Das hat eigentlich einen simplen Grund, da ich die RTC nur als Timer verwene brauche ich nichts zu lesen. Vielleicht muss ich diese Methode aber no regänzen damit ich besser debuggen kann.

    Wie meinst du das mit einen definierten Zustand bringen? Wahrscheinlich ist es schon so, dass mein Bus blockiert ist, weil etwas schief gegangen ist bei der Übertragung.

    Sonst weiss ich nichts mehr, was falsch ist.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Alter
    48
    Beiträge
    2.731
    Auch wenn ein Fehler aufgetreten ist, muss man dem TWI sagen wie es weitergeht, bzw. man setzt es zurück, sonst klappt auch nicht nächste Sendung (Startsequenz) nicht.
    Auch wenn Du in C progst, kannst Du an den Bascom-Beipielen erkennen wie man der Reihe nach die Aktionen ausführen muss, um evtl. Fehler abzufangen. Und wie man das TWI danach wieder in Ausgangsstellung bringt.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    17.07.2005
    Ort
    Oberwil
    Alter
    36
    Beiträge
    131
    Ok habe jetzt mein System, wenns nicht klappen sollte, in einen definierten Zusatnd gebracht. Jedenfalls läuft es jetzt einwandfrei. Irgendwie war es aber trotzdem komisch das es vorher nicht ging. So viel habe ich nicht geändert.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •