-         

Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 23

Thema: [I²C] Beschleunigungssensor gibt kein ACK aus

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419

    [I²C] Beschleunigungssensor gibt kein ACK aus

    Anzeige

    Hallo!

    Also, ich habe da ein Problem.
    Ich habe ein Beschlunigungssensor Modul von ELV mit einem BMA020 an einen atmega 32 angeschlossen.
    Über den I²C bus.
    Das Teil hat schon 10K pullup widerstände drauf.
    Sonst habe ich keine pull ups.
    Das Teil sendet aber kein Acknowledgment, also SDA wird am Ende nicht low.
    Könnt ihr euch das mal ansehen?
    Mein gut komemntierter code

    Code:
     
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    #define F_CPU 1000000UL  
    #define BAUD 1200UL      // Baudrate
    #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
    #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
    #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
     
    #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
      #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
    #endif  
    #include <util/delay.h>
    int zahl = 0;
    
    void uart_init(void)
    {
      UBRRH = UBRR_VAL >> 8;
      UBRRL = UBRR_VAL & 0xFF;
     
      UCSRB |= (1<<TXEN) | (1<<RXEN);  // UART TX und RX einschalten
      UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
    } 
    void uart_write (char eingabe[40]) //funktion um strings auszugeben
    {
    while (eingabe [zahl] != 0)
    {
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich                   */
        {
        }
     
        UDR = eingabe[zahl];
     zahl ++;  
     }    
    zahl = 0;
    }
    uint8_t uart_getc(void)
    {
        while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
            ;
        return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
    } 
    
    int main (void)
    {
    
    uart_init (); 
    
    DDRC  &= ~(1<<PC1); 
    if (PINC & (1<<PINC1))
    {uart_write("High");}
    DDRC = 0xFF;
    PORTC &=  ~(1 <<PC0) | (1<<PC1); //SCL und SDA auf LOW 
    DDRC  &= ~(1<<PC0) | (1<<PC1);   //SCL und SCA als Eingang also high
    DDRC = (1 <<PC1); //SDA low (starbedingung2) [ecvnetuell pause davor]
    //01110000
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl high 1.bit
    DDRC &= ~(1 <<PC1); //SDA high
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl high 2.bit
    DDRC = (1 <<PC0); //SCL low
    DDRC  &= ~(1<<PC0);//SCl high 3.bit
    DDRC = (1 <<PC0); //SCL low
    DDRC  &= ~(1<<PC0);//SCl high 4.bit
    DDRC =(1 <<PC1);   //SDA low
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl high 5.bit
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl high 6.bit
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl hogh 7.bit
    DDRC = (1 <<PC0);  //SCL low
    DDRC  &= ~(1<<PC0); //SCl high 8.bit
    
    DDRC  &= ~(1<<PC1); 
    if (!(PINC & (1<<PINC1)))
    { uart_write ("low");}
    else
    { uart_write ("high2");}
    while(1)
    {
    }
    }
    Ich ahbe den gnazen Code gepostet, weil der fehler ja überalls ein könnte.
    Aber der wichtige Teil sit unten.
    Zuerst kommt die Startbedingung, dann wird die Adresse übertragen und dann wird das ACK geprüft.
    Aber das ist bei mir immer High.
    Wenn ich die pullups wegmache, dann ist es low, nur so als Test.

    Für Antworten wäre ich sehr Dankbar.

    Gruß

    Olaf

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    Hallo,
    am Code fällt mir auf, dass du zur Ausgabe auf SDA/SCL immer auf DDRC schreibst, damit schaltest du aber immer nur von Eingang auf Ausgang und umgekehrt. Müsste wohl PORTC heißen Und wahrscheinlich läuft das auch viel zu schnell ab (1Mhz Takt und beim Setzen hast du keine Pausen o.ä., evtl kommt der Sensor nicht mit).

    Ich würde dir empfehlen, unbedingt das integrierte TWI-Modul (I2C) im Atmega zu verwenden, das ist viel einfacher und komfortabler, als immer die Pins selber setzen zu müssen. Das TWI-Interface ist ja genau an den beiden Pins, die du verwendest (PC0,PC1). Außerdem lassen sich bei der Übertragung Fehlercodes auslesen (z.B. ob ACK fehlt) - noch ein Vorteil

    Ohne Pullup-Widerstände kann kein High-Pegel erreicht werden, da jeder Teilnehmer nur open-Collector/open-Drain-Ausgänge hat (d.h. jeder Busteilnehmer kann nur auf Low ziehen oder hochohmig sein, im hochohmigen Zustand ziehen die Pullups den Pegel auf High; schützt vor Kurzschlüssen)
    Grüße, Bernhard

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Hallo Bernhard!

    Danke für die schnelle Antwort.
    Auch wenn ich mit Google so einiges zum TWI modul finde, so hilft es mir nicht wirklich weiter.
    Da steht zwar, welche Register man setzen muss und so, aber nicht wie man das jetzt genau in C umsetzt.
    Kennst du vielleicht eine gute Anleitung?

    Gruß
    Olaf

  4. #4
    Erfahrener Benutzer Roboter-Spezialist Avatar von -schumi-
    Registriert seit
    30.12.2009
    Ort
    Wasserburg am Inn / Bayern
    Alter
    23
    Beiträge
    449
    Du musst die Namen der Register einfach wie eine Variable benutzen

    Da kannst du dann (bei den meisten) reinschreiben wie du willst, lesen und auch logisch miteinander verknuepfen usw. Also genauso benutzen, wie du z.B PORTA benutzt.

    (PORTB, DDRC, PINA usw. sind auch alles nur Register)

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Danke,
    jetzt weiß ich endlich mal, wie man Register richtig verwendet
    Also um zum beispiel das Interrupt Flag zu setzen müsste ich:
    TWCR =| (1<<TWINT);
    schreiben?

    Ich bin aber gerade auf noch ein Problem gestoßen.
    Also.
    Beim I²C soll man ja nicht den Pin vom atmega High machen sondern den einfach als Eingang setzen und den Pull up widerstand die Arbeit amchen lassen.
    Das problem ist nun:
    Wenn ich einfach mal
    DDRC = (1 <<PC0); //SCL low
    [12:34:49] crabtack: PORTC &= ~(1 <<PC0) | (1<<PC1);
    mache, dann ist der Pin immernoch high.
    Der ganze Port ist high.
    Was amche ich falsch?

    Gruß
    Olaf

  6. #6
    Erfahrener Benutzer Begeisterter Techniker Avatar von schorsch_76
    Registriert seit
    25.03.2012
    Ort
    Kurz vor Neuschwanstein
    Alter
    41
    Beiträge
    398
    Was mir noch auffällt, bzw als Verbesserungsvorschlag. Mach dir Makros wie

    #define sda_to_high() (PXYZ |= (1<<PXY))
    #define sda_to_low() (PXYZ &= ~(1<<PXY))

    dann erscheint der code leserlicher und du bist sicher, dass du immer bei SDA/SCL whatever das gleiche register beschreibst


    Gruß
    Georg

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Danke,
    Makros werden vor allem den Code meienr Binäruhr übersichtlicher machen.
    Für das Momentane Problem bringen sie aber ncihts, da ich ejtzt das TWI Modul vom atmega nutzen möchte.

    Was ich aber nicht verstehe ist, wie das mit dem ACK funktioniert.
    Wann liest er das ACK aus und wo kann ich nachgucken, ob es ein ACK gab oder nicht?

    Gruß
    Olaf

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von crabtack Beitrag anzeigen
    ... TWI modul ... wie man das jetzt genau in C umsetzt ... eine gute Anleitung? ...
    Hi Olaf,

    der Sternthaler hatte GENAU für den BMA020 hier (klick) Codeschnippsel in C in seinem bewährten, sauberen Form zum Auslesen vorgelegt. Ich hatte das weitergeführt und im gleichen Thread ein paar Seiten weiter meine Subroutine (klick) zum Auslesen des BMA020 gepostet. Meine I²C-Routine basiert auf der Bibliothek von P.Fleury. Die Sache läuft bei mir recht ordentlich, siehe klick.

    Vielleicht hilft Dir dies und die sonstigen Postings im zitierten Thread.

    Viel Erfolg.
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Hallo Oberallgeier!

    Danke für deine Antwort.
    Allerdings würde ich am liebsten keine fertige LIB nutzen, das wäre dann die Notlösung.
    Aber eigentlich muss nurnoch das ACK Problem gelöst werden

    Gruß
    Olaf

  10. #10
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    Hallo,
    soweit ich weiß, gibt ein I2C-Slave ein ACK, wenn er seine Adresse erkannt hat bzw. noch weitere Daten entgegennehmen will/kann.
    Irgendetwas stimmt noch nicht, sonst würde sich der Slave ja melden

    Wenn du das integrierte TWI-Modul verwendest (was ich dir wirklich nocheinmal ans Herz legen möchte, ich meine es ja nur gut ), kannst du im Register TWSR nachschauen, ob ein ACK angekommen ist (Datenblatt Seite 186, z.B. Code $38 oder $48 ).
    Infos zum TWI/I2C im Datenblatt gibt es ab Seite 167; konkret wird es ab Seite 175.

    Grüße,
    Bernhard
    Geändert von BMS (31.03.2012 um 17:05 Uhr)

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. DCF77 gibt kein Signal
    Von .:markus:. im Forum Elektronik
    Antworten: 13
    Letzter Beitrag: 06.08.2010, 18:10
  2. Beschleunigungssensor
    Von oratus sum im Forum Sensoren / Sensorik
    Antworten: 12
    Letzter Beitrag: 01.11.2009, 01:31
  3. Beschleunigungssensor
    Von bastman im Forum Sensoren / Sensorik
    Antworten: 3
    Letzter Beitrag: 01.11.2006, 09:53
  4. MyAVR- Board gibt kein masse
    Von senk im Forum AVR Hardwarethemen
    Antworten: 49
    Letzter Beitrag: 03.11.2005, 20:48
  5. Beschleunigungssensor
    Von BlackBroom im Forum Sensoren / Sensorik
    Antworten: 1
    Letzter Beitrag: 14.07.2005, 21:52

Berechtigungen

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