LM75 an ATMega 8

OP #804636
Hallo,

Nach ein paar Monaten ohne Erfolg komme ich jetzt zu meinem 2. Versuch.
Ich will die Temperatur aus einem LM75 auslesen.

Software: AVR Studio 4.13 (GCC)
Hardware: ATMega 8

Programmausschnitt:
1
#define LM75_write  144
2
#define LM75_read 145
3
#define FAKTOR 44
4
#define TEILER 0
5

6
void init (unsigned char faktor, unsigned char teiler)
7
{
8
 TWBR = faktor;
9
 TWSR = teiler;
10
}
11

12
unsigned char empf (unsigned char adres)
13
{
14
 unsigned char daten;              //hilfsvariable
15
 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);   //startbedingung
16
 loop_until_bit_is_set(TWCR, TWINT);      //warte bis fertig
17

18
 TWDR = adres;                  //adresse
19
 TWCR = (1<<TWINT) | (1<<TWEN);          //senden
20
 loop_until_bit_is_set(TWCR, TWINT);      //warten bis fertig
21

22
 TWCR = (1<<TWINT) | (1<<TWEN);          //empfang starten
23
 loop_until_bit_is_set(TWCR, TWINT);      //warte bis fertig
24

25
 daten = TWDR;                  //daten abholen
26
 TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);    //ack impuls senden
27
 loop_until_bit_is_set(TWCR, TWINT);      //warte bis fertig
28

29
 TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);  //stoppbedingung
30
 return daten;
31
}
32

33
init(FAKTOR,TEILER);
34

35
wert1 = empf(LM75_read);
36
wert2 = empf(LM75_read);

Die Werte lasse ich mir direkt von einem LCD anzeigen.
leider sind beide Werte immer gleich (ca. 247) und Schwanken nur leicht
Gast
Beim TWI-Interface der AVRs musst du schon vor dem lesen wissen, ob der 
Master ACK'en soll:
1
    //empfang starten, mit ACK antworten:
2
    TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
3
    loop_until_bit_is_set(TWCR, TWINT); //warte bis fertig
4

5
    daten = TWDR;                       //daten abholen
6
    TWCR = (1<<TWINT) | (1<<TWEN);      // KEIN ack impuls senden
7
    loop_until_bit_is_set(TWCR, TWINT); //warte bis fertig

hth. Jörg
OP
Ich habe es jetzt soweit hinbekommen das Ich die Temperatur (1. Byte) 
anzeigen kann, aber wie kann ich jetzt das 2. Byte auslesen?
1
void init (unsigned char faktor, unsigned char teiler)
2
{
3
 TWBR = faktor;
4
 TWSR = teiler;
5
}
6

7

8
void i2c_start (unsigned char adres)
9
{
10
 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);    //start
11
 loop_until_bit_is_set(TWCR, TWINT);
12
 TWDR = adres;                    //adresse eingeben
13
 TWCR = (1<<TWINT) | (1<<TWEN);            //freigeben (senden)
14
 loop_until_bit_is_set(TWCR, TWINT);
15
}
16

17
void i2c_stopp (void)
18
{
19
 TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);    //stopp 
20
}
21

22

23
void ack (void)
24
{
25
 TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);      //ack senden
26
 loop_until_bit_is_set(TWCR, TWINT);
27
}
28

29

30
unsigned char empf (void)
31
{
32
 unsigned char daten;
33

34
 TWCR = (1<<TWINT) | (1<<TWEN);            //freigeben (empfangen)
35
 loop_until_bit_is_set(TWCR, TWINT);
36
 daten = TWDR;                    //daten empfangen
37
 return daten;
38
}
39

40
 init(44,1);
41

42
 i2c_start(0x91);
43
 ewert = empf();
44
 ack();
45
 //ewert2 = empf();
46
 i2c_stopp();
Gast
Hallo René.

Jörg sagte ja bereits, daß du das ACK flag setzen mußt. Also ein empfang 
mit TWEA und eins ohne.
1
   i2c_start(0x91);
2
   event1=empf_ACK();
3
   event2=empf_NACK();
4
   i2c_stop();

Olaf
Gast
Ich hätte dann noch eine 'etwas' weiter entwickelte Version (im Anhang).
Aber sobald du richtig begriffen hast wie das TWI funktioniert, schau 
dir mal die TWI-Library von P. Fleury an (http://jump.to/fleury), die 
funktioniert dann mit Interrupts -- ohne jedesmal das ganze Programm 
aufzuhalten.
Außerdem gibt's für den Interruptbetrieb noch zwei (Master/Slave) 
Appnotes von Atmel (u.a. AVR315, IIRC).

hth. Jörg
Angehängte Dateien:
OP
Habe ich noch vergessen zu erwähnen!

in deinem Code hat sich ein Fehler eingeschlichen! (aber trotsdem Danke 
für den Code!)

und zwar bei dieser zeile:
1
uint8_t ret_val, status;    //return-wert, temp. Variable fuer TWSR

sollte so aussehen:
1
uint16_t ret_val, status;    //return-wert, temp. Variable fuer TWSR
Gast
IMHO müsste folgende Zeile auch anders sein:
1
#define TW_ERROR_MSK 0x1F
sollte
1
#define TW_ERROR_MSK 0x7F
sein

weil die untersten 7 bit des Temperaturwerte undefiniert (siehe 
Datenblatt) sind. Damit die Abfrage auf Kommunikationsfehler 
funktioniert muss man ausserdem beim Lesen diese letzten 7bit def. auf 0 
setzen.
1
return ret_val & ~0x7f;
statt
1
return ret_val;

Das nur so am Rande... wenn mans nicht so macht kanns funktionieren... 
muss aber nicht. Hat bei mir zu Beginn in 90% der Fälle funktioniert, 
dann hab ich ein paar Änderungen an meiner Schaltung gemacht und dann 
war desshalb ein kompletter Ausfall.
Gast
Hallo,
ich probier den Ledtreiber TLC59116 zu beschreiben, klapt aber nicht so 
ganz mit dem I2C Bus:
Könnt Ihr mir bitte sagen was da nicht stimmt?
Mit dem Oszilloskop mess ich keinen Takt an SCL und auch nichts an SDA.

lg Kurt
Angehängte Dateien:

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.