C XMEGA - TWI (I2C)

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. 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
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
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
i2c_start()
i2c_start_wait()
i2c_rep_start()
i2c_readAck()
i2c_readNack()
i2c_stop()


Gearbeitet. Das wollte ich jetzt auf dem "xMega" nachbilden.
 
Zuletzt bearbeitet:
Habe gerade mal wieder Probleme bei dem einrichtigen einer I2C Kommunikation zwischen XMEGA und einem Slave.
»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.
 
Aktuell habe Ich diese Routinen in Verwendungen zum lesen und schreiben.


CodeBox 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?
 
Mir ist der Ablauf noch nicht so bewusst. Im Datenblatt gibt es (siehe Bild), verschiedene "CMD"..
Wann muss ich was machen?!
 

Anhänge

  • xmega_twi.jpg
    xmega_twi.jpg
    398,6 KB · Aufrufe: 4
Aktuell habe Ich diese Routinen in Verwendungen zum lesen und schreiben.
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.
Verstehst du mich ein wenig?
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.
Wann muss ich was machen?!
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.
 
@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

  • xmega_twi.c
    2,1 KB · Aufrufe: 11
  • xmega_twi.h
    970 Bytes · Aufrufe: 7
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.
 
@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.
 
@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...
 
Zuletzt bearbeitet:
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
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.
 
Zeig doch mal deinen Kode..
 
Ich habe noch eine TImeout Funktion mit eingebaut.
 

Anhänge

  • xmega_twi.c
    5,6 KB · Aufrufe: 11
  • xmega_twi.h
    1,5 KB · Aufrufe: 9
Ich habe noch eine TImeout Funktion mit eingebaut.
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
#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

  • E5DS1307.zip
    29,1 KB · Aufrufe: 11
Habe ich das richtig verstanden das du schreiben kannst jedoch lesen klappt nicht?
 
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.
 
Also ich habe auch eine RTC, einen BMP180 und ein SSD1306 am Bus und alles ohne Probleme.
 
Also ich habe auch eine RTC, einen BMP180 und ein SSD1306 am Bus und alles ohne Probleme.
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.
 
Mit welchen Funktionen? Mit den neuen oder den alten? Oder mit noch anderen?
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?
 
@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..
 
Hast du externe PullUps drauf geschaltet (SDA , SCL)?
Extern, hättest Du meinem Projekt entnehmen können.
Nutzen die Routinen vom ASF evtl. die internen PullUps?
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 beim ASF einstellen ob MSB oder LSB zuerst raus geschubst werden?
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

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)