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

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