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


von J. H. (Gast)


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:
1
#include  <avr/io.h>
2
#define    F_CPU 16000000
3
#include   <util/delay.h>
4
5
void i2c_init(void)
6
{
7
8
// 100 kHz SCL bei 4MHz CPU
9
   TWBR = 12;
10
   TWSR = 0;
11
}
12
13
void i2c_start(void)
14
{
15
   // I2C-Startbedingung
16
   TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
17
   // Warten bis fertig ist
18
   loop_until_bit_is_set(TWCR,TWINT);
19
}
20
21
void i2c_stop(void)
22
{
23
   // Stoppe Übertragung
24
   TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
25
}
26
27
void i2c_sendbyte(uint8_t adresse,uint8_t byte)
28
{
29
30
   // Schreibe zu Adresse
31
   TWDR = (adresse & 0xFE);
32
   
33
   // Senden
34
   TWCR = (1<<TWINT) | (1<<TWEN);   
35
36
   // Warten bis fertig ist
37
   loop_until_bit_is_set(TWCR,TWINT);
38
39
40
   // Lege Daten an
41
   TWDR = byte;
42
43
   // Senden
44
   TWCR = (1<<TWINT) | (1<<TWEN);   
45
46
   // Warten bis fertig ist
47
   loop_until_bit_is_set(TWCR,TWINT);
48
49
}
50
51
uint16_t i2c_receivebyte(uint8_t adresse)
52
{
53
uint16_t data;
54
   // Schreibe zu Adresse
55
   TWDR = (adresse | 0xFF);
56
57
   // Senden
58
   TWCR = (1<<TWINT) | (1<<TWEN);   
59
60
   // Warten bis fertig ist
61
   loop_until_bit_is_set(TWCR,TWINT);
62
63
   // Empfange Daten
64
   TWCR = (1<<TWINT) | (1<<TWEN);   
65
66
   // Warten bis fertig ist
67
   loop_until_bit_is_set(TWCR,TWINT);
68
69
   data = (TWDR<<8);
70
71
   // Empfange Daten
72
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);;   
73
74
   // Warten bis fertig ist
75
   loop_until_bit_is_set(TWCR,TWINT);
76
77
   data |= (TWDR);
78
79
   // Empfange Daten
80
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);;   
81
82
   // Warten bis fertig ist
83
   loop_until_bit_is_set(TWCR,TWINT);
84
85
   return data;
86
} 
87
88
89
int main(void)
90
{
91
int temp;
92
i2c_init();
93
i2c_start();
94
i2c_sendbyte(0x96,0xEE);
95
i2c_start();
96
97
98
while(1)
99
{
100
i2c_start();
101
i2c_sendbyte(0x96,0xAA);
102
i2c_start();
103
temp = i2c_receivebyte(0x96);
104
i2c_stop();
105
}
106
}

von Stefan B. (stefan) Benutzerseite


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.

von J. H. (Gast)


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.

von Stefan B. (stefan) Benutzerseite


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.

von J. H. (Gast)


Angehängte Dateien:

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.

von Stefan B. (stefan) Benutzerseite


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_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F

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.

von Dani S. (aboutblank)


Lesenswert?

stefan, hast du meine PM bekommen?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

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.