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
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.
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
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.
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?
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.
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.
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.
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
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
Klaus schrieb: > Wenn I2C Bus > so einfach, warum haben viele Probleme damit? Weil die meisten halt genau solche Copy&Paste-"Programmierer" sind wie du.
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.
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?
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.
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
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.
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.
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.
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...
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
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...
Bleibt bloss die Frage ob ich alles korrekt verstehe und auch umsetze ...
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
Danke für den Code. Habe mal reingeschaut. Nach dem ersten Eindruck sind die unterschiedlichen Codes relativ gleich auch stückweise nur.
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.
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...
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
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
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 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.