mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega 8535 und DS1621 über I2C


Autor: J. H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ein Problem mit dem I2C Bus... haben ein Projekt in der Arbeit aber 
komm mit mit dem I2C nicht wirklich klar hab im internet rumgesucht und 
die Datenblätter durchgeschaut aber das hat nicht viel geholfen.
Hab einen vielversprechenden Code gefunden aber in der Simulation bleibt 
das Programm immer bei dem "loop_until_bit_is_set(TWCR,TWINT);" hängen 
weil die Bits anscheinend nicht gesetzt werden und somit auch weiterhin 
nichts funktioniert.

Es soll die Temperatur des DS1621 ausgelesen werden und als erstes am 
Display angezeigt werden. Das mit dem Display ist kein problem ich häng 
nur grad an dem DS1621...

Vielleicht hat das schon mal jemand mit dem Atmega 8535 gemacht und kann 
mir weiterhelfen.

Hier mal das Komplette Programm:
#include  <avr/io.h>
#define    F_CPU 16000000
#include   <util/delay.h>

void i2c_init(void)
{

// 100 kHz SCL bei 4MHz CPU
   TWBR = 12;
   TWSR = 0;
}

void i2c_start(void)
{
   // I2C-Startbedingung
   TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);
}

void i2c_stop(void)
{
   // Stoppe Übertragung
   TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}

void i2c_sendbyte(uint8_t adresse,uint8_t byte)
{

   // Schreibe zu Adresse
   TWDR = (adresse & 0xFE);
   
   // Senden
   TWCR = (1<<TWINT) | (1<<TWEN);   

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);


   // Lege Daten an
   TWDR = byte;

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

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);

}

uint16_t i2c_receivebyte(uint8_t adresse)
{
uint16_t data;
   // Schreibe zu Adresse
   TWDR = (adresse | 0xFF);

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

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);

   // Empfange Daten
   TWCR = (1<<TWINT) | (1<<TWEN);   

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);

   data = (TWDR<<8);

   // Empfange Daten
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);;   

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);

   data |= (TWDR);

   // Empfange Daten
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);;   

   // Warten bis fertig ist
   loop_until_bit_is_set(TWCR,TWINT);

   return data;
} 


int main(void)
{
int temp;
i2c_init();
i2c_start();
i2c_sendbyte(0x96,0xEE);
i2c_start();


while(1)
{
i2c_start();
i2c_sendbyte(0x96,0xAA);
i2c_start();
temp = i2c_receivebyte(0x96);
i2c_stop();
}
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da passt offensichtlich etwas nicht:

> #define    F_CPU 16000000
> #include   <util/delay.h>
>
> void i2c_init(void)
> {
> // 100 kHz SCL bei 4MHz CPU

Hast du den Code selbst entworfen, so dass man den komplett genauer 
unter die Lupe nehmen muss?

Oder handelt es sich um einen bereits anderswo (wo?) erfolgreich 
eingesetzen Code, den man nur in deiner Anpassung/Anwendung debuggen 
muss?

Wie sind AVR und Sensor und I2C-Pullups miteinander verschaltet, d.h. 
wie sieht der Schaltplan aus? Wie lang sind die I2C Leitungen?

> temp = i2c_receivebyte(0x96);

Und was machst du mit temp weiter? Ich sehe überhaupt keine keine 
Anzeige- oder Ausgabefunktion, mit der man die Funktion des Gerätes 
prüfen kann.

Autor: J. H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
weiß jemand die Adresse über die ich den DS1621 ansprechen kann? finde 
im Datenblatt nichts. SDA und SCL hab ich scho aber nicht welche Adresse 
ich verwenden soll.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für das Feedback zu meiner Antwort ;-(

Die slave address ist im Datenblatt auf Seite 8 beschrieben
http://datasheets.maxim-ic.com/en/ds/DS1621.pdf

Wichtig ist wie die Pins A0, A1 und A2 des DS1621 hardwaremäßig 
beschaltet sind. Also ob auf GND gezogen oder auf Vcc.

Die Adresse ist dann binär:

1 0 0 1 A2 A1 A0 W

Also bei A0...A2 auf GND:

Lesen: 0b10010001 = 0x91
Schreiben: 0b10010000 = 0x90

Du verwendest eine Grundadresse z.B. in folgendem Code die 0x96

> i2c_sendbyte(0x96,0xAA);

Und toggelst das R/W bit dann je nach Schreib/Leseoperation dazu.

0x96 = 0b10010110, d.h. A2 müsste auf GND Potential (LOW) liegen aber A1 
und A0 auf Vcc Potential (HIGH). Prüfe das mal im Schaltplan.

Autor: J. H. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
die pins A0, A1 und A2 liegen auf GND also das mit schreib- und 
leseadresse ist jetzt klar aber nocht nicht ganz wie ich das ganze 
anwende um die temperatur auszulesen...

habe jetzt auch eine andere i2c vorlage genommen die wir in der 
berufsschule bekommen haben.
hab das projekt auch mal als anhang beigefügt.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> habe jetzt auch eine andere i2c vorlage genommen die wir in der
> berufsschule bekommen haben.

Und? Jetzt funktioniert dein Aufbau?

Wenn nein:

Das neue Projekt ist komplizierter.

Zusätzlich ist drin eine LCD Ansteuerung und eine 
PWM-Lüfteransteuerung. Dafür werden die bekannten und geprüften 
I2C Routinen von Peter Fleury benutzt. In dem Code ist einiges 
auskommentiert und ich überblicke im Moment nicht, ob der Code im 
jetzigen Zustand lauffähig ist.

Ich würde beim alten Projekt bleiben, denn du schreibst oben,

>> "Das mit dem Display ist kein problem ich häng
>> nur grad an dem DS1621..."

Also zeige deinen lauffähigen Code, um einen Text auf deinem Display 
auszugeben. Den kann man gemäß FAQ wie folgt erweitern:

1/ Umwandlung der Zahl temp in einen Text (String)
2/ Ausgabe des Textes auf dem Display

http://www.mikrocontroller.net/articles/FAQ#Wie_ka...

Im ersten Schritt nicht darum kümmern, welche Temperatur temp anzeigt, 
sondern nur, ob der Sensor einen Wert über den I2C Bus liefert. Wenn da 
pausible Werte kommen (nicht nur 0xFFFF oder 0), ist die Umrechnung gem. 
Datenblatt der nächste Schritt.

In deinem alten Projekt könntest du am Ende von while in main einen 
Aufruf dieser neuen Ausgabefunktion für temp einbauen, die 
Displayinitialisierung am Anfang von main ergänzen und die *slave 
address* im Programm auf die verwendete Verdrahtung anpassen (0x90 statt 
0x96).

Apropos Verdrahtung: Ich frage jetzt zum letzten Mal nach dem 
Schaltplan. Am I2C-Bus müssen Pull-Up-Widerstände installiert sein, 
damit der funktioniert.

Autor: Dani S. (aboutblank)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stefan, hast du meine PM bekommen?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, aber ich möchte mich da nicht mit ICQ oder Email reinhängen. ICQ 
benutze ich überhaupt nicht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.