Hallo zusammen,
ich möchte mit meinem ATmega32 die Sensorwerte (Temperatur, Druck,
Luftfeuchtigkeit) von einem MS8607-PHT-Sensor auslesen.
Den ATmega32 programmiere ich in C mit Microchip Studio.
Für den Sensor habe ich diese Bibliothek gefunden:
https://github.com/TEConnectivity/MS8607_Generic_C_Driver
Um die Bibliothek zu benutzen, muss die Datei i2c.h platformspezifisch
implementiert werden:
Ich habe meine Implementierung der Funktionen angehängt (i2c.h).
Die Werte lese ich dann wiefolgt in meiner main aus:
1
float*p,*h,*t;
2
ms8607_read_temperature_pressure_humidity(t,p,h);
In meiner Implementierung der Funktionen muss aber ein Fehler vorliegen,
denn alle drei Sensorwerte sind 0,0
Was hab ich bei der Implementierung falsch gemacht?
M. K. schrieb:> Was hab ich bei der Implementierung falsch gemacht?
Zunächst mal Prinzipielles.
In eine *.h Datei gehört weder (Programm-)Code noch Variablen-
Deklaration. Dagegen ist eine Typ-Definition (deine Struct) dort
richtig. Wohlgemerkt eine Typ-Definition, nicht die Variable
(struct i2c_master_packet{} ) selbst.
holperdistolper schrieb:> In eine *.h Datei gehört weder (Programm-)Code noch Variablen-> Deklaration. Dagegen ist eine Typ-Definition (deine Struct) dort> richtig. Wohlgemerkt eine Typ-Definition, nicht die Variable> (struct i2c_master_packet{} ) selbst.grundschüler schrieb:> sieht so aus, als würde es i2c.c nicht geben
Für einen ersten Test habe ich habe die Funktionen einfach mit in der
Header-Datei definiert.
Ihr habt vollkommen Recht, dass sowas da eigentlich nicht hingehört.
foobar schrieb:> Sollte das nicht eher:float p, h, t;> ms8607_read_temperature_pressure_humidity(&t, &p, &h);> sein?
Kommt das gleiche bei raus.
Die Bibliothek sagt hier nur, dass die Funktionen implementiert werden
müssen, gibt aber keine nähere Auskunft als den Funktionsnamen.
Wenn mir jemand sagen kann, was die Funktionen inhaltlich machen sollen,
wäre mir das auch schon eine große Hilfe.
Was die Funktionen machen sollen, steht doch in ihren Namen.
Und implementieren musst du nicht mehr und nicht weniger als eine
vollständige I2C-Kommunikation.
Deine Überschrift ist insofern völlig falsch, als du ja überhaupt keine
I2C-Lib hast. Der „generic driver“ ist keine, der braucht eine.
i2C-libs für AVR gibt es einige, Google wird dir da sicher weiterhelfen.
Wenn du gar nicht weiterkommst, schau halt mal in die Artikelsammlung
hier.
Oliver
Es liegt zwar nahe dass es an der von dir implementierten HAL liegt,
aber woher weißt du das es kein Hardware Problem ist.
Spannung am Sensor OK?
Alles richtig angeschlossen?
Pullups haben gültige Werte?
Ansonsten sieht für mich die Implementierung des TWI Status falsch aus.
1
enumstatus_code{
2
STATUS_OK=0x00,
3
STATUS_ERR_OVERFLOW=0x01,
4
STATUS_ERR_TIMEOUT=0x02,
5
};
6
uint8_tI2C_Status()
7
{
8
uint8_tstatus;
9
status=(TWSR&0xF8);
10
returnstatus;
11
}
Im DB wird der Status anhand der letzten Aktion überprüft(siehe S.182ff)
Beispiel aus dem DB:
1
if((TWSR&0xF8)!=START)
2
ERROR();
Wenn das nicht stimmt wird in jeder anderen Funktion die Sequenz
abgebrochen.
Dann steht das auf den Variablen was vorher draufstand. Wahrscheinlich
0.
Du musst erstmal verstehen, wie der i2c-bus funktioniert.
Wenn die i2c-lib in das Projekt eingebunden ist, erstmal testen ob die
Kommunikation slave ./. master stattfindet:
1
uint8_ti2c_start(uint8_tadr)
2
{
3
i2c_start_cond();
4
uint8_tAckBit=i2c_write(adr);
5
returnAckBit;
6
}
Erst wenn hier das Ack-Bit vom slave korrekt zurückkommt funktioniert
der Bus. Dann kannst du dich um den ganzen Rest kümmern.
MaNi schrieb:> aber woher weißt du das es kein Hardware Problem ist.> Spannung am Sensor OK?> Alles richtig angeschlossen?> Pullups haben gültige Werte?
Ich habe noch ein weiteres Gerät am I2C-Bus angeschlossen und das
funktioniert einwandfrei, dafür hatte ich eine fertige Bibliothek
gefunden.
MaNi schrieb:> Lass dir Mal noch bei deinem Aufruf den Status zurückgeben
Ich bekomme den Status 2 / "ms8607_status_i2c_transfer_error" beim
Aufruf von ms8607_read_temperature_pressure_humidity zurück.
Die Werte t, p und h behalten den Wert, den sie vor dem Funktionsaufruf
hatten, werden also gar nicht beschrieben.
M. K. schrieb:> dafür hatte ich eine fertige Bibliothek> gefunden.
Ja, dann nimm die doch. Zwei verschiedene I2C-libs auf der selben
Harwareschnittstelle gibt eh nur Chaos.
Oliver
Vielleicht ist der Ansatz 'fertige Bibliotheken' zu nehmen nicht der
richtige?
Evtl sollte man verstehen, was auf dem Bus passiert. Manchmal wird ja
auch nur ein Status-Bit falsch interpretiert. Oder der Pull-up passt
nicht, was man mit einem Oszilloskop erkennen könnte. Oder die
Parameter-Übergabe muss mit Pointern erfolgen. oder oder oder....
Wenn man in diesen Bereichen arbeitet, dann sollte man C können, wissen
was ein I2C Bus macht und auch ein Scope bedienen können. Einfach nur
fertige Bibliotheken zusammen linken, das reicht nicht aus.
M. K. schrieb:> Wie implementiere ich die folgenden Funktionen für den ATmega32 in C?
Du scheinst ein genialer Quellcode-Finder zu sein.
Also mal im Ernst: Verstehst du denn überhaupt den I2C-Bus als solchen?
Weißt du dann, was eine Startcondition und eine Stopcondition ist? Und
wie die Bits eines Bytes transportiert werden und dann der Empfänger des
Bytes das mit ACK bestätigt oder nicht, was dann ein NAK ist?
Für mich sieht das Ganze bei dir eher wie ein gequirltes Durcheinander
verschiedener Dinge aus: Was haben Zeiger wie float *p, *h, *t; beim I2C
zu suchen? Natürlich nichts.
Für einen Master-Anschluß das I2C sehe ich nur folgende Funktionen:
1. bool OpenSlave(adresse, R oder W) - darin sind enthalten: Bus als
Master erhalten, Slave adressieren und Datenrichtung festlegen. Das kann
auch mal nicht funktionieren, dann wird der Mißerfolg im Ergebnis
gemeldet. (Bus wird nicht erhalten oder Slave antwortet nicht bzw.
quittiert die Datenrichtung mit einem NAK)
2. bool SendeByte(zu sendendes Byte)
oder
byte EmpfangeByte(bool ob mit ACK oder nicht)
3. void CloseSlave(void) - darin enthalten: Stopcondition und
Busherrschaft aufgeben.
So. alles andere ist eine andere Ebene, insbesondere das Zusammenfügen
eines Temperatur-, Druck- oder Feuchtigkeitswertes aus den Bytes, die da
vom Slave herholbar sein sollten. Ich argwöhne, daß da zunächst an den
Slave eine Adresse für die interessierende Stelle in dessen Ergebnis-RAM
gesendet werden muß und dann erst der jeweilige Wert gelesen werden
kann.
W.S.