Forum: Mikrocontroller und Digitale Elektronik Frage zur TWI Schnittstelle Atmega8


von Markus (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Problem mit der TWI Schnittstelle. Ich wollte einfach mal 
diese ausprobieren. Ich komme nun einfach nicht weiter und kann mir 
nicht erklären, woran der Fehler noch liegen könnte. Die Schaltung 
besteht aus zwei Atmega8. An die SDA sowie SDL habe ich jeweils einen 
Widerstand an VCC genhangen (jeweils 10kohm). Ab und zu funzt es auch. 
Wenn ich dann die Spannung mehrmals an und aus mache geht es immer noch. 
Verändere ich allerdings die Slave Adresse z.B. zu TWDR=0b11100001; geht 
es wieder nicht. Auch nicht, wenn ich die alte Adresse wieder 
reinschreibe. Woran könnte das liegen?

Es soll hier der Master Receive und Slave Transmitter Mode ausprobiert 
werden. Hier das Programm:



Für den Master:
1
#include <avr/io.h>
2
#include <util/twi.h>
3
4
int main(void)
5
{
6
7
8
  DDRD=0b00000010;
9
  PORTD=0;
10
  int ergebnis=0;
11
12
13
14
   while(1)
15
16
    {
17
// Senden der Startbedingung
18
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
19
while (!(TWCR & (1<<TWINT)))
20
;
21
22
23
24
//Adresse Slave
25
TWDR=0b11000001;
26
27
//Adresse verschicken
28
TWCR = (1<<TWINT)|(1<<TWEN);
29
while (!(TWCR & (1<<TWINT)))
30
;
31
32
33
34
35
36
// Stop senden
37
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
38
while (!(TWCR & (1<<TWINT)))
39
;
40
41
42
43
TWDR=ergebnis;
44
45
46
47
if (ergebnis==8)
48
{
49
50
    PORTD=0b00000010;
51
52
}
53
54
55
}
56
57
return 0;
58
59
}


Für den Slave
1
#include <avr/io.h>
2
#include <util/twi.h>
3
4
int main(void)
5
{
6
7
8
while(1)
9
{
10
11
TWAR=0b11000000;
12
TWDR=8;
13
14
//Slave wird aktiviert
15
TWCR =(1<<TWEA)|(1<<TWEN);
16
17
//warten bis Daten empfangen
18
while (!(TWCR & (1<<TWINT)))
19
;
20
21
}
22
23
return 0;
24
25
}

: Bearbeitet durch User
von Stefanus (Gast)


Lesenswert?

Du solltest herausfinden, an welcher Stelle das Programm hängt und 
welche Signalpegel dabei an den beiden Leitungen vorliegen. Ein Debugger 
und ein Oszilloskop könnte dabei sehr hilfreich sein.
Notfalls tun's auch ein paar LED's, die anzeigen, wo das Programm gerade 
steht.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Markus schrieb:
> TWDR=0b11000001;

Das sieht nach einer Adresse zum lesen aus. (LSB ist high).

> TWDR=ergebnis;
Öh, was wird das? Dann schreibst du ins TWDR? Du müssest jetzt entweder 
eine Subadresse zum Slave schicken oder das Ergebnis aus TWDR lesen und 
nicht schreiben. Erst dann schickst du die Stop Bedingung.

Stefanus schrieb:
> Du solltest herausfinden, an welcher Stelle das Programm hängt und
> welche Signalpegel dabei an den beiden Leitungen vorliegen.

Das ist immer gut. Setze doch im Ablauf immer ein Portpin high und wenn 
die Antwort gut ist, wieder low. Dann kommt das nächste Portbeinchen.

: Bearbeitet durch User
von Markus (Gast)


Lesenswert?

Hallo,

ich danke euch erstmal für eurere Antworten. Den Fehler habe ich behoben 
mit TWDR=ergebnis;

Hier nochmal mein neuer Code:




1
#include <avr/io.h>
2
#include <util/twi.h>
3
4
5
6
7
int main(void)
8
{
9
10
int steuer=1;
11
DDRD=0b00000010;
12
PORTD=0;
13
int ergebnis=0;
14
15
16
17
18
   while(1)
19
20
    {
21
22
if(steuer==1)
23
{
24
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
25
while (!(TWCR & (1<<TWINT)))
26
;
27
28
29
30
TWDR=0b11000001;
31
32
33
TWCR = (1<<TWINT)|(1<<TWEN);
34
while (!(TWCR & (1<<TWINT)))
35
;
36
37
38
39
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
40
while (!(TWCR & (1<<TWINT)))
41
;
42
43
ergebnis=TWDR;
44
45
46
47
48
if (ergebnis==8)
49
{
50
51
    PORTD=0b00000010;
52
53
}
54
55
56
}
57
58
59
60
if(steuer==2)
61
{
62
63
//Slave
64
65
TWAR=0b11000000;
66
TWDR=8;
67
68
//Slave wird aktiviert
69
TWCR =(1<<TWINT)|(1<<TWEA)|(1<<TWEN);
70
71
//warten bis Daten empfangen
72
while (!(TWCR & (1<<TWINT)))
73
;
74
75
76
77
}
78
79
80
81
    }
82
83
84
return 0;
85
86
}



Die Variable steuer soll einfach nur dazu dienen mit 1 den Master und 
mit zwei den Slave zu flashen. Dann brauch ich nicht immer alles 
ausmaskieren. Also ich habe jetzt mal nachgeforscht und festgestellt, 
dass er bis zur folgenden Zeile kommt:
1
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
2
while (!(TWCR & (1<<TWINT)))  
3
;
Er bleibt also in de while-Schleife hängen. Auf dem Osca hab ich mir das 
dann auch mal angeschaut. Dabei musste ich feststellen, das auf SCL nur 
9 Clockzyklen kommen und auf SDA wird die Slaveadresse gesendet und das 
wars dann. Der Slave wird aber angesprochen, aber es werden einfach 
keine Daten an den Master gesendet.

Woran kann das liegen?

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

Atmel hat massenhaft Application Notes. Darunter auch für TWI-Master:

http://www.atmel.com/Images/doc2564.pdf
http://www.atmel.com/Images/AVR315.zip

Und TWI-Slave:

http://www.atmel.com/Images/doc2565.pdf
http://www.atmel.com/Images/AVR311.zip

Jeweils PDF und Software. Also sieh dir an, wie es richtig gemacht wird.

MfG spess

von Markus (Gast)


Lesenswert?

Hallo,

das mag sein, aber ich möchte nicht einfach was blind übernehmen, was 
ich nicht verstehe. Also will ich es erstmal so ausprobieren. Kann mir 
vielleicht jemand sagen, was an dem Code falsch sein könnte?

Lg

von Thosch (Gast)


Lesenswert?

Hmm.
Spess hat dir doch schon den goldenen Tip gegeben.
Von blind übernehmen war übrigens gar nicht die Rede:
spess53 schrieb:
> Also sieh dir an, wie es richtig gemacht wird.

Aber du lehnst das ab und willst mit Gewalt das Rad neu erfinden?

Um noch kurz bei dem Beispiel mit dem Rad zu bleiben:
Anstatt an deinem nicht drehenden eckigen Rad herumzuschnitzen
solltest du dir einfach mal die Beispielquellen und vor allem die Doku 
(incl. Flußdiagrammen) dazu anschauen, und daran nachvollziehen,
wie man lauffähige Räder baut.

Das Vorhandensein dieser Quellen läßt z.B. auch meine Motivation
gegen Null gehen, mich mit deinem Code auseinanderzusetzen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Markus schrieb:
> Hier nochmal mein neuer Code:

Ich will jetzt nicht ein 'Schöner C Stil' Meckere starten, aber ohne 
jegliche Indentation und mit den vielen Leerzeilen ist das schlecht zu 
lesen. (auch für dich, du willst ja logisch vorgehen) Für mich 
jedenfalls ein Grund, mich da nicht tiefer reinzuhängen.

von Markus (Gast)


Lesenswert?

Hallo,

das mag sein, aber ich muss doch nicht für eine private Anwendung mich 
hier soviele Stunden mit dem ganzen Quellcode usw. rumärgern, wenn 
jemand mir in 10Minuten sagen kann, was dort nicht richtig ist. Dann 
hätte ich mir diesen Eintrag auch sparen können und das Forum hier hätte 
seinen Platz verfehlt, wenn alle so eine Antwort bekommen.

Lg

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> Hallo,
>
> das mag sein, aber ich muss doch nicht für eine private Anwendung mich
> hier soviele Stunden mit dem ganzen Quellcode usw. rumärgern, wenn
> jemand mir in 10Minuten sagen kann, was dort nicht richtig ist.

Um dir sagen zu können, was da alles nicht richtig ist, muss dein Helfer 
erst mal 20 Minuten investieren, deinen Code zu analysieren und mit dem 
abzugleichen, was das Datenblatt zu dem Thema sagt bzw. mit dem 
korrekten Vorgehen zu vergleichen. Aufgrund deines Codestils steigert 
siczh die Zeit noch mal, da man den erst mal so umformen muss, dass man 
ihn überblicken kann.

Das alles sind Dinge, die du genausogut auch machen kannst. Wenn du 
Programme entwickeln willst, dann MUSST du das sogar irgendwann mal 
selber machen. Und das hat nichts damit zu tun, ob du Profi werden 
willst oder nicht.
Du willst die Wasser-Installation in deinem Bad selber machen? Ok, dann 
lerne mit den Werkzeugen umzugehen. Nur mit dem Hammer auf irgendwelche 
Rohre hauen können, ist nun mal zuwenig.

> Dann
> hätte ich mir diesen Eintrag auch sparen können und das Forum hier hätte
> seinen Platz verfehlt, wenn alle so eine Antwort bekommen.

Das Forum ist nicht dazu da, für dich das Lernen zu übernehmen.

Irgendwann ist man in der Programmierung nun mal an einem Punkt 
angelangt, an dem es nicht mehr so einfach ist zu sagen: Da, in dieser 
Zeile steckt ein Fehler. Ob dir jetzt ein Helfer eine 30 zeilige 
Erklärung schreibt, was und warum an welcher Stelle nicht stimmt (die er 
nur schreiben kann, weil er erst mal mühsam deinen Code auseinander 
klauben muss) oder ob du eine 10 seitige AppNote liest und durchdenkst, 
spielt so gesehen erst mal keine Rolle. Der UNterschied besteht darin, 
dass dein Helfer erst mal Zeit investieren muss um rauszufinden, was 
denn eigentlich falsch ist (das kann er, weil er sich bereits die Mühe 
gemacht hat das zu lernen) und dann eine Abhandlung drüber schreibt, die 
genau auf dieses eine Detail eingeht. Im anderen Fall hat Atmel bereits 
eine AppNote geschrieben, in der nicht nur auf dieses Detail eingegangen 
wird, sondern auf alle Details, die wichtig sind und das diese AppNote 
umfangreicher ist, als es ein Helfer hier im Forum je schreiben könnte. 
Dafür stehen dann dort aber auch die Sachen drinnen, die ein 
Forumshelfer im Eifer des Gefechts vergessen hat zu erwähnen.
Und warum das ganze? Antwort: Weil es dich im Grunde überhaupt nicht 
interessiert. Du willst nur, dass das funktioniert. Wie und warum das 
funktioniert ist dir schlicht und ergreifend völlig wurscht. Nur: So 
wird das nichts mit dem Entwickeln von Programmen. Wir sind hier kein 
kostenloses Ingenieursbüro, bei dem man mit seinen verkorksten 
Programmen vorstellig wird und die dann alles richtig stellen, so wie 
man dann eben doch irgendwann einen Klempner ruft, der dann erst mal das 
verkorkste Rohr mühsam aus der Wand holen muss, was nicht notwendig 
gewesen wäre, wenn der Hobby-Bastler wenigstens ein bischen was von 
Klempnern verstanden hätte oder eben gleich den Klempner gerufen hätte.

Du willst lernen?
Dann lerne! Atmel stellt dir dazu das Lernmaterial in Form von AppNotes 
zur Verfügung.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.