PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C und DS1631 allgemeine Grundlagen



Thomas E.
18.03.2012, 09:05
Hallo Gemeinde!


Ich habe mich seit einigen Tagen an meinen ersten I2C-Versuchen gewagt. Allerdings scheinen mir einige Grundlagen massiv zu fehlen, weshalb ich nicht wirklich vorankomme. Ich habe das RN-Wissen und das Buch "Programmieren der AVR RISC-Microkontroller mit Bascom" von Claus Kühnel zu rate gezogen und mir sämtliches über I2C durchgelesen. Auch versuchte ich, über Google an einige Beispiele zu kommen. Das Datenblatt des DS1631 habe ich natürlich ebenfalls zur Hand.

Zur Hardware: An einem Mega8 hängen ein DS1631 Temperatursensor und ein ST24C16 EEPROM. SDA und SCL sind über jeweils 6k8 an +5V.

Als erste Tat wollte ich den DS1631 ansprechen, allerdings scheint mir hier einiges an Basiswissen zu fehlen. Ich habe bis jetzt folgende Dinge verstanden:

Der Mega8 ist der Master, die beiden Bausteine sind die Slaves
Der Datenstrom am Bus geht nacheinander vor sich
Um ein Baustein anzusprechen muss als erstes die Slave-Adresse des Bausteins gesendet werden
Die Übertragung geht Byteweise vor sich
Es funktioniert nicht


Der DS1631 besitzt laut Datenblatt diese Adresse (A0,A1,A2 liegen auf GND):
10010000 für schreiben
10010001 für lesen
Weiters gibt es Befehle, um den Baustein etwas zu befehlen (nona). Diese sind:
Stop Convert T [ 22h ]
Stops temperature conversions when the device is in continuous conversion mode (1SHOT = 0).
Read Temperature [ AAh ]
Reads last converted temperature value from the 2-byte temperature register.
Access TH [ A1h ]
Reads or writes the 2-byte TH register.
Access TL [ A2h ]
Reads or writes the 2-byte TL register.
Access Config [ ACh ]
Reads or writes the 1-byte configuration register.
Software POR [ 54h ]

Soweit ich das verstanden habe, sind die Befehle im Zahlensystem Hex. Als ich versuchte, diese Werte in Bascom zu verwenden bekam ich Compilerfehler. Ich vermute, ich muss die Eingabe eines Wertes in Hex irgendwie deklarieren. Leider war die Bascom-Hilfe wenig hilfreich.

Vielleicht möchte jemand Licht in meine massive Dunkelheit bringen?

peterfido
18.03.2012, 09:30
Für z.B. HEX 20 kommt da einfach &H20 hin. Dein Beispiel mit Stop Convert T wäre dann &H22
Der Compiler macht dann daraus eh wieder ein Byte.

Aus irgendwelchen Gründen läuft bei mir meist SoftTWI besser als Hardware.

Thomas E.
18.03.2012, 10:49
Für z.B. HEX 20 kommt da einfach &H20 hin. Dein Beispiel mit Stop Convert T wäre dann &H22

Alles klar, eigentlich hätte ich auch selbst draufkommen sollen. ;)


Aus irgendwelchen Gründen läuft bei mir meist SoftTWI besser als Hardware.
Ich benutze ebenfalls Soft-I2C.

Inzwischen konnte ich bereits das EEPROM ansprechen, aber beim DS1631 beiße ich mir noch die Zähne aus. Mein Ansatz:
Laut Datenblatt funktioniert das Auslesen der Temperatur so (Seite 12, Absatz "2-Wire Reads"):

I2C start
Control Byte
Read Temperature Command
ACK from device
Repeated start
Conrol byte with same Slave Adress
Read ACK (Byte 1)
Read NACK (Byte 2)
Stop

Das R/W-Bit im Control-Byte muss 1 sein, damit dem DS1631 eine Leseoperation mitgeteilt wird.
Ist das so richtig?

Klebwax
18.03.2012, 10:55
I2C start
Control Byte
Read Temperature Command
ACK from device
Repeated start
Conrol byte with same Slave Adress
Read ACK (Byte 1)
Read NACK (Byte 2)
Stop

Das R/W-Bit im Control-Byte muss 1 sein, damit dem DS1631 eine Leseoperation mitgeteilt wird.
Ist das so richtig?

Die erste Operation ist ein Write, du schreibst das Kommando. Die Zweite ist ein Read, du liest die Werte.

MfG Klebwax

Thomas E.
18.03.2012, 11:16
Hallo Klebwax!


Vielen Dank für deine Antwort.
Nach nochmaligen Durchlesen des entsprechenden Absatzes im Datenblatt habe ich jetzt auch gesehen, dass das R/W-Bit beim ersten Mal 0 sein muss.

Hier mein erster Versuch:

Do

If S2 = 0 Then

Led = 0

Waitms 500

Incr Count

I2cstart
I2cwbyte &H90
I2cwbyte &HAA
I2crepstart
I2cwbyte &H91
I2crbyte Var1 , Nack
I2crbyte Var2 , Ack
I2cstop
Waitms 10

Cls
Lcd "Gelesen:"
Locate 2 , 1
Lcd "Var1=" ; Var1
Lcd " "
Lcd "Var2=" ; Var2
Lcd " "
Lcd Count

Waitms 100

Led = 1

End If

Loop
Als Var1 bekomme ich 22, wenn ich die Platine mit dem Föhn "anföhne" steit dieser Wert kontinuierlich auf etwa 38. Var2 bleibt immer bei 255. Ich nehme an, dass der DS1631 standardmäßig im 8-bit Modus arbeitet?

peterfido
18.03.2012, 11:17
Da wäre Code zum gucken besser. Bei meinen Bauteilen ist die Leseadresse um 1 höher als die Schreibadresse.

Config:

Const Si4703_read_addr = &H21 ' Lese Adresse SI4703
Const Si4703_write_addr = &H20
Lesen:

I2cstart
I2cwbyte Si4703_read_addr
For I = 0 To 31
I2crbyte Register_read_byte(i) , Ack
Next I
I2cstop


Schreiben:

Si4703_write_register:
I2cstart
I2cwbyte Si4703_write_addr
For I = 1 To Anzahl
I2cwbyte Registerbyte(i)
Next I
I2cstop
Return


Hat sich überschnitten. Jetzt ist ja code zum gucken da.

for_ro
18.03.2012, 11:59
I2cwbyte &H91
I2crbyte Var1 , Nack
I2crbyte Var2 , Ack

Nack und Ack müssen genau anders herum.

Thomas E.
18.03.2012, 12:56
Nack und Ack müssen genau anders herum.
Danke. Hätte ich die Bascom-Hilfe besser gelesen wäre mir dieser Fehler erspart geblieben:
Specify ACK if there are more bytes to read.
Specify NACK if it is the last byte to read.

Jetzt bekomme ich die zwei Werte. Der erste scheint relativ konstant zu sein, der zweite springt bei Änderung der Temperatur. Interessant wird jetzt die Umrechung. Ich versuche, einen Lösungsansatz zu finden.

Thomas E.
18.03.2012, 16:37
Ich habe mich jetzt stundenlang an der Berechnung versucht, bin aber nicht wirklich zufrieden damit:
Das erste Byte ergibt die Ganzzahl für die Temperatur, zusätzlich bestimmt Bit 7 das Vorzeichen. Das zweite Byte besteht eigentlich nur aus vier Bits, weil die letzten vier Bits immer null sind.
Somit:
Byte1 = Ganzzahl
Byte2 viermal nach rechts shiften und das Ergebnis mit 0,0625 multiplizieren ergibt jenen Wert, der zur Ganzzahl addiert werden muss.

Am Papier sowie am µC funktioniert es, aber durch die notwendige Single-Variable frisst es einiges an Speicherplatz.

Später möchte ich die Werte in einem EEPROM ablegen, ich nehme an das es einfacher ist, die beiden Bytes alleine nacheinander abzuspeichern (Zelle 1: Byte1, Zelle2: Byte2) und erst vor der Ausgabe umzuwandeln. Das Abspeichern einer Single-Variable wäre mit großem Aufwand verbunden, oder sehe ich das falsch?

for_ro
18.03.2012, 17:00
Hallo Thomas,
für eine Single müsstest du halt 4 Byte abspeichern. Halte ich hier aber sowieso für unsinnig, da du nur 16 verschiedene Werte hinter dem Komma hast.
Ich habe es bei mir so gemacht, dass ich die 16 berechneten Werte in Data Befehlen abgespeichert habe. Die legst du einmal fest und gibst sie dann nur noch nach dem Komma aus. Das Addieren habe ich also auch nicht gemacht. Warum erst eine Single verwenden um sie dann für die Ausgabe wieder umzuwandeln.
Bei Vergleichen habe ich dann nur den Ganzzahlanteil genommen. Damit hast du dann auch gleich eine Hystere mit eingebaut.

Thomas E.
19.03.2012, 15:03
Hallo For_ro!


Danke für deine Antwort.
Du verwendest eine interessante Variante, aber ich habe mich bereits mit der Single-Methode abgefunden. Es ist einfacher und geht relativ schnell. Ausserdem benötige ich in meiner Anwendung sowieso weitere Single-Berechnungen. Interresanterweise steigt der Verbrauch an Flash-Speicher zwar mit der ersten Deklaration einer Single-Variablen stark an, bei der Deklaration von weiteren Single-Variablen wird allerdings nur wenig mehr Speicherplatz verbraucht.