Forum: Mikrocontroller und Digitale Elektronik TWI: Clock leitung auf low halten


von Gast (Gast)


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?

von Zeusi (Gast)


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

von Jörg X. (Gast)


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 ...

von Gast (Gast)


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.

von Jörg X. (Gast)


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

von Gast (Gast)


Lesenswert?

Danke Jörg, das bringt mich weiter.

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.