Hallo zusammen, ich versuche mich gerade am ASF im Atmel Studio in Kombination mit dem TWI-Service für nen Xmega16 und verzweifel ein wenig. Ich bin auf der Suche nach einer Funktion, mit der ich ein Byte an Daten an einen i2c-Slave schicken kann um danach 2 Byte vom Slave zurück zu lesen, ohne dem Slave nochmal seine eigene Adresse zu schicken. Leider gibt es so wie es aussieht mit dem TWI-Modul im Xmega keine Möglichkeit mehr Starts selber zu repeaten... Beim ATmega war das ja noch durch ein Bit möglich... Eine API-Funktion, die sowas kann habe ich auch nicht gefunden. Hat jemand so eine Funktion für den ATXmega schonmal gesehen und würde mir ne Quelle nennen? Das wäre super. Eine weiter Sache, die nicht so recht verstehe, ist die mehr als merkwürdige API-Dokumentation... Wenn man sich hier: http://asf.atmel.com/docs/3.11.0/xmegae/html/twi_quickstart.html mal den Codeblock "Writing to a slave device" anschaut, wird in der ersten Zeile der Konfiguration ein "EEPROM_MEM_ADDR" verwendet? Der Kommentar dahinter spricht von "TWI slave memory address data", also war meine erste Idee, dass damit bei einem Speicher zum Beispiel angegeben wird, an welcher Adresse die folgenden Daten geschrieben werden sollen. Also etwa so: SDA: - start - {chip-addresse} --- {addr (0 bis 3 Byte)} --- {buffer (schreiben)} - stop - Sollte diese Vermutung stimmen, habe ich gedacht, dass das beim Empfangen auch so funktioniert, nur halt lesend: SDA: - start - {chip-addresse} --- {addr/Befehl (1 Byte)} --- {buffer (lesen 2 Byte)} - stop - Stimmen meine Annahmen bisher, oder bin ich komplett auf dem Holzweg?
Hallo, schau dir mal die Seite an: http://www.jtronics.de/avr-projekte/library-i2c-twi-master.html Die Biblitothek von Peter Fleury gibt eigentlich alles her. > Beim ATmega war das ja noch durch ein Bit möglich... Wie ist das Bit genau definiert? Gruß G.G.
Hallo, im Register TWIx.Master.CTRLC kann mit CMD 1 ein Repeated Start ausgelöst werden (Datenblatt Seite 216). Es gibt von Atmel auch eine nützliche AppNote zu dem Thema (AVR315 http://www.atmel.com/Images/doc2564.pdf).
Hallo Gerhard, erstmal danke für deine Antwort. Die von dir verlinkte Bibliothek habe ich auch schon gefunden. Ist aber augenscheinlich nicht für einen AVR Xmega gedacht, da dieser kein TWSR-Register hat. Zumindest nicht laut Datenblatt und in AVR-Studio auch nicht ;) Also hilft mir das leider nicht weiter, oder ich bin blind. Gerhard Gehlert schrieb: >> Beim ATmega war das ja noch durch ein Bit möglich... > > Wie ist das Bit genau definiert? Ok es war die Kombination aus 3 Bits, während einer laufenden Verbindung ;)
1 | TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // Start schicken |
Gruß
Also ich verwende die Funktionen aus der Atmel Appnote AVR1308 für den Xmega. Damit hat es bisher wunderbar funktioniert mehrere Bytes per Burst aus dem Slave zu lesen :
1 | sendBuffer[0] = READ_REG; |
2 | //ein byte (sendbuffer) senden, 6 Bytes in readData lesen
|
3 | TWI_MasterWriteRead(&twiMaster, I2C_SLAVE_ADRESS, &sendBuffer[0],1,6); |
Danach hast du in "twiMaster.readData" [0...5] 6 Bytes des Slaves
:
Bearbeitet durch User
Julian B. schrieb: > > Ich bin auf der Suche nach einer Funktion, mit der ich ein Byte an Daten > an einen i2c-Slave schicken kann um danach 2 Byte vom Slave zurück zu > lesen, ohne dem Slave nochmal seine eigene Adresse zu schicken. Leider > gibt es so wie es aussieht mit dem TWI-Modul im Xmega keine Möglichkeit > mehr Starts selber zu repeaten... Beim ATmega war das ja noch durch ein > Bit möglich... Ich würde mal sagen, das geht nicht (grundsätzlich in I2C), weil dass Lese-/Schreib-Bit Teil des Adressbytes ist. Um von Schreiben auf Lesen zu schalten, sendet man eben gerade die 7-Bit-Adresse + Lese-Bit. Das Hardwaremodul macht das ja auch automatisch so. Wenn du das Verhältnis Adressbytes/Nutzdaten verbessern willst, solltest du einfach längere Pakete verwenden.
Hallo zusammen, danke für eure Antworten. @Timmo H.: Hab mir die Appnote mal angesehen und werde sie jetzt auch mal ausprobieren... Komisch finde ich aber, dass der TWI_Slave bei allen Beispielen mit initialisiert wird. Ist der nötig zum empfangen von Daten? Es verwirrt mich, dass der dann auch eine eigene Empfangsadresse bekommt.... @Thomas F.: Um Datenraten oder Durchsatz geht es mir nicht, ich hab bei einem I2C-Slave nur das Datenblatt gelesen und nicht den Beispielcode des Herstellers betrachtet. Laut Datenblatt muss die Adresse zum lesen nicht gesendet werden, nachdem ein bestimmter Befehl an den Slave gesendet wurde. Das hat mich halt verwirrt. Im Beispielcode des Herstellers schicken die aber auch die Adresse zum lesen nochmal raus und lesen dann erst das Ergebnis zurück. Danke!
Julian B. schrieb: > Hallo zusammen, > > danke für eure Antworten. > > @Timmo H.: > Hab mir die Appnote mal angesehen und werde sie jetzt auch mal > ausprobieren... Komisch finde ich aber, dass der TWI_Slave bei allen > Beispielen mit initialisiert wird. Ist der nötig zum empfangen von > Daten? Es verwirrt mich, dass der dann auch eine eigene Empfangsadresse > bekommt.... Nein du brauchst natürlich nur den Master initialisieren.
1 | #include <avr/io.h> |
2 | #include <avr/pgmspace.h> |
3 | #include <util/delay.h> |
4 | #include <avr/interrupt.h> |
5 | #include <stdint.h> |
6 | #include <stdio.h> |
7 | |
8 | #include "twi_master_driver.h" |
9 | TWI_Master_t twiMaster; /*!< TWI master module. */ |
10 | |
11 | int main(){ |
12 | uint8_t sendBuffer[10]; |
13 | |
14 | //Set TWI Clock to 400 kHz
|
15 | TWI_MasterInit(&twiMaster, &TWIE, TWI_MASTER_INTLVL_LO_gc, (F_CPU/(2*400000)) - 5); |
16 | |
17 | sendBuffer[0] = 0x2B; //CTRL_REG2 |
18 | sendBuffer[1] = 0x02; //MODS1 = 1 => High Res |
19 | TWI_MasterWriteRead(&twiMaster, MMA845XQ_ADDR, &sendBuffer[0],2,0); |
20 | while (twiMaster.status != TWIM_STATUS_READY) { |
21 | /* Wait until transaction is complete. */
|
22 | }
|
23 | ...
|
24 | ...
|
25 | ...
|
26 | *x = twiMaster.readData[0] <<6; |
27 | *x |= twiMaster.readData[1] >>2; |
28 | if(*x & 0x2000){ |
29 | *x |= 0xE000; |
30 | }
|
31 | *y = twiMaster.readData[2] <<6; |
32 | *y |= twiMaster.readData[3] >>2; |
33 | if(*y & 0x2000){ |
34 | *y |= 0xE000; |
35 | }
|
36 | *z = twiMaster.readData[4] <<6; |
37 | *z |= twiMaster.readData[5] >>2; |
38 | if(*z & 0x2000){ |
39 | *z |= 0xE000; |
40 | }
|
41 | |
42 | ...
|
43 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.