TWI: Clock leitung auf low halten

Gast #646463
Lesenswert?
• ▲
▼
Ich habe in meinem Projekt die TWI Schnittstelle verwendet, in der ISR 
lese ich die Daten ein, nur habe ich das Problem, falls ich z.B. 3 
Packete über die I2C-Schnittstelle gleich hintereinander bekomme, kann 
ich mur auf das erste reagieren. Ich möchte aber, nach dem ich ein STOP 
erhalten habe eine Funktion aufrufen, abarbeiten und dann wieder die 
nächsten Pakete empfangen. Wie kann ich solange die Clockleitung halten, 
als Slave?
Gast #646470
Lesenswert?
• ▲
▼
Wenn Du uns sagst welchen µC du verwendest könnte wir Dir evtl. mehr 
helfen, aber ansonsten bietet Atmel im (vollständigen) Datenblatt von 
dem ATMega32 eine reine Softwarelösung,.

grüüüße
Gast #646508
Lesenswert?
• ▲
▼
Der "klassische" Ansatz ist ein Jobflag+Puffer:
die ISR empfängt ein ganzes Paket und setzt, sobald eins da ist, eine 
Variable/ein Bit (Flag), die Main loop fragt das Bit regelmäßig ab, und 
ruft die Funktion auf, wenn das flag gesetzt ist (auch in den Atmel 
appnotes zu TWi wird das so gemacht).

Wieso willst du die Clock-Leitung halten??? (Dann kommt ja auch keine 
stop-condition, weil der Bus blockiert ist)
Wenn dein Slave signalisieren soll, dass er beschäftigt ist, antwortet 
er einfach nicht auf seine Adresse.

hth. Jörg

ps.: bei AVRs wird die Clock-Leitung immer auf Low gehalten, wenn das 
TWINT-Bit gesetzt ist ...
Gast #646535
Lesenswert?
• ▲
▼
Ich verwende einen Atmega. Die Softwareschnittstelle kann ich jetzt 
nicht mehr nehmen, da die Hardware bereits steht (will ich auch nicht). 
Zu dem TWI Slave habe ich glaub ich hier was gefunden und angepasst. 
Soweit funktioniert das ganze, bloss wenn mehrere Pakete direkt 
hintereinander ankommen, wird das zweite immer ignoriert. Ich müsste 
praktisch die SCL Leitung auf low halten, was man theoretisch mit dem 
TWINT Flag machen kann, das klappt aber nicht.
Hier ist das problematische Stück vom Code
1
case TW_SR_STOP:   // 0xA0 STOP empfangen
2
    rx_ready  = 0x01;
3
    tx_ready  = 0x01;
4
    i2c_busy  = 0x00;
5
    buffer_adr  = 0xFF;
6

7
    TWCR    |= (1<<TWINT);
8
    printf("\r\n");
9
    for(i=0; i< 32; i++)
10
    {
11
     printf("x0%X ", rxbuffer[i]);
12
     TWCR    |= (1<<TWINT);
13
    }
14
    transform_i2c_to_para();              
15
    TWCR    &= ~(1<<TWINT);

TWCR    |= (1<<TWINT);
Hiermit will ich SCL low time stretchen, um diese Funktion 
"transform_i2c_to_para()" problemlos ausführen zu können.
Gast #646549
Lesenswert?
• ▲
▼
> TWCR    |= (1<<TWINT);
damit löschst du das flag!
Wie die allermeisten AVR-Interruptflags, wird das TWINT mit einer 1 
gelöscht.
Um das Flag gesetzt zu lassen, brauchst du einfach NICHTs zu tun, weil 
das Flag gesetzt ist, wenn die ISR läuft.

Wenn der Slave NACH der Stop-Condition warten soll, lösche einfach das 
TWEA-Bit, und setze es sobald der Slave wieder ansprechbar ist. Der 
Master muss dann eben pollen, d.h. solange die Slave-addresse senden, 
bis der Slave antwortet.

hth. Jörg

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

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.