Forum: Mikrocontroller und Digitale Elektronik I2C Slave mit dem Attiny 841


von Klaus (Gast)


Lesenswert?

Hallo
versuche seit ein paar Stunden den Attiny 841 als I2C Slave in Betrieb 
zu nehmen. Als Master verwende ich einen Atmega 128. Das Programm auf 
dem Atmega läuft mit anderen Slaves ohne Probleme. Leider scheint es im 
Netz zu diesem Thema nicht viel zu geben. Es wird in der App 311 vom 
Hersteller zwar beschrieben wie es geht, geht aber leider nicht. Auch 
die Seiten von Jtronic funktionieren nicht. Es gibt auch eine Abhandlung 
zur Verwndung von 2 Atmmegas bzw. Attiny, geht aber auch nicht. Bin 
jetzt ziemlich ratlos. Programmiere mit C und AVR 7. Die I2C 
schnittstelle scheint etwas anders zu sein als die übrigen.
Der Vorgänger zum Attiny 841 soll docj der Attiny 84 sein. Stimmen die 
wenigsten überein?
Hat jemand ein Beispiel dazu?
Der Attiny funktioniert sonst ohne Probleme, kann Ein und Ausgänge 
schalten.
LG Klaus

von Karl M. (Gast)


Lesenswert?

Hi,

was Du vorher an I2C auf dem AVR Atmel kanntest, ist für den Attiny841 
so nicht mehr gültig.

Man muss nach dem Datenblatt ein I2C Client neu schreiben.

Vielleicht gibt es auf github.com schon etwas.

von Klaus (Gast)


Lesenswert?

Leider nichts gefunden

von Karl M. (Gast)


Angehängte Dateien:

Lesenswert?

Karl M. schrieb:
> Attiny841

Eigenartig, hier einige Funde bei einem Suchsystem.

von Klaus (Gast)


Lesenswert?

Deine Fundstellen sind mir bekannt. Habe sie alle bereits gelesen und 
die meisten getestet. Teilweise suchen auch andere nach Infos oder 
machen erste Versuche. Doch leider ohne konkrete ergebnisse

von c-hater (Gast)


Lesenswert?

Klaus schrieb:

> Die I2C
> schnittstelle scheint etwas anders zu sein als die übrigen.

Die ist sogar ziemlich anders. Im Besonderen kann sie z.B. 
ausschließlich Slave.

> Der Vorgänger zum Attiny 841 soll doch der Attiny 84 sein. Stimmen die
> wenigsten überein?

Nein, absolut nicht. Der Tiny84 hat nämlich überhaupt keine dedizierte 
I2C-Hardware, sondern, wie die meisten Tinys, nur das USI, was es aber 
wiederum beim 841 nicht gibt.

von HP41 (Gast)


Lesenswert?

Ich hätte da auch eine Frage. Gibt es irgendwo ausserhalb der bekannten 
NXP Dokus  I2C Zustandsmaschinen Dokus die eine formelle Implementierung 
diverser I2C Funktionalität erlaubt?

Die NXP Bus Spezifikation ist ja sehr nützlich, aber eine formale 
Zustandsmaschine Spezifikation diverser Modelle (I2C Busmaster, I2C 
Slave) um das Protokol ohne Verletzungen unter allen Umständen zu 
gewährleisten zu können wäre natürlich angenehm zur Verfügung zu haben. 
Ich denke da Dokumentation im Stil ähnlich wie z.B IEEE-488 wo die 
minimale vorgeschriebene Bus Device genau vorgeschrieben ist und man 
einen Unterschied zwischen Bus Protokoll Compliance und (optionale) 
Device Funktionen macht.

Sicher, es ist nicht schwer einen I2C Busmaster zu schreiben der 
praktisch funktioniert aber eine komplette Implementation die 
Fehlersituationen formell korrekt behandelt ist ein anderes Kapitel.

Bitte kein RTFM. Ich habe bis jetzt noch keine Dokus die in der 
Formalität und Komplettheit vergleichsweise an die IEEE-488 Bus 
Spezifikation herankommt gefunden. Man ist da meist diesbezüglich 
scheinbar auf sich selber gestellt.

Ferner wäre eine formelle Testsuite auch sehr nützlich, kommerzielle I2C 
Devices oder eigene Entwicklungen zu testen um irgendwelche Bugs 
bloszulegen. Es wäre ja peinlich wenn eine Eigenentwicklung dann später 
unerwartet z.B durch einen Bug den Bus blockiert...

Z.B. muß ich anhand der NXP Unterlagen annehmen, daß der ACK/NACK 
Datenzustand innerhalb der vorherigen Clock Timing stabil sein muß. Bei 
uC FW Implementierung ohne HW könnte das möglicherweise ins Auge gehen 
wenn man keine I2C HW im uC verwenden würde.

Abgesehen davon wäre das noch wichtiger bei Eigenentwicklung mittels uC 
oder FGPA/CPLD um festzustellen, daß das eigene Design alles Notwendige 
adequate erfüllt. Bis jetzt mußte ich noch kein eigenes I2C Device 
selber entwickeln.

Es gibt viele I2C Beispiele, Bibliotheken, Application Notes aller Art. 
Aber ohne viel Zeit mit sorgfältiger Eigenanalyse hinzustecken, hat man 
keine Gewissheit ob alle diese Implementationen die NXP Vorgaben 
wirklich erfüllen.

Also, gibt es formelle Bus Spezifizierungs Dokus die über die von NXP 
hinaus gehen und man Unterlagen ähnlich der IEEE-488 hätte auf die man 
bauen könnte? Wie würdet ihr das Problem ohne solche Dokus angehen um 
einigermaßen sichergehen zu können, daß man alle vorgesehenen 
Ausnahms-Fälle richtig behandelt?

von Klaus (Gast)


Lesenswert?

USI habe ich mit verschiedenen Typen gemacht. Verwende dazu die Datein 
von Jtronic. Da aber USI auf dem Ati 841 nicht läuft, gibt es nicht 
viele Möglichkeiten. Selber etwas zu machen traue ich mir nicht zu.
Der Hersteller gibt zwar als Beispiel die App 311 an, doch leider geht 
die auch nicht bzw. recht kompliziert.
Habe auch die angegeben Stellen auf dem Bild angeschaut. Github hat auch 
kaum was dazu oder für den Arduino. Suche aber was für normales C. Das 
ganze scheint nicht so einfach zu sein.

von c-hater (Gast)


Lesenswert?

Klaus schrieb:

> Das
> ganze scheint nicht so einfach zu sein.

Doch, ist es. Die Hardware des 841 stellt genau die zusätzliche 
Unterstützung bereit, die man beim USI so schmerzlich vermisst und 
relativ aufwendig in Software implementieren muss.

Es ist also deutlich einfacher, einen "normalen" I2C-Slave mit der 
Hardware des 841 umzusetzen als mit dem USI. Die darüber hinaus 
gebotenen Möglichkeiten der Hardware (mehrere Slave-Adressen, 
promiscuous mode) muss man ja nicht nutzen.

von Alexander S. (alex998)


Angehängte Dateien:

Lesenswert?

Klaus schrieb:
> Das ganze scheint nicht so einfach zu sein.

Häh? Das TWI_Modul vom 841 ist doch relativ komfortabel, macht fast 
alles selber.

Der Anhang ist eine Quick&Dirty-Lösung um ein 16x2-LCD per TWI 
anzusprechen. In TWI_Init werden die notwendigen Interrupts angeschaltet 
und Slave-Adresse gesetzt, anschliessend wird nur noch die ISR 
ausgewertet wenn was über den Bus kommt. Und das geht sehr einfach indem 
man das Statusregister TWSSRA ausliest und schaut was da reinkam: wars 
ein Addressmatch, oder Stop, oder Daten? Dementsprechend wird gehandelt. 
In der Main wird dann das Display beschrieben falls das Flag gesetzt 
ist.
Ist etwas rudimentär, nur auf eingehende Daten ausgelegt und ohne 
jedwede Fehlerbehandlung. Musst es dir halt umstricken wie es für dich 
passt.

Ich hab mit dem 841 nicht soviel gemacht, ist auch schon etwas länger 
her; aber das TWI war eigentlich problemlos WIMRE.

von auch Klaus (Gast)


Lesenswert?

Klaus schrieb:
> USI habe ich mit verschiedenen Typen gemacht. Verwende dazu die Datein
> von Jtronic.

Also nicht gemacht, sondern ^C ^V.

Klaus schrieb:
> Suche aber was für normales C. Das
> ganze scheint nicht so einfach zu sein.

I2C gehört zu den einfachsten Protokollen, die ich kenne. Man braucht 
auch keine formale Zustandsmaschinen Spezifikation, dazu sind es einfach 
zuwenig Zustände. Wer es einmal verstanden hat, implementiert es aus dem 
Kopf.

MfG Klaus

von Klaus (Gast)


Lesenswert?

Danke für die Info und das Beispiel. Werde es ausprobieren. Wenn I2C Bus 
so einfach, warum haben viele Probleme damit? Mit den andren ICs habe 
ich keine Probleme, bloss der 841 zickt ganz schön rum. egal, adnke an 
alle

von c-hater (Gast)


Lesenswert?

Klaus schrieb:

> Wenn I2C Bus
> so einfach, warum haben viele Probleme damit?

Weil die meisten halt genau solche Copy&Paste-"Programmierer" sind wie 
du.

von H.Joachim S. (crazyhorse)


Angehängte Dateien:

Lesenswert?

Für die Faulen: Wizard von CodeVision, gibts auch als Demo. Keine Ahnung 
ob die TWI unterstützt. Damit hatte ich das in 2min am laufen, war 
allerdings der Tiny441, sollte aber bis auf den Speicher identisch sein.

Nein, das ersetzt nicht das Verstehen, ist aber sehr schön, dass man 
erst mal was lauffähiges hat und das dann Schritt für Schritt durchgehen 
kann.

von HP41 (Gast)


Lesenswert?

Klaus schrieb:
> Danke für die Info und das Beispiel. Werde es ausprobieren. Wenn
> I2C Bus
> so einfach, warum haben viele Probleme damit? Mit den andren ICs habe
> ich keine Probleme, bloss der 841 zickt ganz schön rum. egal, adnke an
> alle

Ich habe mir mal die App note 311 zu Gemüte geführt. Von wegen State 
machine ist nicht nötig weil man das alles im Kopf halten kann. Der 
Grund warum das so einfach sein soll besteht ja darin, daß der 
Hersteller diesen Teil in HW gelöst hat um SW Latenzen und komplizierten 
Code zu vermeiden. Die Frage wie dieser Teil gelöst ist, lohnt sich 
näher betrachtet zu werden. Daß der TWI Sklaven Code im Beispiel so 
einfach ist, ist kein Wunder und ist eigentlich ein bischen Schummeln:-)

In meinem vorherigen Beitrag wollte ich die Frage aufwerfen wie man das 
bei anderen uC ohne solche TWI Unterstützung machen könnte. In diesen 
Fall würde eine formale Doku dieser Implementierung schon nützlich sein 
weil die TWI HW ein schwarzer Block ist und sein Eigenleben hat was 
Bustransaktionen betrifft.

Bis jetzt konnte ich herstellerseitig noch nie eine formale 
Dokumentation bezüglich der TWI Implementierung in ausreichenden Detail 
finden. Es werden ja nur die Schnitstelleregister und teilweises 
Verhalten dokumentiert, aber nicht die interne Logik im einzelnen. Die 
gleiche Notwendigkeit besteht ja wenn man einen TWI Sklaven mittels CPLD 
oder FPGA verwirklichen möchte. Da muß man ja auch die State Machine 
Logik und HW Verhalten genauestens definieren können. Es ist ja schön, 
daß die Hersteller einem mit TWI halb entgegen konmen. Die andere Hälfte 
wäre auch nützlich dokumentiert zu haben. Wenn man natürlich nur 
einfachst TWI Sklave verwirklichen möchte, reicht das Erhältliche.

Es gibt in Quartus übrigens ein CPLD Beispiel. Aber ein uC ist oft auch 
keine schlechte Lösung und viel billiger.

Hat sich denn noch keiner von Euch über den "schwarzen Block" viel 
Gedanken gemacht?

von Karl K. (karl2go)


Lesenswert?

HP41 schrieb:
> In meinem vorherigen Beitrag wollte ich die Frage aufwerfen wie man das
> bei anderen uC ohne solche TWI Unterstützung machen könnte.

Software-TWI-Slave. Ist bis 100kHz kein Problem.

von auch Klaus (Gast)


Lesenswert?

Ich will jetzt nicht den Versuch machen, das ganze I2C Protokoll hier 
aufzuschlüsseln. Aber ein paar Hinweise zum Prinzip: der Transfer eines 
Bits ist ein Handshake auf der Clockleitung. Der Master zieht Clock auf 
low, mindestens so lange, wie als Bitzeit/2 verabredet ist ( 5 us bei 
100kHz). Bei einem Write legt er die Daten auf SDA. Der Slave erkennt 
die fallende Flanke der Clock und zieht seinerseits SCL auf low. Dann 
liest er die Daten vom Master bzw. legt seine Daten auf SDA und lässt 
SCL wieder los. Ist SCL wieder oben, wartet der Master wieder eine halbe 
Bitzeit und alles beginnt von vorne. Meist sind die Slaves so schnell, 
daß sie SCL losgelassen haben, bevor der Master es tut. Jetzt gilt es 
noch Start, Stop und Bus Idle zu erkennen.

MfG Klaus

von Klaus (Gast)


Lesenswert?

Da wird es wohl Zeit etwas grundlegendes mit dem I2C Bus und dem Attina 
841 zu machen. Von der Grösse her ist er ja bestens geeignet kleine 
Platinen mit verschiedenen Elementen aufzubauen und mit dem Bus zu 
verbinden. Hatte so was ähnliches als Start UP für einen PIC gesehen.

von Dieter R. (drei)


Lesenswert?

Ich habe hier:

https://www.avrfreaks.net/comment/2694441

Code für Series 1 gepostet. Nach Überfliegen des Datenblatts scheint 
mir, dass die Slave Engines für Series 1 und ATtiny841 ziemlich ähnlich, 
aber nicht ganz identisch sind. Mit Copy & Paste wird es nicht gehen, 
aber ich vermute, es sind nur wenige Anpassungen notwendig.

Der Slave ist Interrupt-basiert und emuliert ein Registerfile, ähnlich 
einem EEPROM. Für Series 1 waren wegen eines (von Microchip inzwischen 
bestätigten) Bugs an einer Stelle ein paar Klimmzüge notwendig, bei 841 
mag das anders sein. Der Versuch, das Thema hier im 
Microcontroller-Forum ernsthaft zu diskutieren, ist seinerzeit leider in 
einem Schwall von unqualifizierten Hass-Postings geendet.

Vielleicht nützt es ja was.

von Klaus (Gast)


Lesenswert?

Hallo Alexander
Bei anderen Beispielen mit Code wird I2C Master oder TWIslave mit c und 
verwendet. Das hast du nicht drin. Geht das auch diese Datein?

Alexander S. schrieb:
> Häh? Das TWI_Modul vom 841 ist doch relativ komfortabel, macht fast
> alles selber.

von c-hater (Gast)


Lesenswert?

Klaus schrieb:

> Bei anderen Beispielen mit Code wird I2C Master oder TWIslave mit c und
> verwendet. Das hast du nicht drin. Geht das auch diese Datein?

Wenn du wenigstens auch nur einmal kurz in's DB geschaut hättest, dann 
wüsstest du, dass die I2C-Hardware des 841 ausschließlich Slave sein 
kann...

von Klaus (Gast)


Lesenswert?

Ich habe in das Datenblatt geschaut und gesehen das es nur Slave 
erlaubt. Bin gerade dabei die Register anzuschauen und die einzelnen 
Funktionen durchzugehen und hoffentlich auch zu verstehen

c-hater schrieb:
>> Bei anderen Beispielen mit Code wird I2C Master oder TWIslave mit c und
>> verwendet. Das hast du nicht drin. Geht das auch diese Datein?

Mit diesem I2C Master meine ich eine Datei von Peter und nicht den 
Betrieb als Master

von Alexander S. (alex998)


Lesenswert?

Klaus schrieb:
> Bei anderen Beispielen mit Code wird I2C Master oder TWIslave mit c und
> verwendet. Das hast du nicht drin. Geht das auch diese Datein?

Du brauchst da keine weiteren Treiber oder sonst was; die Hardware 
erledigt das alles. Wie ich bereits schrieb, du initialisierst das 
Interface und schaust dann in der ISR im Statusregister nach was vom 
Master kam. Da ist keine Magie dabei.


> Bin gerade dabei die Register anzuschauen und die einzelnen
> Funktionen durchzugehen

Ein sehr guter Ansatz...

von Klaus (Gast)


Lesenswert?

Bleibt bloss die Frage ob ich alles korrekt verstehe und auch umsetze 
...

von (prx) A. K. (prx)


Angehängte Dateien:

Lesenswert?

I2C Slave auf einem ATTiny841 ist ausgesprochen einfach. Nur völlig 
anders als auf den vorherigen Megas/Tinys. Ich hatte den 841 per UART an 
einen RasPi gehängt. Anbei der Codeschnipsel dazu.

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

Danke für den Code. Habe mal reingeschaut. Nach dem ersten Eindruck sind 
die unterschiedlichen Codes relativ gleich auch stückweise nur.

von (prx) A. K. (prx)


Lesenswert?

HP41 schrieb:
> Ich habe mir mal die App note 311 zu Gemüte geführt.

Die beschreibt Atmels althergebrachtes Master/Slave Modul, wie es z.B. 
in Mega8/16 verwendet wird, nicht aber das damit ein keiner Weise 
verwandte Slave-only Modul des Tiny841.

von c-hater (Gast)


Lesenswert?

Klaus schrieb:

> Danke für den Code. Habe mal reingeschaut. Nach dem ersten Eindruck sind
> die unterschiedlichen Codes relativ gleich auch stückweise nur.

Mehr gibt es einfach nicht zu schreiben, weil halt die Hardware fast 
alles selber erledigt.

Du bist so dramatisch unfähig, dass du dich mit Wertungen einfach mal 
stark zurückhalten solltest. Statt dessen solltest du dich auf deinen 
faulen Arsch setzen und versuchen, zu begreifen, was du da für lau 
geliefert bekommen hast...

von (prx) A. K. (prx)


Lesenswert?

Klaus schrieb:
> Danke für den Code. Habe mal reingeschaut. Nach dem ersten Eindruck sind
> die unterschiedlichen Codes relativ gleich auch stückweise nur.

Bei mir ist beides drin: Slave Read und Slave Write, und bei Slave Write 
auch noch jener Teil, der I2C Frames trennt. So arg viel mehr gibts bei 
I2C nicht. Das war auch nicht als fertige Lösung für dich gemeint, 
sondern ...

Klaus schrieb:
> Hat jemand ein Beispiel dazu?

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


Lesenswert?

Aber du hast recht, das Error-Handling aus main() fehlte:
1
                ATOMIC_BLOCK(ATOMIC_FORCEON) {
2
                        if ((TWSSRA & 1<<TWBE) && (i2c_state == I2C_Idle)) {
3
                                // bus error set, and safe to transmit error message
4
                                TWSSRA = 1<<TWBE; // reset bus error
5
                                xmit_string(PSTR("BUS ERROR"), 0);
6
                        }
7
                }
Und im Watchdog-Interrupt gibts eins auf die Nuss, wenn I2C zu lange 
aktiv ist, weil dann der WDT nicht zurückgesetzt wird:
1
        if (i2c_state == I2C_Idle) {
2
                WDTCSR |= 1<<WDIE; // re-enable the watch dog interrupt
3
                wdt_reset();
4
        }

: Bearbeitet durch User
von Peer (Gast)


Lesenswert?

Hallo
lese diesen Beitrg schon einige Zeit mit. Habe auch so meine Probleme 
mit dem Attiny 841. Der ist halt anders als die anderen Attiny. Mir geht 
es eigentlich um das das ADC und die übertragung mit I2C. Habe schon 
einiges dazu programmiert. Leider klappt die übertgaung nicht so wie sie 
soll. Im Master habe ich eine Abfrage drin die die Adresse des Slave 
überprüft ob sie vorhanden ist. Dies Abfrage funktioniert sehr gut und 
der Slave wird als vorhanden angezeigt.Habe für mich auch Angaben zu den 
Registern dazu geschrieben. Nur leider kommt beim Master nichts an.
Mein Code:
1
void I2C_init(void)
2
  {
3
  TWSA = I2C_SLAVE_ADDRESS;          // TWI Adressregister
4
  TWSD = 0xFF;                // Datenregister
5
  TWSCRA = (1<<TWEN)|(1<<TWSHE)|(1<<TWASIE)|(1<<TWSIE)|(1<<TWDIE);      
6
  // Register A, TWEN-Schnittstelle Aktivieren, TWSHE-Haltezeit aktivieren, TWASIE-Adressenunterbrechung aktivieren, 
7
  // TWSIE-Stop Unterbrechung aktivieren, TWDIE-Datenunterbrechung aktivieren 
8
    TWSCRB = (1<<TWAA)|(1<<TWCMD1)|(0<<TWCMD0);  // Register B, TWI Bestätigungsaktion, TWI Befehl
9
  sei();      // Interrups einschalten
10
  }
1
ISR( TWI_SLAVE_vect )
2
  {
3
    uint8_t status = TWSSRA & 0xC0;      // Register A
4
  if (status & I2C_DATA_INTERRUPT)
5
  // Daten wurden vom Master empfangen oder werden angefordert
6
    {
7
      if (TWSSRA & (1 << TWDIR))          // Master fordert Daten vom Slave an
8
      {
9
      if(tx_buf_index >= sizeof(tx_buf))
10
        {
11
        tx_buf_index=0;
12
        }
13
      TWSD = tx_buf[tx_buf_index];
14
      tx_buf_index++;
15
      TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
16
      }
17
    else       // Master sendet Daten zum Slave
18
      {
19
      TWSCRB |= (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
20
      command = TWSD;
21
      }
22
    }
23
  else if (status & I2C_ADDRESS_STOP_MATCH)
24
    {
25
    if (TWSSRA & I2C_BUS_COLLISION)
26
      {
27
      TWSCRB = (uint8_t) (1<<TWCMD1);
28
      }
29
    else
30
      {
31
      if (TWSSRA & (1<<TWAS))
32
        {
33
        // ACK
34
        TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
35
        }
36
      else
37
        {
38
        // Stop Condition
39
        TWSCRB = (uint8_t) (1<<TWCMD1);
40
        }
41
      }
42
    }
43
  }
1
int main(void)
2
  {
3
    //ADC_init();
4
  I2C_init();
5
  while(1)
6
    {
7
    if(command != 0x00)
8
    {
9
      switch(command)
10
      {
11
        case 0x01:
12
        // Test Daten
13
        tx_buf[0] = 0x01;
14
        tx_buf[1] = 0x02;
15
        tx_buf[2] = 0x03;
16
        tx_buf[3] = 0x04;
17
        tx_buf_index = 0;
18
        break;
19
      }
20
      command = 0x00;
21
    }

von Peer (Gast)


Lesenswert?

Könnte jemand sich das mal ansehen?

von Peer (Gast)


Lesenswert?

Jemand eine Idee dazu?

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.