Attiny804 (tinyAVR0) als I2C Slave gibt überhaupt keine Regung von sich

Gast #7329186
Lesenswert?

Hallo Leute!

Ich würde gerne einen ATtiny804 (tinyAVR0-Serie) als I2C Slave verwenden. Eine Application Note von Microchip konnte ich dazu nicht finden und sonst auch nicht so viel im Web, aber wenn man etwas gräbt findet man ein paar Codebeispiele (Links siehe unten). Entsprechend diesen habe ich mir einen minimalsten Code gebaut und einen Arduino ran gehangen der fleißig I2C sendet (verifiziert mit Oszi).

Allerdings passiert absolut überhaupt nix; keine Ausgabe via UART, dass die ISR aufgerufen wurde bzw. ich habe es auch schon mit Counter/LED innerhalb der ISR versucht. Aber es passiert gar nix.

Und so langsam habe ich keine Idee was noch falsch sein könnte, da sich alle Beispiele halbwegs einig sind. Habt Ihr eine Idee wo der Fehler liegen könnte?

1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4

5
extern void USART0_sendString(char *str, uint16_t len);
6
extern void USART0_init();
7

8
void twi_slave_begin(uint8_t address) {
9
  // Silicon bug?
10
  PORTB.OUTCLR = 0x03;  // PB0, PB1
11
    /*
12
        SDA ---> PB1
13
        SCL ---> PB0
14
    */
15

16
  TWI0.CTRLA = 0;                                        // Default timings
17
  TWI0.SADDR = address<<1;                             // Bottom bit is R/W bit
18
  // Enable address, data, and stop interrupts:
19
  TWI0.SCTRLA = TWI_APIEN_bm | TWI_DIEN_bm | TWI_PIEN_bm | TWI_ENABLE_bm;
20

21
  USART0_sendString("READY!\n", 7);
22
}
23

24
void TWI_HandleSlaveIRQ() {
25
  uint8_t action = 0;
26
  uint8_t clientStatus = TWI0.SSTATUS;
27

28
  if (clientStatus & TWI_APIF_bm) {  // Address/Stop Bit set
29
    if (clientStatus & TWI_AP_bm) {    // Address bit set
30
//...
31
    }
32
//...
33
  }
34
}
35

36

37
ISR(TWI0_TWIS_vect) {
38
  USART0_sendString("ISR\n", 4);
39
  // TWI_HandleSlaveIRQ();
40
}
41

42

43
int main() {
44
  _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 1);         // set clock frequency to 10 MHz
45
    USART0_init();
46
    USART0_sendString("\n\n---Ready---\n", 14);
47

48
    twi_slave_begin(0x2a);
49
    
50
    sei();
51

52
    while(1) {
53
      _delay_ms(1);
54
    }
55

56
    return 0;
57
}

Links falls mal jemand hierüber stolpern sollte:

Gast #7329376
Lesenswert?

Lothar M. schrieb:

DerElektronikbastler schrieb:

// Silicon bug?

Woher kommt dieser Kommentar?

Der Kommentar kommt hier her: https://github.com/SpenceKonde/megaTinyCore/tree/master/megaavr/libraries/Wire#errata-warning

Da steht:

All modern AVRs, since the release of the first tinyAVR 0/1-series, through the AVR DB-series, have always had a silicon bug relating to the TWI pins ...

Lothar M. schrieb:

Bist du sicher, dass die Pins auf die TWI0-Einheit gemappt sind? Irgendwie werde ich aus dieser Tabelle nicht so recht schlau. Ist aber auch schon spät...

Aber dort steht doch (siehe Bild):

  • TWI0 SDA (9. Spalte) auf PB1, Pin 8
  • TWI0 SCL (9. Spalte) auf PB0, Pin 9

und ich bin mir ziemlich sicher, dass das so passt (Verpolung auch geprüft).

Angehängte Dateien:
(Firma: L-E-A) #7329381
Lesenswert?

DerElektronikbastler schrieb:

Allerdings passiert absolut überhaupt nix; keine Ausgabe via UART, dass die ISR aufgerufen wurde bzw. ich habe es auch schon mit Counter/LED innerhalb der ISR versucht. Aber es passiert gar nix.

1
> ISR(TWI0_TWIS_vect) {
2
>   USART0_sendString("ISR\n", 4);
3
>   // TWI_HandleSlaveIRQ();
4
> }
5
>

Bist Du Dir sicher, dass USART0_sendString() aus einem Interrupt heraus aufgerufen werden darf? Zeig' doch bitte den Code dieser Funktion.

Grüßle, Volker

Gast #7329400
Lesenswert?

DerElektronikbastler schrieb:

Entsprechend diesen habe ich mir einen minimalsten Code gebaut und einen Arduino ran gehangen der fleißig I2C sendet (verifiziert mit Oszi).

Zunächst sehe ich da zwei "Probleme" versteckt. Zum einen ballert der Master mit vermutlich hoher Datenrate auf den Bus was einen Slave zur Verzweiflung bringen kann selbst wenn das Prinzip der Datenübertragung funktioniert. Der Slave hat ja noch was anderes zu tun aussser Bytes in Empfang zu nehmen. Zum anderen ist bei TWI bzw. I2C ein Bus-Handshake vorgesehen (das ACK wir abgewartet) das der Master in diesem Fall vermutlich nicht abwartet.

Gast #7329467
Lesenswert?

Volker B. schrieb:

Bist Du Dir sicher, dass USART0_sendString() aus einem Interrupt heraus aufgerufen werden darf? Zeig' doch bitte den Code dieser Funktion.

Ja, ich bin sicher. Und zur Sicherheit habe ich es ja auch mit einem Port-Pin-Toggle versucht und einem Counter, um die Zeit in der ISR zu minimieren.

beobachta schrieb:

Zunächst sehe ich da zwei "Probleme" versteckt. Zum einen ballert der Master mit vermutlich hoher Datenrate auf den Bus was einen Slave zur Verzweiflung bringen kann selbst wenn das Prinzip der Datenübertragung funktioniert. Der Slave hat ja noch was anderes zu tun aussser Bytes in Empfang zu nehmen. Zum anderen ist bei TWI bzw. I2C ein Bus-Handshake vorgesehen (das ACK wir abgewartet) das der Master in diesem Fall vermutlich nicht abwartet.

Das ist alles Richtig was Du schreibst aber mir ging es ja erstmal um überhaupt eine Reaktion der TWI Hardware, z.B. dass der Interrupt Handler aufgerufen wird. Darin bastelt man ja dann die Logik wie ich in TWI_HandleSlaveIRQ angedeutet habe. Aber das Problem ist ja, dass überhaupt nix passiert.

Weißer Rauch!

TL;DR: es läuft!

Ich habe nochmal drüber nachgedacht, ob es nicht einen Zusammenhang mit der von mir benutzten UART gibt weil die ja teilweise Pins teilen. Also habe ich versucht die alternativen Pins für die UART zu verwenden und das hat nicht geklappt weil die Symbole im C Code als nicht definiert markiert wurde und zu einem Compiler-Fehler geführt haben. Und da hatte ich es: ich hatte das falsche Board eingestellt (ATtiny826) und nach Änderung auf das Korrekte läuft es einwandfrei! Ich bekomme ganz viele "ISR"-Ausgaben auf der seriellen Konsole (was auch oben die zwei "Fragen" beantwortet - eine Reaktion kann ich erzeugen auch ohne ACK etc. Logik).

D.h. Ihr habt mich auf die Lösung gebracht - Dankeschön!

P.S.: Falls jemand - wie ich - irgendwie den Eindruck gewinnt, dass es nirgendwo Beispiele zu TWI-Slave gibt, dem kann ich nur https://github.com/SpenceKonde/megaTinyCore/tree/master/megaavr/libraries/Wire/src empfehlen, weil daran habe ich mich orientiert.

P.S.S.: Zu:

... Zum anderen ist bei TWI bzw. I2C ein Bus-Handshake vorgesehen (das ACK wir abgewartet) das der Master in diesem Fall vermutlich nicht abwartet.

Das klappt auch mit meiner "Brechstangenmethode", weil: initial setzt man ja via "TWI0.SADDR = address<<1;" die Adresse, d.h. die Hardware des AVR antwortet eigenständig und korrekt auf die "Anfragen" des Masters, weil dieser ja die Adresse des Slaves + R oder W auf den Bus legt. Lediglich weitere Kommunikation schlägt fehl. Aber das war ja erstmal auch nicht mein Ziel.

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