Hallo Mikrocontroller-Fans,
ich versuche seit kurzem einen I2C-Sensor anzusteuern, leider scheint
das einfach nicht zu funktionieren. Hab schon mal gegoogelt und auch
hier im Forum ein bisschen gestöbert und geschaut, wie andere das gelöst
haben - nur scheint es immer noch nicht zu funktionieren. Hier ein
Ausschnitt aus der main.c:
i2c_transmit_byte(0xEE);// Startet mit der Temperaturkonversion
11
i2c_stop();
12
13
i2c_start();
14
i2c_transmit_byte(0x90);
15
i2c_transmit_byte(0xAA);// Sensor soll die Temperatur zurueckgeben
16
_delay_ms(10);
17
while(1)
18
{
19
i2c_start();
20
i2c_transmit_byte(0x91);
21
temp1=i2c_receive_byte();
22
temp2=i2c_receive_byte();
23
i2c_stop();
24
USART_String_Transmit(itoa(temp1,s,10));
25
USART_String_Transmit(itoa(temp2,s,10));
26
_delay_ms(100);
27
}
28
29
}
Wenn ich das Programm ausführe, so sendet mir der Sensor nur Nullen,
woran könnte das liegen? Habe schon versucht, die Sendezeiten zu ändern
und habe auch schon die Includes geprüft - sieht eigentlich alles
richtig aus. Ach ja, ich betreibe den Sensor am RnControl (da gibt es
auch direkt einen I2C Anschluss). Die Includes habe ich auch mal mit
angehangen - habe alles ein wenig auskommentiert.
Es gibt ähnliche Forenbeiträge mit Nutzung von Bibliotheken und Co. aber
ich möchte keine fertige Bibliothek nutzen - würde es lieber selbst hin
bekommen ;)
Vielleicht kann mir ja jemand helfen?
MfG,
Rob
Naja, ich habe beide Versionen gesehen - einige schreiben dort ein Stop
dazwischen, andere nicht. Laut Datenblatt gehört das ein Repeated Start
hin - so gesehen kein Stop sondern nur ne neue Startbedingung, daran
habe ich mich gehalten. Habe vorns noch eniges getestet, aber immer das
Selbe Ergebnis. Werde mir demnächst einen zweiten DS1621 holen und mit
dem neuen Exemplar noch einmal testen.
MfG, Robert
Hallo Robert,
Die while () loop ist nicht notwendig. Du musst aber ACK und NACK beim
Empfang der Daten vom MASTER aus senden. Sieh Dir den PIC Beispiels Code
unten an:
int main(void)
{
USART_init();
i2c_init();
unsigned char temp1, temp2;
char s[7];
i2c_start(); // setzt ein Start-Kommando
i2c_transmit_byte(0x90); // uebermittelt Adresse+Write (1001000)
i2c_transmit_byte(0xEE); // Startet mit der Temperaturkonversion
i2c_stop();
// Per Seite 9:
// Ich kenne Deinen Compiler nicht:
// Finde syntax raus wie man ACK und NACK hier senden soll
// hier ein Beispiel mit CCS PIC Compiler:
// Neue Abfrage der Daten:
i2c_start();
i2c_write(0x90);
i2c_write(0xaa);
_delay_ms(100);
i2c_start();
i2c2_write(0x91);
temp2=i2c_read(ACK); // MSB empangen, Master sendet ACK
temp1=i2c_read(NACK); // LSB empfangen, Master sendet NACK
i2c_stop;
USART_String_Transmit(itoa(temp1,s,10));
USART_String_Transmit(itoa(temp2,s,10));
_delay_ms(100);
// Dem Datenblatt nach muesste das funktionieren. Wenn das NACK nicht
// gesendet wird, dann bleibt der DS1621 haengen. Ist ganz wichtig.
// Die eingefuegten ACK/NACK gehen bei Dir vielelicht nicht so:
}
mfg,
Gerhard
Danke für die Sache mit dem Ack und Nack Gerhard, ich wusste doch, da
fehlt was ;)
Habs jetzt umgeschrieben (ich hoffe richtig) und jetzt bekomme ich von
dem Sensor 255 255 zurück (alles Einsen), wenn ich eine Messung starte -
also stimmt wahrscheinlich noch etwas nicht.
Werd nochmal alles durch schauen, vielleicht finde ich ja noch einen
Fehler.
Gibt es eigentlich Festlegungen, wie lange eine Pause bei den
I2C-Kommandos sein muss?
Ich hänge den momentanen Code als Anhang mit ran.
MfG,
Robert
Kommando zurück - hab jetzt doppelt nacheinander das ack drinnen, wie
ich gerade sehe. Hab ich wieder verändert - dennoch tut sich nichts
weiter.
MfG, Robert
Hallo Robert,
mir ist die Library von Dir nicht bekannt. Ich habe mir mal die
Beispiele von Peter Fleury angesehen und in seiner Library verwendet er
integrierte I2CREAD Funktion mit ACK oder NACK Eigenschaft. Allerdings
verwendet er im Vergleich zu Dir die TWI-Hardware des AVRs.
Nur glaube ich nicht dass das im Augenblick Dein Problem ist, da ein
falscher Gebrauch des ACK/NACK nur den DS1621 verwirrt. Zumindestens ein
gueltiges Datenpaket muesste durchkommen.
Villeicht stimmt auch irgendwas noch nicht mit Deiner Hardware.
Ueberpruef noch einmal die Einstellungen der I2C Port pins, pull-up
Widerstaende. Kurzschluss nach Vdd bei der SDA Leitung, etz.
Schau Dir mal auch die library von Peter Fleury an zum Vergleich:
http://homepage.hispeed.ch/peterfleury/group__pfleury__ic2master.html
Ich habe mir Deine I2c.c library angesehen und bin der Ansicht dass da
massive Fehler drin sind.
Zum Beispiel in der i2c_start() werden nur die Direction Registers
manipuliert und nicht der Zustand der SCL/SDA pins. Dafuer ist PORTC da.
Um SDA auf Low zu setzen, muesste man schreiben:
PORTC &= (0 << SDA);
den Pin wieder auf H zu setzen: PORTC |= (1 << SDA);
Die 10ms delay ist nicht notwendig und kann mit NOPS erzielt werden.
Nimm besser die Library von Peter wenn Du TWI Hardware zur Verfuegung
hast. Wenn es mit emulation gehen muss, dann musst die Deine Library
verbessern. (Ist die vom Internet? Von wem? ) Welchen Compiler nimmst Du
her? Dein Quellcode gibt leider keine Auskunft welchen AVR Du
verwendest.
Vielleicht kann Dir jemand vom Forum besser helfen da ich AVRs nur mit
CodeVision programmiere und dort gibt es integrierte I2C Libraries die
garantiert funktionieren.
mfg,
Gerhard
Hallo an alle.
Habe den Fehler gefunden - der Sensor ist defekt. Hab mir ein neues
Sample schicken lassen und mit dem gehts^^
Den Code hatte ich selbst geschrieben mit WinAVR, ich verwende einen
Atmega32. Hab noch einiges verändert - aber im Grundprinzip ist der Code
ähnlich geblieben.
Aber ihr habt natürlich recht - Libraries sind besser, vor allem, wenn
man das später mal auf nem anderen Mc haben möchte. Wollte jedoch einmal
selbst probieren und die Basics lernen - was nun zum Glück auch
funktioniert hat.
Danke nochmal,
Robert