LM75 an ATMega 8

OP #804636
Lesenswert?

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 #804798
Lesenswert?

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 #806062
Lesenswert?

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 #806116
Lesenswert?

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 #821174
Lesenswert?

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 #1640845
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren