Forum: Mikrocontroller und Digitale Elektronik I2C Slaveimplementierung auf einem ATTINY 2313


von Hans-Joachim B. (beckhj)


Lesenswert?

Hallo!
Ich nutze die I2C Slave-Implementierung von Martin Junghans (jtronics) 
schon einen ganze Weile und die hat mir super Dienste geleistet.
Bisher habe ich auch nur immer ein Byte gelesen (ein paar Tasten wurden 
durch den ATTINY entprellt und dann der Status geliefert) und das ging 
prima.
Nun habe ich das Problem, dass ich nun ein paar Bytes vom Master an den 
Slave schicken muss und auch mehrere Bytes vom Slave lesen muss.

Alle meine Daten passen sicher in den Sende oder auch Empfangsbuffer des 
ATTINY, aber ich finde keinen Punkt der mir sagt, wann eine Transaktion 
abgeschlossen ist, also die übertragenen Daten genutzt werden können.
Ich hatte gedacht, dass über die Erkennung der Stopp-Bedingung 
realisieren zu können, aber die Stopp-Bedingung habe ich nie "gefunden"
1
  while (  ( PIN_USI & ( 1 << PIN_USI_SCL ) ) &&  !( ( PIN_USI & ( 1 << PIN_USI_SDA ) ) ));// SCL his high and SDA is low
2
3
  if ( !( PIN_USI & ( 1 << PIN_USI_SDA ) ) )
4
    {  // A Stop Condition did not occur
5
    USICR =
6
    ( 1 << USISIE ) |                // Keep Start Condition Interrupt enabled to detect RESTART
7
    ( 1 << USIOIE ) |                // Enable Overflow Interrupt
8
    ( 1 << USIWM1 ) | ( 1 << USIWM0 ) |          // Set USI in Two-wire mode, hold SCL low on USI Counter overflow
9
    ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |  // 4-Bit Counter Source = external, both edges; Clock Source = External, positive edge  
10
    ( 0 << USITC );                  // No toggle clock-port pin
11
    }
12
  else
13
    {  // A Stop Condition did occur
14
    USICR =
15
    ( 1 << USISIE ) |                // Enable Start Condition Interrupt
16
    ( 0 << USIOIE ) |                // Disable Overflow Interrupt
17
    ( 1 << USIWM1 ) | ( 0 << USIWM0 ) |          // Set USI in Two-wire mode, no USI Counter overflow hold
18
    ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |    // 4-Bit Counter Source = external, both edges; Clock Source = external, positive edge
19
    ( 0 << USITC );                  // No toggle clock-port pin
20
    }
Das ist die Codesequenz, in der das passieren müsste, aber in den 
ELSE-Zweig komme ich nie an.

Hat da jemand schon was gemacht, um das Problem zu lösen?
Ich habe auch nach anderen I2C Slave Implementierungen gesucht, aber so 
was richtig passendes habe ich leider bisher nicht gefunden.

Danke schon mal für Tipps und Grüße
Hans-Joachim

von kyrk (Gast)


Lesenswert?

Zeile 13 sagt:
    {  // A Stop Condition did occur

von Peter D. (peda)


Lesenswert?

USI Status Register – USISR:
Bit 5 – USIPF: Stop Condition Flag
When Two-wire mode is selected, the USIPF flag is set (one) when a stop 
condition is detected. The flag is cleared by writing a one to this bit. 
Note that this is not an interrupt flag. This signal is useful when 
implementing Two-wire bus master arbitration.

von Hans-Joachim B. (beckhj)


Lesenswert?

... wie oben schon geschrieben - in den else-Zweig (also ab Zeile 13) 
kommt er nie rein

von Hans-Joachim B. (beckhj)


Lesenswert?

Hallo Peter,

danke für den Hinweis, probiere ich gleich aus.
Wäre zu einfach - aber wer lesen kann ist im Vorteil und ich hatte den 
Fehler gemacht und nicht in die Doku sondern nur in den Code der Library 
zu schauen.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Zur Not darfst du gerne von meinem Projekt abgucken. Es empfängt 
variabel 1-10 Bytes pro Transaktion und trägt sie in ein Array ein. Die 
Timer-ISR konsumiert das Array, aber ich denke die ist für deine Frage 
irrelevant.

Beachte die kommentierte Stelle "if stop condition received, break the 
for loop"

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.