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:
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.
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.
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
intmain(void)
8
{
9
10
intsteuer=1;
11
DDRD=0b00000010;
12
PORTD=0;
13
intergebnis=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
return0;
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?
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
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.
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.
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
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.