Hallo an alle!
Ich betreibe 3 (später sollen es 7 werden) Atmega32 (16 Mhz) in einem
TWI-Multimaster-System mit 400kHz und einer Leitungslänge von etwa
30cm... und bin verzweifelt: Nach einer kleinen Initialisierung sollen
sich die Controller mit einer Art Ping-Funktion gegenseitig
kontrollieren: Alle 200ms wird eine Anfrage geschickt und 200ms später
kontrolliert, ob eine Antwort gekommen ist (1 kontrolliert 2, 2
kontrolliert 3 und 3 kontrolliert 1). Ich benutze dazu den
MasterTransiever- und den SlaveReceiver-Modus. Neben diesen "Pings"
führen die Controller noch unterschiedliche Hauptfunktionen aus, die
alle 4ms (Controller 3), 40 (Controller 1) oder 100ms (Controller 2)
ausgefrufen werden.
Die Initialisierung des Systems, bestehend aus 2 Nachrichten (2 mal 3
Byte) pro Controller, klappt (meistens) noch gut, aber danach bricht das
TWI komplett zusammen. Außer ich plaziere in einer der main-Schleifen
ein Delay von mindestens 20μs. Leider kann ich nicht vernünftig
Debuggen, da sobald ich mein LCD ansteuere ja eine Verzögerung entsteht
und alles funktioniert (JTAG wäre jetzt sicherlich hilfreich). Ich
behandle den TWI Interrupt-basiert, hier ist der Code des Interrupts:
// Own SLA+W has been received and ACK has been returned
60
case0x60:
61
// Arbitration lost in SLA+R/W as Master, own SLA+W has been received and ACK has been returned
62
case0x68:
63
// General call address has been received and ACK has been returned
64
case0x70:
65
// Arbitration lost in SLA+R/W as Master, general call address has been received and ACK has been returned
66
case0x78:
67
// Set TWI busy flag
68
twi_flag_busy=1;
69
// Reset message part
70
twi_message_part=0x00;
71
// Reset TWINT
72
TWCR=0xC5;// TWINT, TWEA, TWEN, TWIE
73
break;
74
75
// Previously addressed with own SLA+W, data has been received and ACK has been returned
76
case0x80:
77
// Previously addressed with general call, data has been received and ACK has been returned
78
case0x90:
79
// Set TWI busy flag
80
twi_flag_busy=1;
81
// Save data in message
82
twi_message_temp_r[twi_message_part]=TWDR;
83
if(twi_message_part<TWI_MESSAGE_SIZE-2)
84
twi_message_part++;
85
// Reset TWINT
86
TWCR=0xC5;// TWINT, TWEA, TWEN, TWIE
87
break;
88
89
// A STOP condition or repeated START has been received while still addressed as slave
90
case0xA0:
91
twi_message_part=0x00;
92
if(twi_attach_r(twi_message_temp_r)){
93
// Set TWI receive flag
94
twi_flag_r=1;
95
}
96
else
97
PORTC.7=0;
98
// Reset TWI busy flag
99
twi_flag_busy=0;
100
// Set TWI transmit flag
101
twi_flag_t=1;
102
// Reset TWINT
103
TWCR=0xC5;// TWINT, TWEA, TWEN, TWIE
104
break;
105
106
// Bus error due to an illegal START or STOP
107
//case 0x00:
108
PORTC.7=0;
109
// Reset TWINT
110
TWCR=0xC5;// TWINT, TWEA, TWEN, TWIE
111
break;
112
113
}
114
}
Mein Sende Buffer (twi_message_t) ist 5 Felder groß und jeder Eintrag
besteht auf 4 Byte (Zieladresse und 3 Datenbyte). Allerdings werden auch
noch Port-Expander (PCF8574), so dass in machen Fällen (Adresse < 0x20)
nach dem ersten Datenbyte abgebrochen werden kann. Ein Feld im Buffer
gilt als leer, wenn das erste Datenbyte einen Wert von 0xFF hat. Der
Empfangsbuffer ist genauso aufgebaut und wird mit
twi_attach_r(twi_message_temp_r) befüllt.
Eine Übertragung wird mit einer Funktion initiert, die in der
main-Schleife bei gesetztem twi_flag_t aufgerufen wird und versucht ein
START zu senden:
1
// Send messages in TWI buffer
2
voidtwi_transmit(void){
3
4
// Local variables
5
unsignedcharindex;
6
7
if(!twi_flag_busy){
8
for(index=0x00;index<TWI_BUFFER_SIZE;index++){
9
if(twi_message_t[index][1]!=0xFF){
10
// Set index to message index in buffer
11
twi_message_index=index;
12
// Send START
13
TWCR=0xE5;// TWINT, TWEA, TWSTA, TWEN, TWIE
14
break;
15
}
16
}
17
}
18
// Reset TWI transmit flag
19
twi_flag_t=0;
20
21
}
Und noch die Initialisierung des TWI:
1
// 2 Wire Bus initialization
2
// Generate Acknowledge Pulse: On
3
// 2 Wire Bus Slave Address: TWI_ADDRESS
4
// General Call Recognition: On
5
// Bit Rate: 400,000 kHz
6
TWSR=0x00;
7
TWBR=0x0C;
8
TWAR=(TWI_ADDRESS<<1)|0x01;
9
TWCR=0x45;
Entschuldigung für den langen Post! Arbeitet meine Interrupt-Rountine
richtig? Habe ich einen "Fall" vergessen (Kollision)? Achja: Habe das
ganze auch schon bei 1000ms Ping-Takt versucht, aber es geht auch nicht,
nach der ersten oder zweiten Anfrage/Bestätigung geht auf dem TWI nix
mehr, die Controller laufen aber noch. Ich versuche jetzt seit 3 Tagen
dahinter zu kommen und finde einfach nichts. Bin für jede Anregung
außerst dankbar!
J.W.
Wenn Du willst, daß man sich den Code auch ansieht, mußt Du ihn als
Anhang senden, sonst scrollt man sich ja tot (wichtige Regeln Punkt 5)!
Ich kann bestätigen, daß Multimaster-I2C mit AVRs ne haarige Sache ist.
Ich hatte keine Zeit mehr, den Hänger zu finden und hab dann nen Timeout
aufgesetzt.
Ich mache Multimaster-I2C nie wieder!
Peter
Oh, entschuldigung. Da habe ich gar nicht dran gedacht. Ich habe den
Code mal in eine txt-Datei geschmissen und an diese Nachricht angehängt.
Aber ob man sich nun im Browser oder in nem Editor tot scrollt... nun
ja, wie auch immer.
Hätte nicht gedacht, dass das so problematisch wird mit dem Multimaster,
da im Datenblatt was von Multimaster-fähig steht. Aber vielleicht
könntet Ihr trotzdem nochmal grob drüberschauen, ob ich nicht
irgendeinen grundlegenden Zustand des TWI vergessen habe. Die NACKs habe
ich z.B. komplett ausgeklammert, da ich die eigentlich gar nicht
erzeuge(n will). Könnt das ein Problem sein?!
Danke schon mal für die Beachtung und den Hinweis!
Janis
Janis Wojtusch wrote:
> Oh, entschuldigung. Da habe ich gar nicht dran gedacht. Ich habe den> Code mal in eine txt-Datei geschmissen
Warum das denn?
Quelltexte postet man als C-Datei, dann werden sie auch richtig
formatiert im Forum angezeigt.
Peter
Janis Wojtusch wrote:
> Die NACKs habe> ich z.B. komplett ausgeklammert, da ich die eigentlich gar nicht> erzeuge(n will). Könnt das ein Problem sein?!
Könnte sein.
Die NACK/ACK sind für den I2C-Bus lebenswichtig. Sie müssen immer
korrekt erzeugt und ausgewertet werden.
Peter
Peter Dannegger schrieb:
> Janis Wojtusch wrote:>> Die NACKs habe>> ich z.B. komplett ausgeklammert, da ich die eigentlich gar nicht>> erzeuge(n will). Könnt das ein Problem sein?!>> Könnte sein.>> Die NACK/ACK sind für den I2C-Bus lebenswichtig. Sie müssen immer> korrekt erzeugt und ausgewertet werden.
Müssen sie das wirklich solange sich Master und Slave trotzdem einig
sind?