Forum: Mikrocontroller und Digitale Elektronik TWI mit ATTiny817 - Verständnis-Frage


von Jürgen (Gast)


Lesenswert?

Hallo, ich möchte auf einem ATTiny817 einen simplen TWI-Slave, nur im 
Slave-Receive-Mode, realisieren.
Da ich im Moment keine andere Hardware greifbar habe, verwende ich einen 
Arduino in Verbindung mit "Wire" als Master. Er sendet Daten an den 
Tiny817. Das Empfangen funktioniert bisher auch problemlos. Das 
Debugging mache ich im Moment über die UART-Ausgabe und Putty.

Nun meine Frage zum Verständnis des TWI-Transfers.
Ich kann auf der Empfängerseite sehen, daß nach dem Empfang der 
korrekten Adresse und auch nach dem Daten-Byte jeweils in Interrupt 
ausgelöst wird. Darauf wird jeweils mit einem ACK reagiert.
Auf den Empfang der Stop-Condition kann ich aber keinen Interrupt 
registrieren.
Müsste ich normalerweise auf das STOP einen Interrupt erhalten?

Mein Code aus dem Tiny817 sieht so aus:
1
void I2C_0_send_ack(void)
2
{
3
  TWI0.SCTRLB = (0 << TWI_ACKACT_bp) | TWI_SCMD_RESPONSE_gc;
4
}
5
6
ISR(TWI0_TWIS_vect){
7
  
8
  // Address received
9
  if ((TWI0.SSTATUS & TWI_APIF_bm) && (TWI0.SSTATUS & TWI_AP_bm)) {
10
    I2C_0_send_ack();
11
    i = 65;
12
  }
13
  
14
  // Data received
15
  if (TWI0.SSTATUS & TWI_DIF_bm) {
16
    I2C_0_send_ack();
17
    i = TWI0_SDATA;
18
  }  
19
  
20
  
21
  // Check if STOP was received
22
  if ((TWI0.SSTATUS & TWI_APIF_bm) && (!(TWI0.SSTATUS & TWI_AP_bm))) {
23
    //I2C_0_send_ack();
24
    TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc;
25
    i = 83;
26
    I2C_0_send_ack();
27
  }
28
    
29
  LED0_toggle_level();
30
  
31
}    // end ISR
32
33
int main(void)
34
{
35
  
36
  TWI0.SADDR = 0x71; /* Slave Address: 0x71 */
37
  TWI0.SCTRLA = 1 << TWI_APIEN_bp    /* Address/Stop Interrupt Enable: enabled */
38
  | 1 << TWI_DIEN_bp   /* Data Interrupt Enable: enabled */
39
  | 1 << TWI_ENABLE_bp /* Enable TWI Slave: enabled */
40
  | 1 << TWI_PIEN_bp   /* Stop Interrupt Enable: enabled */
41
  | 0 << TWI_PMEN_bp   /* Promiscuous Mode Enable: disabled */
42
  | 0 << TWI_SMEN_bp;  /* Smart Mode Enable: disabled */
43
  
44
  TWI0.SCTRLA |= TWI_ENABLE_bm;
45
  
46
  
47
  
48
49
  /* application code */
50
  while (1) {
51
    
52
    if (i)
53
    {
54
      USART_0_write(i);
55
      i = 0;
56
      
57
    }
58
  }
59
}

Der Arduino sendet hiermit:
1
void loop() {
2
3
4
  x++;                  // Increment x
5
  if (x > 126) x = 32; //
6
7
8
 Wire.beginTransmission(0x38); // transmit to device #0x71
9
 Wire.write(x);                // sends x 
10
 //Wire.write(106);
11
 //Wire.write(104);
12
 //Wire.write(x);
13
 int i = Wire.endTransmission(true);    // stop transmitting
14
15
 Serial.println(i);
16
  
17
 delay(1000);
18
19
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
20
}

von Jürgen (Gast)


Lesenswert?

PS:
Das Datenblatt - 
http://www.atmel.com/Images/Atmel-42721-ATtiny417-814-816-817_Complete.pdf 
- sagt zum APIF - Flag im SSTATUS - Register:
This flag is set when the slave address match logic detects that a valid 
address has been received or by a
stop condition. … The APIF flag can be used to generate a slave address 
or stop interrupt (see description of the AIEN
control bit in TWI.CTRLA). Take special note of that the slave stop 
interrupt shares the interrupt vector
with slave address interrupt.

PPS:

Allen einen guten Rutsch und viel Gesundheit im neuen Jahr!

von Np R. (samweis)


Lesenswert?

Jürgen schrieb:
> PS:
> Das Datenblatt -
> http://www.atmel.com/Images/Atmel-42721-ATtiny417-814-816-817_Complete.pdf
> - sagt zum APIF - Flag im SSTATUS - Register:
> This flag is set when the slave address match logic detects that a valid
> address has been received or by a
> stop condition. … The APIF flag can be used to generate a slave address
> or stop interrupt (see description of the AIEN
> control bit in TWI.CTRLA). Take special note of that the slave stop
> interrupt shares the interrupt vector
> with slave address interrupt.
>
> PPS:
>
> Allen einen guten Rutsch und viel Gesundheit im neuen Jahr!

Dir auch ein gutes Neues Jahr!

Könnte es sein, dass die Taktfrequenz zu langsam ist?

Seite 318:
"Bit 5 – PIEN: Stop Interrupt Enable
Writing this bit to '1' enables APIF to be set when a STOP condition 
occurs. To use this feature the system frequency must be 4x the SCL 
frequency."

von (prx) A. K. (prx)


Lesenswert?

Ich habe einen TWI Slave auf dem ATtiny841 implementiert. Der hat ein 
Modul drauf, das weitgehend dem TWI Slave des ATtiny817 entspricht. Und 
dafür kann ich bestätigen, dass der Stop-Interrupt durchkommt.

In
1
    TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc;
2
    i = 83;
3
    I2C_0_send_ack();
sollte die letzte Zeile raus, weil schon in der ersten erledigt.

NB: Als Master für den Test verwendete ich den Bus Pirate. Den 
Arduino-Code kann ich nicht einschätzen.

: Bearbeitet durch User
von Jürgen (Gast)


Lesenswert?

Danke für Eure Antworten!
@np rn
Die Taktfrequenz beträgt 3,33MHz. Das sollte also ok sein.

Ja, es ist eine blöde Idee sich in unbekannte Materie einarbeiten zu 
wollen, wenn das Handwerkszeug nicht passt. Ich muss zugeben, mich für 
die ATMegas der üblichen I2C-Libs bedient zu haben. Daher fehlt mir doch 
I2C - Grundlagenwissen. Der Bus-Pirate scheint in dieser Hinsicht eine 
sinnvolle Investition. Ich hatte eigentlich ein Dev-Board mit dem 
MCP2221 im Sinn. Der Pirate ist aber universeller.

Wie dem auch sei, ich habe noch etwas mit dem Arduino getestet.
Dabei stellte sich heraus, daß wenn ich den Tiny817-Slave nur schreibend 
anspreche (Adress-Bit 8 = 0) kann ich auf meinem "Serial-Debug-Terminal" 
erkennen, daß im TWI-Interrupt die Adresse erkannt wird und mein 
Datenbyte empfangen wird.
1
i2c_start(0x70);  // address + 0
2
i2c_write(0x79);  // data Byte 'y'
3
i2c_stop();

Spreche ich den Slave mit Adress-Bit 8 = 1 an wird im TWI-Interrupt die 
Stop - Condition erkannt. Das Datenbyte enthält jedoch den Wert der 
Adresse. Die erste if-Abfrage im Interrupt, die Adresserkennug, wird 
offensichtlich nicht durchlaufen.
1
i2c_start(0x71);  // address + 1
2
i2c_write(0x79);  // data Byte 'y'
3
i2c_stop();

Mit folgender Sequenz:
1
i2c_start(0x70);  // address +0
2
i2c_write(0x79);  // data Byte 'y'
3
i2c_rep_start(0x71);  //repeat_start Address + 1
4
i2c_stop();
werden alle 3 if-Bedingungen im TWI-Interrupt erfüllt und an meiner 
Konsole erkenne ich, daß die Adresse korrekt erkannt, das Datenbyte 
korrekt empfangen und die Stop-Condition erkannt wurde.

Die letzte, für mich unlogische, Sequenz erzeugt das, von mir, erwartete 
Ergebnis.

Sobald ich neues Spielzeug, den Bus-Pirate, habe kann ich wohl etwas 
sinnvoller weitermachen. Jetzt hat es etwas von im Nebel herumstochern.

von Jürgen (Gast)


Lesenswert?

Laut Datenblatt teilen sich 'valid address' und 'stop condition' ein 
Interrupt - Flag.

Demzufolge können die beiden Zustände gar nicht gemeinsam während der 
Übertragung eines Bytes auftreten - oder?

von (prx) A. K. (prx)


Lesenswert?

Jürgen schrieb:
> Demzufolge können die beiden Zustände gar nicht gemeinsam während der
> Übertragung eines Bytes auftreten - oder?

Das ergibt sich zumindest auch aus dem Zustandsdiagramm in 26.3.4.3.

von (prx) A. K. (prx)


Lesenswert?

Jürgen schrieb:
> Sobald ich neues Spielzeug, den Bus-Pirate,

Dass ich den Bus Pirate verwendete macht ihn nicht empfehlenswert. Der 
beherrscht kein Clock Stretching. Man muss also den I2C-Takt ziemlich 
weit absenken, um garantiert keine Latenzprobleme zu kriegen.

Ich hatte den einfach nur deshalb verwendet, weil ich ihn rumliegen 
hatte. Ich wollte als Master ein für interaktive Tests einfach 
verwendbares und getestetes Interface haben, das ich also nicht auch 
debuggen muss. Was, wie ich bei der Gelegenheit feststellen musste, ein 
Griff ins Klo war.

Mit der erwähnten Einschränkung kann man ihn für Tests verwenden, aber 
ihn extra wegen I2C zu besorgen wäre wohl nicht sinnvoll.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Ein Werkzeug, das bei Problemen mit seriellen Protokollen durchaus 
weiter helfen kann, ist ein DSO oder ein Logikanalysator. Was beim 
niedrig getakteten I2C wohl auch die Spielzeugklasse leisten kann. Es 
gibt welche, die mehr oder weniger nur aus einem STM32 bestehen.

: Bearbeitet durch User
von Jürgen (Gast)


Lesenswert?

A. K. schrieb:
> Dass ich den Bus Pirate verwendete macht ihn nicht empfehlenswert.

Danke für den Hinweis!

A. K. schrieb:
> Ich wollte als Master ein für interaktive Tests einfach
> verwendbares und getestetes Interface haben...

Das war nun auch mein Gedanke, zumal ich mich als nächstes noch am SPI - 
Empfang auf dem Tiny817 versuchen möchte. Ich werde also vor einer 
Kaufentscheidung noch mal durchs "Bus Pirate Support" - Forum schauen. 
Das Board scheint interessant, da wohl verschiedene Protokolle 
unterstützt werden.
Gibt es da noch etwas ähnliches, eventuell empfehlenswerteres?

Der größte Teil meiner Hobby-Werkstatt ist im Moment, wegen einer 
größeren Renovierung, in Umzugskartons ausgelagert. Darunter auch mein 
LA, ein Logic Cube von Zeroplus. Mir hat einfach die Bastelei gefehlt. 
Daher habe ich, über die etwas ruhigeren Feiertage, angefangen mal etwas 
mit den noch verfügbaren Komponenten herum zu probieren.

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.