Hallo an alle Ich hab wieder ein Problem ;) Ich hoffe ihr könnt mir helfen :) Ich hab hier einen LM75 Temperatursensor der über I²C angesteuert wird., Als Prozessor hab ich einen Mega 8. Als Basisaddresse hat der LM75 90. Jedoch verstehe ich die Ansteuerung noch nicht wirklich. Ich möchte damit nur Temperaturen auslesen Als I²C Lib will ich die Procyon Bibliothek verwenden. Nur leider komme ich damit überhaupt nicht zusammen. Kann mir bitte wer eine Funktions Code zum Auslesen der Temperatur zeigen?? Oder kann mir wer das erklären? Danke im Voraus Gruß Robert
Hallo Ich bin auch Anfänger. Ich habe es mit der unten genannten Ansteuerung hingebracht. http://sandiding.tripod.com/Bertys.html Gruß
Hallo Eine Lib für den LM75 will ich eigentlich nicht nehemn, da ich den I²C Bus verstehen will ;) Ich hab einmal etwas geschriben: #include <avr/io.h> #include <stdlib.h> #include "i2c.h" //Procyon I2C LiB #define LM75_ADRESS 0x97 int lm75_read(void); TEMPERATUR struct { uint8_t high; uint8_t low; } temp; int lm75_read(void) { TEMPERATUR struct { uint8_t high; uint8_t low; } temp; i2cSendStart(); i2cSendByte(LM75_ADRESS); //Sende Adresse i2cSendByte(0X00); //Temperature Register i2cSendSart(); temp.high = i2cReceiveByte(); temp.low = i2cReceiveByte(); i2cSendStop(); return(0) } Kann das so Funktionierten? Danke im Voraus Gruß Robert
Hallo Robert hab vor einiger Zeit sowas mit einem LM92 gemacht Default nach Power Up ist das Temperaturregister - darum kannst Du in Deinem Quelltext die Sache mit dem Temperaturregister weglassen Die Temperatur steht in den Bits D7 - D15. Übertragen werden zwei Byte D0 - D7 Low Byte D8 - D15 High Byte Du musst die Bits so schieben damit die Temperatur mit D7 rechtsbündig in einem Register steht Nun musst Du die ganze Sache in °C umwandeln - dazu teilst Du einfach durch 128 (2 hoch 7 = 128 da Du um 7 Stellen nach rechts schieben musstest) Hoffe ich hatte das noch richtig in Erinnerung
Sieht doch gar nicht so schlecht aus. Die Adresse muss natürlich 0x90 sein und die struct kannst du als typedef deklarieren und danach verwenden. Ach ja, und dann muss zuerst die Adresse mit write-Bit gesendet werden, nach dem repeated start nochmal mit read-Bit. Etwa so: ... #define LM75_ADDRESS 0x90 int lm75_read(void); typedef TEMPERATUR struct { uint8_t high; uint8_t low; }; int lm75_read(void) { TEMPERATUR temp; i2cSendStart(); i2cSendByte(LM75_ADDRESS); //Sende Adresse mit write Bit i2cSendByte(0x00); //Temperature Register i2cSendStart(); i2cSendByte(LM75_ADDRESS | 1); //Sende Adresse mit read Bit temp.high = i2cReceiveByte(); ...
Hallo Tom Danke :) Warum aber i2cSendByte(LM75_ADDRESS | 1); Warum das?? Nach dem Repeated Start muss zuerst wieder die Adresse Senden und das Register, das ich auslesen will, oder?? Ich will ja aus dem Temperaturregister (0x00) auslesen. Warum also das |1? Wenn ich hintereinander das High und das Low Byte auslese, stimmt da die Adresse der Bits automatisch? (Springt der Chip beim 2. Auslesen (Low) automatisch zur Lowbyteadrese??) Danke im Voraus Gruß Robert
Hallo an alle Ich hab das mal geändert: #include <avr/io.h> #include <stdlib.h> #include "i2c.h" //Procyon I2C LiB #define LM75_ADRESS 0x97 int lm75_read(void); struct TEMPERATUR { uint8_t high; uint8_t low; } temp; int lm75_read(void) { i2cSendStart(); i2cSendByte(LM75_ADRESS); //Sende Adresse mit write Bit i2cSendByte(0x00); //Temperature Register i2cSendStart(); i2cSendByte(LM75_ADRESS | 1); //Sende Adresse mit read Bit temp.high = i2cReceiveByte(FALSE); temp.low = i2cReceiveByte(FALSE); i2cSendStop(); } int main(void) { i2cInit(); i2cSetBitrate(100); lm75_read(); return(0); } Nur wenn ich es compilieren will, dann bekomm ich immer 2 Fehlermeldunden: lm75.c:23: error: void value not ignored as it ought to be lm75.c:24: error: void value not ignored as it ought to be Warum??? Danke im Voraus Gruß Robert
Hallo Robert, hab auch gerade erst diesen Baustein verwendet und kann zumindest hierzu was sagen: Warum aber i2cSendByte(LM75_ADDRESS | 1); Warum also das |1? Das |1 steht dafür, dass man vom Slave lesen möchte |0. Das Temperaturregister wird automatisch ausgelesen, du brauchst also kein 0x00 senden. Ich habe den LM75 in ein buf[1] ausgelesen und so ausgegeben: fprintf(uart, "Temperatur %d.%d\n\n", buf[0], (buf[1] ? 5 : 0)); Hoffe, dass ich dir etwas weiter helfen konnte. Gruß, Stefanie
Hab mir mal deinen Code angeschaut, also ich denke, dass es so reicht: int lm75_read(void) { i2cSendStart(); i2cSendByte(LM75_ADRESS | 1); //Sende Adresse mit read Bit temp.high = i2cReceiveByte(FALSE); temp.low = i2cReceiveByte(FALSE); i2cSendStop(); }
Hallo Stefanie So hab ich es auch. Nur leider bekomm ich immer die eine Fehlermeldung vom Compiler: lm75.c:21: error: void value not ignored as it ought to be Kann das mit dem struct zusammenhängen?? Gruß Robert
Weiß denn keiner was da los ist?? Ich bekomm die Fehlermeldung nicht weg :( Ich weiß auch nicht was sie bedeutet :( Gruß Robert
Hallo Werner Ich bekomm 2-mal dioe Fehlermeldung. Einmal in 20 und einmal in 21. Die Zeilen 20 und 21: temp.high = i2cReceiveByte(FALSE); temp.low = i2cReceiveByte(FALSE); Gruß Robert
Hallo inline void i2cReceiveByte(u08 ackFlag) { // begin receive over i2c if( ackFlag ) { // ackFlag = TRUE: ACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // ackFlag = FALSE: NACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } } Das ist der Prototyp aus der Procyon i2c Lib. Gruß Robert
inline void i2cReceiveByte(u08 ackFlag) void bedeutet dass die Fn NICHTS zurückliefert, die Zuweisungen temp.high = i2cReceiveByte(FALSE); temp.low = i2cReceiveByte(FALSE); sind als Unzulässig. Du musst Dir eine FN suchen die auch einen Rückgabewert liefert der an temp.high bzw temp.low zugewiesen werden kann.
Danke Werner Hätte ich eigentlich selber erkennen müssen :( Jetzt muss ich nur noch das Register auslesen, oder ? Werde ich mal probieren Gruß robert
Hallo an alle So es funktioniert jetzt so einigermaßen. Nur die Temperaturs stimmt noch nicht wirklich. Hier nun die read Funktion: int lm75_read(void) { i2cSendStart(); i2cSendByte(LM75_ADRESS | 1); //Sende Adresse mit read Bit i2cSendStart(); i2cReceiveByte(FALSE); temp.high = i2cGetReceivedByte(); i2cReceiveByte(FALSE); temp.low = i2cGetReceivedByte(); i2cSendStop(); } Der Prototyp von i2cGetReceivedByte(): inline u08 i2cGetReceivedByte(void) { // retieve received data byte from i2c TWDR return( inb(TWDR) ); } temp.low ist ja die Kommastelle. Sie steht linksbündig in der Variable temp.low. Wenn ich sie nach Rechts verschiebe und mit 5 Multipliziere, hab ich die Kommastelle oder?? temp.low = (temp.low>>=7)*5; Soe meine ich das. Die High Variable macht mir jedoch noch mehr Sorgen. Ich bekomm immer 0xFF (255) empfangen. Den empfangenen Wert muss ich ja durch 2 Teilen, oder?? 125°C entspricht 1111 1010 = 0xFA = 250 25°C enspricht 110010 = 32 = 50 Daraus schleiße ich, dass ich den Wert durch 2 dividieren muss, oder?? Muss ich sonst noch etwas mit der Zahl machen?? Gruß Robert
Hallo an alle So jetzt hab ich die Routine für das Auswerten der Zahlen Fertig. if(bit_is_set(temp.low, 0)) nachkomma = 5; else nachkomma = 0; temp.low >>= 1; temp.high <<= 7; ganzzahl= temp.low | temp.high; Das funktioniert auch so. Leider steht nach dem Auslesn im Low und im High Byte 255. Also stimmt beim Auslesen des LM75 irgendetwas nicht. Was stimmt den da nicht?? Ich hoffe es kann mir wer helfen Danke im Voraus Gruß Robert
Ich rate mal: 1. Du sagst die Adresse des LM75 ist 90, im Beispiel steht 0x97. Wieso? 90 ist gleich 0x5A, da bei I2C mit 7 Bit adressiert wird und das 8. Bit Lesen/Schreiben auswählt, müsste die korrekte Adresse 0xB4 lauten (0x5A um eine Stelle nach rechts geschoben). 2. Mit dem Aufruf von i2cReceiveByte() wird zwar der Empfang eines Bytes gestartet, aber wann ist dieser abgeschlossen? Da du sofort danach das TWDR Register ausliest, kann der Transfer evtl. noch nicht abgeschlossen sein. Du solltest das TWINT Bit abfragen, bit dieses gesetzt ist, dann erst auslesen. 3. Ist die I2C Schnittstelle korrekt initialisiert? Ist die Bitrate in TWBR gesetzt? 4. Temperaturumrechung ist einfach: temp.high enthält schon den Ganzzahlanteil der Temperatur. temp.low ist entweder 0 (für 0.0) oder 0x80 (für 0.5 Grad). Somit wäre dein Code: if(bit_is_set(temp.low, 7)) nachkomma = 5; else nachkomma = 0; Gruss
> 1. Du sagst die Adresse des LM75 ist 90, im Beispiel steht 0x97. > Wieso? Ein LM75 kann je nach Hardwarebeschaltung zwischen 0x90 und 0x97 liegen, du kannst also maximal 8 davon an einem Bus betreiben. Wie du deine Hardware beschaltet hast, weißt du selbst am besten. > 90 ist gleich 0x5A, Nein, es war 0x90 gemeint. > da bei I2C mit 7 Bit adressiert wird und das 8. Bit Lesen/Schreiben > auswählt, müsste die korrekte Adresse 0xB4 lauten (0x5A um eine > Stelle nach rechts geschoben). Nein, erstens wäre 0x5a ein Bit nach rechts geschoben 0x2d (du hast nach links geschoben), zweitens brauchst du da nichts schieben, da ja nur das oberste Bit zwischen Lesen und Schreiben unterscheidet, die unteren 7 Adressbits bleiben gleich.
Hallo an alle MIt den Adressen bin ich dazwischen schon selber drauf gekommen. Als Adresse hab ich 1001 1110 = 0x9E. Wenn ich das Read/Write Byte noch setze, hab ich 1001 1111 = 0x9F. Hardware funktionert. Ich hab das mit einem Basic Codeschnipsel getestet. Funktioniert die Proycon Lib erfolgreich?? Oder soll ich das ganze selber zu Fuß schreiben? Vielleicht habt ihr noch ein paar Tipps ;) Gruß Robert
Hallo an alle Hallo an alle Ich hab nun die I2C Routine fertig geschrieben Smile Jedoch funktioniert sie noch nicht. Ich finde jedoch keinen Fehler :( Ich hoffe es kann mir wer helfen. Im Anhang ist der Code Danke im Voraus Gruß Robert
Es wäre vielleicht ganz gut zu wissen, was nicht geht.. Zu sagen, dass etwas nicht geht, bringt nichts. Also eine etwas ausführlichere Fehlerbeschreibung wäre ganz nett. Bis dann, Nico
Hallo Nico Compilieren und Flashen kann ich es. Jedoch funktioniert das auslesen nicht. Am Display steht 79.0. In den Variablen temp.ghi und temp.low steht 158. Gruß Robert
Die Adresse bei i2c_send_start() muss 0x9f lauten, da du ja lesen willst. In i2c_read() wird die Adresse ignoriert. Ausserdem stimmt deine Umrechung nicht. Hab ich aber 6 Beiträge weiter oben schon geschrieben. Gruss
Hallo an alle Die Umrechnung ist erstmals egal Hier nun meine Receive Code mit Acknoledgement: Ich hab nach jedem Befehl eine Lcd Ausgabe eingeführt, um zu sehen wo es hakt. int i2c_read_ack(void) { lcd_putc('1'); TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); lcd_putc('2'); while(!(TWCR & (1<<TWINT))); lcd_putc('3'); if(!(TWSR & 0x50)) { lcd_putc('4'); return -1; } lcd_putc('5'); return TWDR; } Am Display wird aber nur 12 angezeigt. Es hängt also bei while(!(TWCR & (1<<TWINT))); Weiß irgendwer, was da falsch sein könnte. Ich hab jetzt echt keinen Plan mehr Danke im Voraus Gruß Robert
Hallo Leute. Ich wollte mal fragen ob ich hier ein wenig Hilfe bekommen kann. Ich versuche schon seid paar Tagen mit I2C die Temperatur aus meinem LM75 aus zu lesen, aber irgendwie will es nicht funktionieren. Könnt ihr mir da vielleicht weiter helfen?!? Adresse ist 1001001 der C code ist: int data1, data2; i2c_start(); i2c_write(0x93); data1 = i2c_read(); data2 = i2c_read(); i2c_stop(); Danke schon mal im Vorraus!
Die Adresse bei i2c_write(...) muss 0x92 lauten! (und nicht 0x93) Ansonsten müsste das so funktionieren (wenn der Rest drumherum stimmt). Beachte aber, dass du den LM75 nicht zu schnell hintereinander ausliest, weil der immer ein bißchen Zeit braucht um eine neue Messung durchzuführen (ich glaub so um die 100ms).
ach sorry, stimmt ja garnicht. du willst ja auslesen. also ist 0x93 als adresse schon richtig.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.