Forum: Mikrocontroller und Digitale Elektronik Erste Schritte mit I2C


von M. T. (cube7)


Lesenswert?

Hallo Pros,

ich bin gerade dabei meine ersten Schritte mit AVR µC und TWI zu machen 
und habe ein Paar allgemeine Fragen.

Was vorhanden ist:

3xATmega 328P
1xSTK500
1xLichtsensor ISL29010 über I2C anbindbar

Ziel: Mein Wunsch ist es nun diesen Lichtsensor über den µC auszulesen, 
so dass bei bestimmten Lichtverhältnissen z.B. eine LED zu Leuchten 
beginnt.

(Die f***ing manuals habe ich natürlich gelesen, okay die vom Atmel nur 
selektiv XD.)

Hier mal n reines Verbindungsschema mit der Frage ob ich irgendetwas 
nicht bedacht habe.

Sensor----STK500(ATmega 328P)

Vdd-------VTG(Zielspannung)
GND----GND
REXT--100kOhm--GND (laut manual)
A0----GND (für Slave-Adresse:1000101x)
SCL----SCL
SDA----SDA
Am STK500 habe ich den Expansion Connector 0 genutzt.

Die erste Frage stellt sich mir beim Programmieren des AVR unter der 
Benutzung von Peter Fleurys I2C library.
1
 #include <i2cmaster.h>
2
3
4
 #define ISL29010  0x8A      // Sensor x8A = Adresse 10001010
5
 int main(void)
6
 {
7
     unsigned char ret;
8
9
     i2c_init();                             // initialize I2C library
10
11
     //  
12
     i2c_start_wait(ISL29010+I2C_READ);     // set device address and write mode
13
     i2c_read (ret);                        // auslesen ohne ACK 
14
     i2c_write(ret);                        // write value to EEPROM
15
     i2c_stop();                             // set stop conditon = release bus
16
17
     i2c_stop();
18
19
     for(;;);
20
 }

Würde so bereits das aktuelle Messbyte im EEPROM gespeichert werden, 
obwohl ich nicht einmal das Register angegeben habe in der das Messbyte 
im Sensor liegt, oder gar den Ort an dem es im AVR gespeichert werden 
soll?

Für ein bisschen Unterstützung wäre ich als noop sehr dankbar XD.

Grüße,
M.

P.S.
Gibt es eigentlich eine Alternative für den 100kOhm pull-up Widerstand, 
ich hab momentan keinen zur Hand.

von M. T. (cube7)


Lesenswert?

Hat vielleicht sonst bereits jemand Erfahrungen mit dem STK500 und TWI 
gemacht und könnte mir da ein paar Ratschläge geben?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Gibt es eigentlich eine Alternative für den 100kOhm pull-up Widerstand,
> ich hab momentan keinen zur Hand.

Hundert 1k in Serie? 10 1M parallel?
SCNR

von XXX (Gast)


Lesenswert?

Hallo

Soweit ich üerb TWI Bescheid weiß, kann man nicht so einfach zwischen
Schreiben und Lesen umschalten so wie du das machst.
Dazwischen gehört ein STOP-Befehl mit anschließender neuer
Adressierung.

Siehe
//http://pdf1.alldatasheet.com/datasheetpdf/view/224135/INTERSIL/ISL29010.html//

Seite 3 und 4.

>>     i2c_start_wait(ISL29010+I2C_READ);     // set device address and write mode


Da stimmt auch was nicht. Laut Funktion willst du lesen, laut
Kommentar willst du schreiben.

Gruß
Joachim

von M. T. (cube7)


Lesenswert?

Ah eine hilfreiche Antwort!
Sorry, der Kommentar ist falsch, muss natürlich lesen heißen.
Mit dem Stop befehl bin ich mir nicht sicher, ist zwar nach I2C 
Datasheet notwendig, aber ich verwende ja Peter Fleurys library.

Ich wüsste nur mal gerne ob ich das Prinzip seiner Library richtig 
verstanden habe.

Für weitere hilfreiche Antworten wäre ich dankbar.

Grüße,
M.

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

ne ne des ist quatsch

Um zum Beispiel ab einer gewissen Adresse zu lesen muss als Erste der 
Lesebefehl gesendet werden, dann die Adresse ab der gelesen werden soll, 
unmittelba darauf folgen die Takte zum lesen der Bytes. Beim Lesen des 
letzten Bytes ist die Lücke für das Aknow_Bit zu durch setzen des 
Nack_Bit durch den Sender zu schließen. Darauf erst kann ein Stoppbefehl 
folgen oder mit dem Senden eines neuen Befehls die übertragung 
fortgesetzt werden.

von M. T. (cube7)


Lesenswert?

Hallo Winne,
danke für deine Antwort.
Hmm, dacht ich mit  schon, dass das nicht so einfach ist.

Also nehmen wir mal mein Beispiel und wollen einen Sensor über I2C 
auslesen.
D.h. ich muss zuerst ganz normal I2C initialisieren
1
#include <i2cmaster.h>
2
3
4
 #define ISL29010  0x8A      // Sensor x8A = Adresse 10001010
5
 int main(void)
6
 {
7
    ....
8
9
  i2c_init();                           // I2C lib. initialisieren
10
11
      
12
  i2c_start_wait(ISL29010+I2C_READ);  //Sensor ansprechen und auf ACK warten                  
13
 }

dann muss ich aus dem entsprechenden Register des Sensors die Messdaten 
auslesen
1
i2c_read (0x04);   //hier die Addresse des Registers aus der gelesen werden        soll
2
3
i2c_read (ret);   // und hier die Variable in der die Daten gespeichert werden sollen????

dann schreibst du
"unmittelba darauf folgen die Takte zum lesen der Bytes"
was ich nicht ganz verstehe, meins du wie lange / wie viele Takte der 
Sensor ausgelesen werden soll und wenn ja, wie reguliert man das, mit 
schleifen?

Grüße,
M.

von Lehrmann M. (ubimbo)


Lesenswert?

M. T. schrieb:
> Hat vielleicht sonst bereits jemand Erfahrungen mit dem STK500 und TWI
> gemacht und könnte mir da ein paar Ratschläge geben?

Was hat denn das STK500 mit TWI zu tun ?

M. T. schrieb:
> (Die f***ing manuals habe ich natürlich gelesen, okay die vom Atmel nur
> selektiv XD.)

Ziemlich schlechte Einstellung ...

Woran erkennst du denn, dass dein Programm nicht funktioniert?

Wie steht's mit Fuses ?

Hier für die Verdrahtung:
http://www.sprut.de/electronic/pic/grund/i2c.htm

Und noch ein Schaltplanbeispiel:
http://www.sprut.de/electronic/pic/grund/i2c_soft.htm

Ist allerdings beides für PIC und nicht für AVR

M. T. schrieb:
> Die f***ing manuals habe ich natürlich gelesen

Wenn du das getan hast dann sollte ja alles klar sein oder? Da steht 
doch alles drin. Man muss nur genau lesen und sich Zeit nehmen. Wir 
können auch nur das Datenblatt lesen.

Außerdem solltest du die Libraries nur verwenden wenn du sie auch 
verstehst.

Ansonsten überleg dir ob nicht eine diskrete Schaltung für dich besser 
geeignet ist...

von M. T. (cube7)


Lesenswert?

Hallo Michael,
eigentlich geht es mir in meinem Thread nicht darum diesen 
Programmschnipsel zum laufen zu bringen, sondern besser I2C zu 
verstehen.
Nur vom lesen irgendwelcher manuals wird man aber weder programmieren 
lernen, noch TWI verstehen.
Um die Fuses mach ich mir momentan noch keine Gedanken, da ich das 
Programm ja nicht einmal gebrannt habe - wie gesagt ich will erst einmal 
die Grundlagen verstehen.

Grüße,
M

P.S.
Danke für die Links, ich glaube die helfen mir wieder ein Stück 
weiter:-)!

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

noch vergessen jede übertragung muss mit einer startconition beginnen 
und mit einer stoppcondition enden

hier wird eine Uhr DS3231 gelesen und gestellt ()nur die zeit)

lesen aus der TWI

TWI_STARTCONDITION();
TWI_SLA_W (clock_SLA_W);
TWI_SENDDATA (0x00);
TWI_RSTARTCONDITION();
TWI_SLA_R (clock_SLA_R);
s0=TWI_RECIVEDATA_ACK ();
m0=TWI_RECIVEDATA_ACK ();
h0=TWI_RECIVEDATA_NACK ();
TWI_STOPCONDITION();


schreiben in die TWI


TWI_STARTCONDITION();
TWI_SLA_W (clock_SLA_W);
TWI_SENDDATA (0x00);
TWI_SENDDATA (s0);
TWI_SENDDATA (m0);
TWI_SENDDATA (h0);
TWI_STOPCONDITION();


die Funtkionen dazu

.....


hier noch was zu I²C

char
TWINT=7
TWEA=6
TWSTA=5
TWSTO=4
TWWC=3
TWEN=2
TWIE=0

START=0x08
RSTART=0x10
MT_SLA_ACK=0x18
MT_DATA_ACK=0x28
MR_SLA_ACK=0x40
MR_DATA_ACK=0x50
SLA_W1=0xa0
SLA_W2=0xa2
SLA_R1=0xa1
SLA_R2=0xa3
;

//-----------------------------
void ERROR (int errcode)
{
if (errorcode == 1 )
UART1_Write_Strf ("fehler beim senden der TWI_STARTCONDITION \n\r");
if (errorcode == 2 )
UART1_Write_Strf ("fehler beim senden der TWI_RSTARTCONDITION \n\r");
if (errorcode == 3 )
UART1_Write_Strf ("fehler beim senden des TWI_SLA_W \n\r");
if (errorcode == 4 )
UART1_Write_Strf ("fehler beim senden des TWI_SLA_R \n\r");
if (errorcode == 5)
UART1_Write_Strf ("fehler während TWI_SENDDATA \n\r");
if (errorcode == 6)
UART1_Write_Strf ("fehler während TWI_RECIVEDATA \n\r");
if (errorcode == 7 )
UART1_Write_Strf ("fehler während TWI_RECIVEDATAF \n\r");
if (errorcode == 8 )
UART1_Write_Strf ("fehler beim senden der TWI_STOPCONDITION \n\r");

}
//------------------------------
void TWI_STARTCONDITION()
{
TWCR=0x00 |(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8)!=START)ERROR(1);
}
//------------------------------
void TWI_RSTARTCONDITION()
{
TWCR = 0x00 |(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8)!=RSTART)ERROR(2);
}
//------------------------------
void TWI_SLA_W (int SLA_W)
{
TWDR = SLA_W;
TWCR = 0x00 |(1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8)!=MT_SLA_ACK)ERROR(3);
}
//------------------------------
void TWI_SLA_R (int SLA_R)
{
TWDR =SLA_R;
TWCR = 0x00 |(1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8)!=MR_SLA_ACK)ERROR(4);
}
//------------------------------
void TWI_SENDDATA (int DATA)
{
TWDR=DATA;
TWCR = 0x00 | (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8)!=MT_DATA_ACK)ERROR(5);
}
//------------------------------
char TWI_RECIVEDATA ()
{
char DATA;
TWCR = 0x00 |(1<<TWINT) | (1<<TWEA)| (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8)!=MR_DATA_ACK)ERROR(6);
DATA=TWDR;
return DATA;
}
//------------------------------
//------------------------------
char TWI_RECIVEDATAF ()
{
char DATA;
TWCR = 0x00| (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8)!=MR_DATA_ACK)ERROR(7);
DATA=TWDR;
return DATA;
}
//------------------------------
void TWI_STOPCONDITION()
{
TWCR=0x00 |(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//while (!(TWCR & (1<<TWINT)));
}

von M. T. (cube7)


Lesenswert?

Danke Winne,
ich werde mal versuchen mich daran zu orientieren!

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.