Forum: Mikrocontroller und Digitale Elektronik Xmega16 ASF + TWI Write und Read


von Julian B. (zitrone18)


Lesenswert?

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?

von Gerhard G. (g_g)


Lesenswert?

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.

von afroman (Gast)


Lesenswert?

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).

von Julian B. (zitrone18)


Lesenswert?

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ß

von Timmo H. (masterfx)


Lesenswert?

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
von Thomas F. (tomasf)


Lesenswert?

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.

von Julian B. (zitrone18)


Lesenswert?

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!

von Timmo H. (masterfx)


Lesenswert?

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
Noch kein Account? Hier anmelden.