C XMEGA - TWI (I2C)

Dieses Thema im Forum "Software" wurde erstellt von Janiiix3, 29. März 2018.

  1. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Habe gerade Probleme bei dem konfigurieren einer I2C Kommunikation zwischen XMEGA und einem Slave.

    Um genau zu sein handelt es sich um einen "XMEGA256A3BU".

    Sehe ich das richtig, dass ich hiermit den Kommunikationskanal "öffne" zwischen Kontroller und Slave?


    CodeBox C und C++
    uint8_t twiStart( TWI_t *twi , uint8_t addr )
    {
       /*
       *   Slave Adresse senden
       */
       twi->MASTER.ADDR = addr;
     
       /*
       *   ACK oder NACK empfangen
       *   ACK       = 0
       *   NACK   = 1
       */
       return ( ( twi->MASTER.STATUS & 1<<TWI_MASTER_RXACK_bp ) >> TWI_MASTER_RXACK_bp );
    }
    


    Danach wollte ich mit


    CodeBox C und C++
    uint8_t twiReadNack( TWI_t *twi , uint8_t reg )
    { 
       /*
       *   Adresse übertragen
       */
         twi->MASTER.DATA   = reg;
       /*
       *   Warten bis Übertragung komplett ist
       */
         while( ! ( twi->MASTER.STATUS & TWI_MASTER_WIF_bm ) );
       /*
       *   Warten bis ein Byte empfangen wurde
       */
       while( ! ( twi->MASTER.STATUS & TWI_MASTER_RIF_bm ) );
     
       return (twi->MASTER.DATA); 
    }
    

    Ein Byte lesen und der Kontroller soll ein NACK senden, damit der Slave weiß er braucht keine weiteren Daten mehr zu schicken.

    Was mache ich verkehrt?

    Bei den 8´bittern habe ich bis jetzt immer mit


    CodeBox C und C++
    i2c_start()
    i2c_start_wait()
    i2c_rep_start()
    i2c_readAck()
    i2c_readNack()
    i2c_stop()
    


    Gearbeitet. Das wollte ich jetzt auf dem "xMega" nachbilden.
     
    #1 Janiiix3, 29. März 2018
    Zuletzt bearbeitet: 11. April 2018
  2. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    »gerade mal wieder« heißt das, Du hattest schon mal Probleme, die Du dann aber überwunden hast?

    Dann hättest Du also funktionierende Funktionen für einen Xmega, wenn auch für eine anderes Projekt, einen anderen Controller, einen anderen Slave.

    Würde mich mal interessieren, wie das geht. Habe I2C bisher nur mit den Funktionen des ASF, das mit Interrupts arbeitet, hingekriegt.

    Die I2C-lib von Peter Fleury funktioniert nur mit den Megas und Tinies und läßt sich nicht mit überschaubarem Aufwand an die Xmegas anpassen, da die hardwaremäßig ganz anders aufgebaut sind.
     
  3. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Aktuell habe Ich diese Routinen in Verwendungen zum lesen und schreiben.


    CodeBox C und C++
    void twiWrite( uint8_t reg, uint8_t data , uint8_t slaveAddr)
    {
       twi->MASTER.ADDR   = slaveAddr + TWI_WRITE;
       while(!(twi->MASTER.STATUS&TWI_MASTER_WIF_bm));
    
       twi->MASTER.DATA   = reg;
       while(!(twi->MASTER.STATUS&TWI_MASTER_WIF_bm));
    
       twi->MASTER.DATA   = data;
       while(!(twi->MASTER.STATUS&TWI_MASTER_WIF_bm));
       
       twi->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
    }
    
    uint8_t twiRead( uint8_t reg, uint8_t slaveAddr )
    {
       uint8_t ret = 0;
       
       twi->MASTER.ADDR = slaveAddr + TWI_WRITE;
       while( ! ( twi->MASTER.STATUS & TWI_MASTER_WIF_bm ) );
       twi->MASTER.DATA = reg;
       while( ! ( twi->MASTER.STATUS & TWI_MASTER_WIF_bm ) );
       twi->MASTER.ADDR = slaveAddr + TWI_READ;
       while( ! ( twi->MASTER.STATUS & TWI_MASTER_RIF_bm ) );
       
       ret = twi->MASTER.DATA;
       twi->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
    
       return ret;
    }
    


    Was mich daran stört ist halt das wenn ich jedes mal ein neues Byte einlesen möchte, muss ich wieder die Slave Adresse + Aktionsbit senden. Mit den Routinen von Peter F.
    konnte ich (so habe ich das verstanden..) eine Verbindung mit dem Slaven aufbauen (i2c_start(SLAVE_ADDR+AKTIONSBIT)) und danach halt lesen oder schreiben..
    Da war ich ziemlich flexibel und musste nicht ständig eine "neue" Verbindung aufbauen. Verstehst du mich ein wenig?
     
  4. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Mir ist der Ablauf noch nicht so bewusst. Im Datenblatt gibt es (siehe Bild), verschiedene "CMD"..
    Wann muss ich was machen?!
     

    Anhänge:

  5. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Und die funktionieren? Mit welchem Xmega? Mit welchem Slave?

    Die Variable twi ist unbekannt. Ist sie global definiert? Soll ich weiter rätseln?

    Ohne komplettes, compilierbares und funktionierendes oder den Fehler produzierendes Minimal-Projekt und allen sonstigen relevanten Angaben ist es schwierig, irgendetwas konkretes rauszufinden.
    Ein wenig. ;)

    Die Funktionen von Peter Fleury sind auf die Megas und Tinies zugeschnitten, da funktionieren sie wunderbar. Die I2C-Hardware der Xmegas ist für den Anwender so »vereinfacht«, daß man nicht mehr all alle Flags rankommt, daher können die Fleury-libs nicht mehr funktionieren, da sie direkten Zugriff darauf brauchen.
    Wenn ich das wüßte, hätte ich nicht das ASF gebraucht.

    Entweder habe ich die Beschreibung nicht richtig verstanden oder das Datenblatt ist fehlerhaft, wobei das zweite unwahrscheinlich ist, weil es für verschiedene Xmegas so beschrieben wird.
     
  6. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    @Mikro23
    Du kannst ja mal die 3 Funktionen ausprobieren wenn du magst.
    mit "twiInit( &TWIEx)" kannst du erstmal die Adresse deiner angeschlossenen Peripherie festlegen (also welche TWI Einheit genutzt werden soll).
    Die beiden anderen Funktionen sollten selbst erklärend sein. Bei mir funktionieren sie super.
     

    Anhänge:

  7. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Weißt Du, ich habe keine Lust immer wieder nach unaufgelösten Referenzen zu suchen. Ein compilierbares Projekt ist z.B. eine zip-Datei des kompletten Atmel-Studio-Projekts, die man entpacken und sofort in Atmel-Studio laden und compilieren kann (Du solltest mitbekommen haben, daß ich auch Atmel-Studio 7 benutze), ohne erst lange zu suchen, in welchen Dateien nun welche Funktionen deklariert und definiert wurden. Atmel-Studio bietet nämlich eine komfortable Funktion: man kann einfach auf einen Namen klicken und bekommt einen Link zur Deklaration und Definition angeboten.

    Mangels grade verfügbarer passender Hardware kann ich Deine Funktionen z.Zt. nicht ausprobieren, sondern lediglich logisch nachvollziehen, warum also sollte ich mir die Arbeit nochmal machen, die Du schon gemacht hast, und erst ein compilierbares Projekt zusammenbasteln.

    Es mag durchaus sein, daß die Funktionen unter optimalen Bedingungen ausreichen, was ich auf den ersten Blick bemerke, ist die Abwesenheit von jeglicher Fehlerbehandlung.

    Bei jedem Fehler hängt sich Dein System unter ungünstigen Umständen also auf.
     
  8. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    @Mikro23 Es tut mir leid das ich nicht über so viele Erfahrungen verfüge wie Du.

    Es kommt mir leider so vor als würdest du alles schlecht reden.
     
  9. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    @Janiiix3 Das braucht Dir nicht Leid zu tun, Du kannst die Erfahrungen immer noch selbst machen.

    Du versuchst immer noch den zweiten Schritt vor dem ersten zu tun, da kann es Dir schon mal so vorkommen, daß ich alles schlecht rede, wenn ich auf mögliche Probleme hinweise, die sich, wenn man sie nicht berücksichtigt, später mal unangenehm bemerkbar machen werden.

    Du hast doch schon eine Menge erreicht, auch wenn Du vieles in gewissem Sinn kopiert hast. Das habe ich auch, aber richtig was damit anfangen kann ich doch erst, wenn ich es auch verstanden habe wie es genau funktioniert.

    Ich kann ja verstehen, daß Du schnell Erfolge sehen willst. Das möchte ich auch. Nur leider funktioniert die Welt meist nicht so...
     
    #9 Mikro23, 29. März 2018
    Zuletzt bearbeitet: 30. März 2018
  10. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    So, inzwischen habe ich die Funktionen aus Beitrag #6 ausprobiert.
    In Ermangelung anderer I2C-Slaves habe ich eine Real Time Clock DS1307 an einen XmegaE5 angeschlossen.
    Nachdem die Initialisierung und die Schreib-Funktion durchgelaufen sind, bleibt er beim Lesen an dieser Stelle hängen:

    CodeBox C und C++
    while( ! ( twi->MASTER.STATUS & TWI_MASTER_RIF_bm ) );
    Das ReadInterruptFlag wird nie high. Bisher habe ich noch keine Idee, woran es liegen könnte.

    Die I2C-Funktionen des ASF, die mit Interrupt laufen, funktionieren dagegen problemlos in dieser Konfiguration.
     
  11. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Zeig doch mal deinen Kode..
     
  12. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Ich habe noch eine TImeout Funktion mit eingebaut.
     

    Anhänge:

  13. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Schaue ich mir an. Hier erstmal ein compilierbares Projekt.

    Dafür habe ich aus einem vorhandenen Projekt weitgehend alles rausgeschmissen, was nicht gebraucht wurde und habe dann Deine Funktionen und die aus dem ASF eingebunden.

    Der E5 läuft hier mit 2MHz und der DS1307 kann nur 100kHz, das habe ich angepaßt.

    Deine Read-Funktion übergibt einen Pointer auf ein globales Array und gibt den selben Pointer zurück. Die unnötige Rückgabe habe ich rausgenommen. Das Array kann sowieso überall gelesen werden, da die Adresse global bekannt ist.

    twi-master-driver sind die ASF-Funktionen (avr-compiler.h gehört auch dazu)

    uartx sind die UART-Funktionen von Peter Fleury, die ich an den Xmega angepaßt habe, um mit dem PC kommunizieren zu können

    Display sind Funktionen für ein LCD, in diesem Fall für ein DOGM162, auf dem Zeit und Datum ausgegeben werden

    Ein paar LEDs blinken auch noch, damit ich gleich sehen kann, ob und was nicht läuft.

    main muß für sich selbst sprechen, da sehr sparsam kommentiert. ;)

    Zwischen Deinen und den ASF-Funktionen wird durch auskommentieren der Zeile

    CodeBox C und C++
    #define USE_ASF
    in main umgeschaltet.

    Hier und da sind wohl noch einige überflüssige Fragmente stehengeblieben, die den Leser irritieren können, die vom Compiler aber, da nicht gebraucht, wegoptimiert werden.
     

    Anhänge:

  14. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Habe ich das richtig verstanden das du schreiben kannst jedoch lesen klappt nicht?
     
  15. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Da er beim Lesen hängenbleibt, kann ich nicht feststellen, ob er richtig geschrieben hat.
    Beim Schreiben bleibt er jedenfalls nicht hängen, d.h. da er mehrere Bytes hintereinander schickt, muß er wohl ein ACK vom Slave bekommen haben, sonst würde WIF nicht auf 1 gehen.
     
  16. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Also ich habe auch eine RTC, einen BMP180 und ein SSD1306 am Bus und alles ohne Probleme.
     
  17. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Mit welchen Funktionen? Mit den neuen oder den alten? Oder mit noch anderen?
    Da ich bisher noch kein compilierbares Projekt von Dir mit wenigstens einem Slave gesehen habe, kann ich dazu nichts weiter sagen.
    Mein Projekt läuft mit den ASF-Funktionen auch ohne Probleme, mit Deinen nicht.
    Zumindest mit den alten, vielleicht geht es ja jetzt mit den neuen.
     
  18. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Es funktioniert mit beiden! Habe wie schon erwähnt mit keinem Slave Probleme gehabt..

    Du initalisierst ihn schon richtig und ließt auch richtig aus. Hast du externe PullUps drauf geschaltet (SDA , SCL)? Nutzen die Routinen vom ASF evtl. die internen PullUps?
    Kann man beim ASF einstellen ob MSB oder LSB zuerst raus geschubst werden?
     
  19. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    @Mikro23 Was mir gerade noch eingefallen ist.. Bei den neuen Funktion die ich zuletzt gepostet habe, gibt es eine "Fehlerbehandlung"

    Werte mal nach dem "Leseversuch" das Byte "twiErr.allErr" aus und poste mal ob irgendein Bit gesetzt ist..
     
  20. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Extern, hättest Du meinem Projekt entnehmen können.
    Gibt das ASF nicht vor und es sind externe dran, würde also keinen Unterschied machen, wenn die internen zusätzlich aktiviert wären.
    Kann man bei I2C prinzipiell nicht einstellen, ist per Definition MSB-first.

    Deine neue read-Funktion wird immer mit Timeout abgebrochen.
    Da Du meine wiederholten Nachfragen nach einem vollständigen, compilierbaren Projekt mit allen Initialisierungen bisher hartnäckig ignoriert hast, kann ich auch nicht nachsehen, ob Du sonst irgendwas anders machst.
     
  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren und die Seite optimal für dich anzupassen. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden