Forum: Mikrocontroller und Digitale Elektronik 16 Bit Register des Analog Dgitalwandlers ADC128d818 über I2C (TWI) mit dem Atmega 8535 auslesen


von Marcel S. (mascheck277)


Lesenswert?

Hallo zusammen,

Ich habe schon einiges mit dem I2C Bus mithilfe von Arduinos realisiert. 
Nun möchte ich jedoch mit dem Atmega8535 den ADC Wandler ADC128d818 über 
I2C auslesen. Da es hier ja keine Libraries gibt wie wire.begin(), etc. 
muss man das ja über die TWCR TWSR Register etc. machen. Da habe ich 
mich bereits reingearbeitet. Ich habe es nun so verstanden, dass ich, 
wenn ich mit dem Atmega im Master Receiver Modus zum Beispiel ein 
Register von einem Slave (ADC128d818) auslesen möchte, lade ich die 
Adresse+Readbit in das TWDR und sende dies per (1<<Twint) | (1<<TWEN), 
danach lade ich das Register das ich auslesen möchte in TWDR und schicke 
es erneut. Danach starte ich den Empfang uns speichere es in einer 
Variablen.
Ich habe 2 Fragen bezüglich der Datenübertragung über I2C im Master 
Receiver Modus:

1. Ist mein bisheriger Programmcode korrekt oder habe ich etwas falsch 
gemacht?

2. Wenn man 2 Byte als 16 Bit Zahl auslesen will kann man ja beide 
nacheinander auslesen und durch Bitmanipulation / Bitverschiebung MSB 
und LSB aneinanderhängen. Wie mache ich das aber im Fall des ADC128d818 
der für 8 analoge Eingänge nur 8 Register anstatt 16 mit MSB und LSB 
hat? Jedes Register umfasst 16 Bit. Wie empfange ich das per I2C? Mein 
bisheriger Programmcode ist ja nur für das Auslesen eines 8 Bit 
Registers geeignet oder?

Mein bisheriger Code dazu:

#define address 0x1D

uint8_t Wert = 0;


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

while(!(TWCR & (1<<TWINT)))
;

if(((TWSR & 0xF8)!=TW_START) || ((TWSR & 0xF8)!=TW_REP_START)) Error();

TWDR = (address<<1) | TW_READ;

TWCR = (1<<TWINT) | (1<<TWEN);

while(!(TWCR & (1<<TWINT)))
;

if((TWSR & 0xF8) != TW_MR_SLA_ACK) Error();


TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);

while(!(TWCR & (1<<TWINT)))
;

if((TWSR & 0xF8) != TW_MR_DATA_ACK) Error();

Wert = TWDR;

TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

Stimmt das soweit oder habe ich etwas falsch verstanden?
Wie muss ich vorgehen um ein 16 Bit Register über I2C zu Empfangen?

Danke schonmal für die Antworten und Entschuldigung wenn ich etwas 
falsch formatiert habe oder nicht ordnungsgemäß beschrieben habe, bin 
seit heute erst hier angemeldet und habe noch keine Erfahrung 
diesbezüglich. :)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marcel S. schrieb:
> TWDR = (address<<1) | TW_READ;

 Slaveadress wird geschrieben, nicht gelesen.

Marcel S. schrieb:
> Wie muss ich vorgehen um ein 16 Bit Register über I2C zu Empfangen?

 Wenn Registeradress schon gesetzt ist, einfach 2 Bytes lesen, wenn
 nicht, zuerst Registeradress setzen, danach 2 Bytes lesen.

 Steht aber wahrscheinlich alles im DaBla.

von Marcel S. (mascheck277)


Lesenswert?

Hallo und danke erstmal für die schnelle Antwort.

TWDR = (address<<1) bedeutet dass ich die Slave Adresse um 1 Bit nach 
links verschoben in das TWDR Register meines Atmega8535 lade.
| TW_READ bedeutet dass ich daran das TW_READ Bit 1 hänge (also Bit 0 ist hier 1). 
TW_READ ist in der Headerdatei twi.h definiert. Diese binde ich am Anfang mit 
#include <util/twi.h> ein. Man muss ja sagen ob man im Master Transmitter oder im 
Master Receiver Mode senden bzw. lesen will. Deshlab TW_READ.

Habe sowohl das Datenblatt des Atmega8535 als auch das des ADC128d818 
von vorn bis hintern mehrfach durchgearbeitet, jedoch habe ich nichts 
dazu gefunden wie es ausgelesen wird. In dem Datenblatt des ADC ist 
alles recht gut erklärt bis auf das.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marcel S. schrieb:
> Habe sowohl das Datenblatt des Atmega8535 als auch das des ADC128d818
> von vorn bis hintern mehrfach durchgearbeitet, jedoch habe ich nichts
> dazu gefunden wie es ausgelesen wird. In dem Datenblatt des ADC ist
> alles recht gut erklärt bis auf das.

 Ich würde es an deiner Stelle so probieren:
   (Adress AND WR) senden, ACK abwarten,
   RegisterAdress senden, ACK abwarten,
   RepeatedStart,
   (Adress OR RD) senden, ACK abwarten,
   Databyte einlesen, ACK senden,
   Databyte einlesen, NACK senden.

 Schau mal im DaBla nach ob es Kontroll Register gibt, die man vorher
 auf bestimmte Werte setzen muss.

von c-hater (Gast)


Lesenswert?

Marcel S. schrieb:

> 2. Wenn man 2 Byte als 16 Bit Zahl auslesen will kann man ja beide
> nacheinander auslesen und durch Bitmanipulation / Bitverschiebung MSB
> und LSB aneinanderhängen. Wie mache ich das aber im Fall des ADC128d818
> der für 8 analoge Eingänge nur 8 Register anstatt 16 mit MSB und LSB
> hat? Jedes Register umfasst 16 Bit.

Dann MUSS das Register für den I2C-Zugriff natürlich in zwei 
8Bit-Register zerlegt werden, denn I2C kann nunmal nur 8Bit-Zugriffe.

Wie genau man das zerlegt und was dabei eventuell zu beachten ist, steht 
ganz sicher im Datenblatt des ADC128d818. Du musst das Teil einfach mal 
nur lesen und verstehen.

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.