Heiner schrieb:> Leider konnte ich verstehen was ADCW ist.
Ich nehme an du hast es nicht verstanden.
Aber ein Blick ins Datenblatt (16.13.3) lässt die Vermutung
aufkommen dass es sich um eine Kombination von ADCL und ADCH
handelt.
Das bestätigt dann auch ein Blick in die Datei iotn841.h
Ben B. schrieb:> Für 8 Bit kann man das Alignment in ADCL/ADCH entsprechend einstellen
Siehe 16.13.5 im Datenblatt.
ADCSRB – ADC Control and Status Register B
Wenn ich das in 16.13.5 richtig verstanden habe besteht ADCW bei 10 Bit
aus ADCH und ADCL. Wenn ich nur 8 Bit brauche wird in Register ADCSRB
das Bit ADLAR auf 1 gsetzt.
Habe ich das richtig verstanden?
Heiner schrieb:> Wenn ich nur 8 Bit brauche wird in Register ADCSRB> das Bit ADLAR auf 1 gsetzt.
Ja, und nur ADCH auslesen (8 bittig!)... da die unteren 2 Bit
nicht zu auswerten sind.
Warum willst du nur 8 Bit?
Um es einmal zu verstehen und arbeite an einer übertragung mit I2C.
Wollte mir nicht gleich die 10 Bit antun.
Kannst du mir ein paar Tips geben wenn ich 10 Bit per I2C übertragen
will?
Heiner schrieb:> Kannst du mir ein paar Tips geben wenn ich 10 Bit per I2C übertragen> will?
Man überträgt einfach zweimal 8 Bit (ein 10 Bit ADC Wert wird
in einer 16 Bit Variable gespeichert, siehe Return-Wert ADCW)
da du 10 bit über I2C nicht einfach übertragen kannst.
Habe bisher die übertragung der Tastenzustände am Attiny 841 vom Slave
zum Master und zurück hinbekommen. Paralle habe ich den Komparator und
ADC am ATI 841 geschafft. Da der Ati 841 beim Bus sehr anders ist, kann
ich meine bisherigen Programm mit dem Atmega 128 nicht nutzen. Da werde
ich wohl erst einiges machen müssen.
Heiner schrieb:> Eine 16 Bit übertragung mit I2C habe ich noch> nie gemacht.
Wer es verstanden hat 1 Byte zu senden, kann auch ein zweites
übertragen.
Und wenn das nichts wird, dann liegen die Probleme ganz woanders.
Heiner schrieb:> Habe bisher die übertragung der Tastenzustände am Attiny 841 vom Slave> zum Master und zurück hinbekommen. Paralle habe ich den Komparator und> ADC am ATI 841 geschafft. Da der Ati 841 beim Bus sehr anders ist, kann> ich meine bisherigen Programm mit dem Atmega 128 nicht nutzen.
Nicht der Bus ist anders, nur die Hardware. Und deren Funktionsprinzip
ist sehr ähnlich, wenn man mal gedanklich auf Slave beschränkt und die
Smart-Features des 441/841-TWI-Slave aussen vor läßt, also nicht
aktiviert.
Unter diesen Randbedingungen kann man gut geschriebenen Slave-Code für
die normale Mega-TWI-Einheit praktisch ohne jegliche strukturelle
Änderungen für den TWI-Slave der 441/841 übernehmen. Man muß nur etliche
symbolische Konstanten singemäß anpassen.
Setzt natürlich voraus, dass man den Sinn verstanden hat, was bei selbst
geschriebenem Code vorausgesetzt werden kann. Nur bei C&P-Code muss man
erst verstehen lernen, was der eigentlich tut...
Stefan ⛄ F. schrieb:> Ich glaube der Heiner verarscht uns.
Daher wollte ich auch erst mal sehen was er selbst gemacht hat.
weiter weg schrieb:> Dann zeig mal deine 8 Bit Übertragung.
Aber die ganzen übereifrigen, unausgelasteten Technik-Freaks haben
solch massive Scheuklappen dass sie das nicht erkennen können.
Ich möchte euch auf keinen Fall verarschen. Um den Attiny 841 zu
verstehen gehe ich jeden Anwendungsfall nach Datenblatt durch. Dazu
übersetze ich mir den Inhalt, lese die Register genau und vergleiche es
mit den Programmen die ich bisher habe. Hatte euch ja schon öfters um
Rat gefragt und viele Infos dazu bekommen.
Mein Code für den Attiny841 als Slave zum I2C Bus:
Noch mal zur ADC.
Heiner schrieb:> Wenn ich das in 16.13.5 richtig verstanden habe besteht ADCW bei 10 Bit> aus ADCH und ADCL. Wenn ich nur 8 Bit brauche wird in Register ADCSRB> das Bit ADLAR auf 1 gsetzt.> Habe ich das richtig verstanden?
Habe jetzt ADCSRB |=(1<<ADLAR) auf 1 gesetzt. Habe dann die Spannung
zwischen 0 und 5V verändert. Klappt aber nicht damit nur 8 Bit zu
nutzen.
Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?
Heiner schrieb:> Habe jetzt ADCSRB |=(1<<ADLAR) auf 1 gesetzt. Habe dann die Spannung> zwischen 0 und 5V verändert. Klappt aber nicht damit nur 8 Bit zu> nutzen.
Doch das klappt schon. Wenn man verstanden hat, was da passiert.
> Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?
Garnicht. Wenn du nur 8 Bit des Ergebnisses haben willst, benutzt du
auch einfach nur acht Bit davon.
ADLAR dient nur dazu, die relevanten 8Bit der Wandlungsergebnisses in
einem 8Bit-Register bereitzustellen und erspart so, zwei Register
auszulesen und das Ergebnis erst passend zu hinschieben zu müssen.
Sprich: statt ADCW (2x 8 Bit) liest du nur ADCH aus. Da stehen deine 8
Bit schon vollkommen passend drinne. Die zwei wegzuwerfenden Bits stehen
in ADCL. Da du sie sowieso wegwerfen willst, brauchst du es erst
garnicht auslesen.
Heiner schrieb:> Klappt aber nicht damit nur 8 Bit zu nutzen.> Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?
Ich habe es dir doch beschrieben wie es funktioniert.
Was bitte ist an meinem Satz nicht zu verstehen?
Du schaffst es nicht deine Lesefunktion so abzuändern damit
es wie von mir beschrieben arbeitet?
weiter weg schrieb:> Ja, und nur ADCH auslesen (8 bittig!)... da die unteren 2 Bit> nicht zu auswerten sind.
Wenn du das nicht willst/kannst dann unterstelle ich dir Trollerei
oder vollständige Überforderung. Im zweiten Fall empfehle ich dir
ein anderes Hobby wie z.B. Wandern oder Stricken/Häkeln.
weiter weg schrieb:> Im zweiten Fall empfehle ich dir> ein anderes Hobby wie z.B. Wandern oder Stricken/Häkeln.
Mach Dich einfach weg. Ganz weit weg. Mach Dich RAUS!!
Warun wird hier einem sofort ein Troll zu sein untergeschoben?
Die Fragen die ich stelle sind von grossen Intresse für mich.
Ist das der Umgang von euch sogenannten Fachleuten mit Anfänger oder
macht ihr nur Stimmung oder blöde Anmache.
Zurüchk zum Thema.
Habe es jetzt so hinbekommen.
1
ADCSRB|=(1<<ADLAR);// bei 8 Bit links
2
while(ADCSRA&(1<<ADSC))
3
{// auf Abschluss der Konvertierung warten
4
}
5
//return ADCW; // ADC auslesen und zurückgeben bei 16 Bit
6
returnADCH;// 8 Bit mit ADLAR=1
Damit läuft 8 Bit und ich kann mit den Auskommentierten Zeilen auf 16
Bit umstellen.
Bleibt noch das Problem mit der übertragung von 16 Bit mit dem Bus.
Heiner schrieb:> Bleibt noch das Problem mit der übertragung von 16 Bit mit dem Bus.
Du meinst, es bleibt das Problem, dass dir da noch niemand eine fertige
Lösung geliefert hat, richtig?
Wie wäre es mal mit tatsächlich selber programmieren? Alles Nötige an
Hinweisen hast du im Laufe dieses Threads bereits bekommen.
Mehr geht nicht, das wäre Auftragsarbeit, dafür musst du mit Kohle rüber
kommen.
Heiner schrieb:> Bleibt noch das Problem mit der übertragung von 16 Bit mit dem Bus.
Das wirkt wirklich äusserst dümmlich oder trollig. Bleibt keine
andere Schlussfolgerung.
Hier hattest du bereits den Hinweis:
Arduino Fanboy D. schrieb:> Wer es verstanden hat 1 Byte zu senden, kann auch ein zweites> übertragen.
Nicht schon wieder das mit dem Troll. Versuche einfach es zu verstehen.
Hatte weiter oben bereits den Code für den Attiny 841 und den I2C bus
angegeben. Da er anders ist z.B. als bei einem Slave (kein Prozessor)
mit 16 Bit sieht die übertragung anders aus. Leider habe ich im Netz
keine Info dazu gefunden.Vielleicht gehen ein paar Brocken zu meinem
Verständnis.
Heiner schrieb:> mit 16 Bit sieht die übertragung anders aus.
Nur ganz unwesentlich.
> Leider habe ich im Netz> keine Info dazu gefunden.Vielleicht gehen ein paar Brocken zu meinem> Verständnis.
Mein Gott. Verstehe einfach, wie I2C funktioniert und benutze es. Das
hat doch rein garnix mit der AVR8-Architektur im Allgemeinen oder dem
TWI-Slave der ATiny441/841 im Besonderen zu schaffen.
Man muss einfach nur verstehen, wie der Bus funktioniert und den
vorhandenen Code entsprechend nutzen. Wenn man ein Byte korrekt senden
kann, zwei aber nicht, beweist das genau eine Sache: Man benutzt Code,
den man nicht verstanden hat. Und die einzige logische Erklärung dafür
ist:
Weil man wohl einfach zu FAUL war, zu lernen, wie der Bus
funktioniert...
c-hater schrieb:> Weil man wohl einfach zu FAUL war, zu lernen, wie der Bus> funktioniert...
Ein Troll hat immer noch ein "gutes" Argument in der Hinterhand.
Hallo Heiner,
ich sehe 2 Möglichkeiten
a) du zeigst uns wie du derzeit ein Byte sendest und empfängst
b) du nimmst die Arduino IDE, installierst zusätzlich das Package von
SpenceKonde https://github.com/SpenceKonde/ATTinyCore und nutzt die
fertige Lib von den Arduino Leuten bzw. die angpasste von Spencekonde an
den ATtiny
Heiner schrieb:> Hatte weiter oben bereits den Code für den Attiny 841 und den I2C bus> angegeben.
Das hast du nicht!
Die Initialisierung, ja.
Die ISR auch.
Aber die (read/Write) API zur Software hast du geheim gehalten.
Also:
Nur ein untestbares Fragment gezeigt.
Exakt den Bereich, an dem es hakt, geheim gehalten.
Im Moment sendest du genau ein Byte aus 'tx_buff'. Eine Ansatz wäre,
aus tx_buff ein Array aus 2 Byte zu machen und dann tx_buff[0] und
tx_buff[1] hintereinander zu senden.
In deiner ADC Routine könnte zum füllen dann stehen
Danke für die Info
Matthias S. schrieb:> In deiner ADC Routine könnte zum füllen dann stehen> tx_buff[0] = ADCH;> tx_buff[1] = ADCL;
Bei 16 Bit verwende ich ADCW und das besteht aus ADCH und ADCL.
Wenn ich nur 8 Bit verwende, nutze ich ADCH und ADLAR=1.
Dann brauche ich im Master nur aus denn 2 x 8 Bit wieder 16 Bit machen.
Das gefällt mir.
Heiner schrieb:> if (TWSSRA & (1 << TWDIR)) // Master fordert Daten vom Slave an> {> TWSD = tx_buff;> TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));> }
Meinst du diese Stelle?
Das Programm des Slave beim I2C Bus bzw. ISR empfinde ich als relativ
gross und kompliziert. Da ich noch nicht beim Bus angekommen bin, ergibt
sich eine Frage für mich.
Gibt es ein weniger Aufwändiges Programm für den Slave beim Attiny 441?
Hallo,
I2C erfordert mehr Aufwand. Derzeit schreibst du das zu sendende Byte
direkt in das Senderegister. Du weißt es kann nur ein Daten Byte geben,
deswegen ist alles andere "egal". Für mehr als 1 Daten Byte benötigt man
ein Protokoll. Ansonsten weiß man nicht ob ein Byte das Erste oder das
Zweite oder welches überhaupt ist, wenn man hintereinander senden würde.
Schau dir einmal die App Note AVR311 und AVR315 von Atmel an. Die
Register passt du auf deinen ATtiny an.
https://www.microchip.com//wwwAppNotes/AppNotes.aspx?appnote=en591794https://www.microchip.com//wwwAppNotes/AppNotes.aspx?appnote=en591792
Am Ende hast du eine Sende- und Empfangsfunktion.
Donnerwetter!
Du bist wirklich ein Crack!
Weißt Du, wofür “nop” oder “Sam” benötigt wird? Ich bezweifle das, und
mit “Copy & Paste” kommst du nicht weit
SCNR
Hannes
Hannes schrieb:> Mist!>> Muss natürlich “asm” heißen nicht “Sam” - sche** Autokorrektur
Ja, die Autokorrektur macht schöne Sachen. Mir hat sie mal ein Auto von
MAN auf Scania korrigiert. Da konnte ich dann 2 Tonnen mehr laden.
Auch wenn ich noch nicht restlos davon überzeugt bin, dass wir hier
nicht über den Tisch gezogen werden, zeigt sich doch ganz deutlich, wie
heute Programmiert wird! Entsetzlich :-)
Gruß Rainer
Heiner schrieb:> Habe mir die Stellen angesehen. Bin dazu geteilter Meinung. Habe z.B.> Angaben wie asm und nop gefunden. Dachte eigentlich das sowas lange raus> ist.
Hallo,
du meinst das?
1
asm("nop");
nop bedeutet eine einzige Taktverzögerung in der Arbeitung. asm bedeutet
das nop inline gemacht wird, also wirklich real einen Takt Pause
erzeugt. Im Kontext betrachtet mit den Kommentaren steht das in dem Code
Bsp. nur als Platzhalter für irgendwelchen weiteren Code.
nop ist auch heute noch praktisch wenn man es sinnvoll einsetzt. Bspw.
redet dein µC mit einem Device welches mittels meinetwegen SPI
angesprochen wird. Jetzt ist dein Bus samt deiner Code Abarbeitung
schneller wie das Device mit gewissen Wartezeiten zwischen seinen
Kommandos/Daten. Allerdings sind die Wartezeiten auch nicht so lang,
dass es sich lohnt kurz andere Dinge zu erledigen. Vorrausgesetzt Du
möchtest das Device so schnell wie möglich fertig behandelt haben. Du
benötigst bspw. 100ns Wartezeit wofür es sich nicht lohnt erst aus einer
Funktion rauszuspringen und dann wieder reinzuspringen. Das benötigt
deutlich mehr Takte als was es bringt. Hier kannste bspw. 2x nop
einbauen. CPU Takt 20MHz -> 1x nop 50ns. Wenn das Device nicht
zeitkritisch ist muss man es nicht machen und kann zwischendurch anderes
erledigen.
Oft sieht man folgendes define.
1
#define NOP __asm__ __volatile__ ("nop\n\t")
Wofür \n\t hinter nop dienen soll kann ich nicht erklären.
new line und Tabulator? Wer kann den Grund dafür zusammen mit nop
erklären?
Veit D. schrieb:> Wofür \n\t hinter nop dienen soll kann ich nicht erklären.> new line und Tabulator? Wer kann den Grund dafür zusammen mit nop> erklären?
Wenn man sich den ASM Zwischencode anzeigen lässt, steht das schön
untereinander, statt in einer Zeile gequetscht
Veit D. schrieb:> Wofür \n\t hinter nop dienen soll kann ich nicht erklären.
Zeilenumbruch und Tabulator.
In Assembler muss hinter jedem Befehl ein Zeilenumbruch kommen und die
Befehle sind üblicherweise mit Tabulator ein gerückt. Das spielt erst
eine Rolle, wenn du mehrere asm befehle hintereinander schreibst und
dann den Quelltext als Assembler-Listing ausgibt. Der sieht dann schöner
aus.
Veit D. schrieb:> Im disassamblierten Code kann ich das> nicht herauslesen. Da finde ich nur
Da lassen sich die \n und \t auch nicht mehr finden.
Der C Compiler baut ASM Zwischencode(auf Wunsch), da siehst du es.
Der C++ Compiler tut das nicht.
Du scheinst es nicht zu glauben. Ich will keinen ärgern, über den Tisch
ziehen oder ähnliches damit machen. Mein Ziel ist es einfach den Attiny
441 (841) zu verstehen und anzuwenden. Mir gefällt einfach die
Baugrösse, klein relativ wenige Pins und viele Anwendungen. Leider
scheint meine Freude an dem IC nur von wenigen geteilt zu werden. Man
findet im Netz wenige Beispiel dazu. Ja es stimmt, verwende teilweise
vorhandenen Code aus dem Netz. Das sind dann aber Sachen um die Funktion
zu verstehen oder einfach mal anschauen wie es andere machen. Wenn ich
dann das Datenblatt dazunehme komme ich mit den Funktione weit aus
besser klar. Da die Anwendung aber auf mein Brett bezogen sind, muss ich
alles umbauen oder halt neu machen.
Soweit ist das klar. Sehen wir mal was es so für den I2C Bus gibt. Ein
Programm geht ja, ist aber wahrscheinlich einfacher möglich.
LG Heiner
@Stefan
Das wage ich zu bezweifeln. Auch wenn Arduino Libraries bietet, mit
denen man Funktionen “zusammenklimpern” kann, muss man dennoch wissen,
wie es geht 😉.
Außerdem hat Veit D. schon mit den links brauchbare Hinweise gegeben-
wenn man aber nicht versteht sie anzuwenden…
Stefan ⛄ F. schrieb:> Mit Arduino wärst du längst fertig.
Das ist schon möglich.
Kann ich den die ganzen Sachen verwenden wenn ich nicht mit einem
Arduino arbeite?
Habe bisher alles in C gemacht ohne die ganzen Sachen von Arduino.
Alle notwendigen Sachen für den I2C Bus beim Attiny 841 sollen im
Datenblatt stehen. Mag sein, leider schwer für mich zu verstehen. Habe
angefangen die Register anzuschauen und wenn möglich zu verstehen. Ist
leider für mich sehr schwer. Kann mir jemand dabei helfen es zu
verstehen?
Die ADC mit 8 und 16 Bit geht ohne Probleme.
Möchte jetzt einfach weitermachen und den ADC Wert auf einem Display mit
dem Bus darstellen. Dazu möchte ich einen Atmega 128 als Master
verwenden und ein Display ansteuern. Die Ansteuerung mit dem Atmega
funktioniert bereits korrekt.
Soll ich lieber etwas neues aufmachen?
Hannes schrieb:> Ich dachte, Du hättest den I2C Bus vom Attiny 841 schon funktionsfähig> bzw. schon Daten per I2C ausgetauscht?
Ja das stimmt, habe bereits Daten ausgetauscht. Leider ist das Programmm
für den Slave etwas gross geraten. Deshalb mein Versuch es etwas kleiner
und damit übersichtliches zu machen. Habe das Datenblatt dazu genommen,
komme leider nur sehr schwer damit zurecht. Das funktionierende Beispiel
für den slave kann ich kaum nachvollziehen.
Hallo Heiner
Habe ich das korrekt verstanden:
Du willst mit dem Attiny 841 per ADC Werte einlesen (8 Bit), diese per
I2C an den Atmega 128 schicken und die Werte per Display (das direkt
ohne I2C am Atmega 128 angeschlossen ist) anzeigen.
Stimmt meine Zusammenfassung?
Heiner schrieb:> Kann ich den die ganzen Sachen verwenden wenn ich nicht mit einem> Arduino arbeite?
Ja schon, weitgehend. Voraussetzung ist, dass Arduino diesen
Mikrocontroller unterstützt. Offenbar gibt es für den ATtiny841 ein
passendes Plugin (Core).
> Alle notwendigen Sachen für den I2C Bus beim Attiny 841 sollen im> Datenblatt stehen. Mag sein, leider schwer für mich zu verstehen.
Ja das ist so. Die I²C Schnittstelle ist komplizierter als die meisten
anderen, weil sie nicht nur einfach nur Daten rein/raus schiebt sondern
ein komplettes Protokoll implementiert.
In Arduino ist der Teil bereits fertig. Diesen Anzuwenden ist fast so
einfach, wie printf().
> Kann mir jemand dabei helfen es zu verstehen?
Fange mal mit eine Beschreibung des Protokolls an:
https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/
Erstmal musst du verstehen, welche Signale der Bus in welcher
Reihenfolge überträgt und welche Zustände es gibt. Denn diese spiegeln
sich in den Registern wieder.
Lies auch die I²C Spezifikation, das Dokument ist uralt aber sehr gut:
https://www.nxp.com/docs/en/user-guide/UM10204.pdf
Hannes schrieb:> Du willst mit dem Attiny 841 per ADC Werte einlesen (8 Bit), diese per> I2C an den Atmega 128 schicken und die Werte per Display (das direkt> ohne I2C am Atmega 128 angeschlossen ist) anzeigen.
Stimmt nicht ganz. Der Attiny 841 soll per I2C an den Atmega 128
angeschlossen werden. Auch das Display wird per I2C angeschlossen z.B.
mit PCF8574. Verwende teilweise verschiedene Displays. Das Display und
Verbindung mit verschiedenen Slaves funktioniert korrekt.
Stefan ⛄ F. schrieb:> Ja das ist so. Die I²C Schnittstelle ist komplizierter als die meisten> anderen, weil sie nicht nur einfach nur Daten rein/raus schiebt sondern> ein komplettes Protokoll implementiert.
Da gebe ich dir sofort Recht.
Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere
Typen mit dem gleichen Protokoll.
LG Heiner
Heiner schrieb:> Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere> Typen mit dem gleichen Protokoll.
Die Frage verstehe ich nicht
I2C ist ein Protokoll!
Das Protokoll besteht aus einer Hardware Vereinbarung und einem
logischen Regelwerk.
Ich sage mal: ALLE µC können I2C.
Ein paar Tinys bieten dafür den USI Block
Andere Mega, nutzen spezialisierte TWI Einheiten.
Und per Software geht auch immer, wenn sonst nix geht.
Also:
Protokolle hat man nicht, sondern man implementiert sie.
Ist klar geworden, wo der Fehler in der Frage liegt?
Vom Hersteller dieser Attiny werden noch andere Typen produziert. Gibt
es andere Typen die die gleiche Hardware haben? Bei denen man auch mit
der gleichen Software arbeiten kann?
Beispiel:
Es gibt Attiny die haben kein I2C. Da kann man per Software etwas
machen.
Es gibt Attiny die haben I2C Bus ohne eigenes Protokoll.
Gibt es andere Attinys die das gleiche Protokoll verwenden?
Kurz gesagt, gibt es noch andere Typen deren Software auf dem Attiny 441
anwenden oder vergleichen kann?
Also ich habe den Tiny841 in einigen Projekten im Einsatz. Der tut was
er soll, ohne große Überraschungen. Keine Ahnung warum jetzt
ausgerechnet dieser Controller hier das Problem sein soll. Der TE ist
das Problem. Mit dem Wissenstand wird JEDER Controller zum Problem.
Daher kann ich leider auch nicht wirklich On-Topic antworten. Das wäre
alles müßig und vergebens.
Verwende selber diesen Controller in einigen Anwendungen. Da ich ein
Anfänger bin erarbeite ich mir die Anwendungen. Schaue dazu ins
Datenblatt und gehe die verschiedenen Möglichkeiten durch. Weiter oben
habe ich nach ADC gefragt. Das funktioniert jetzt ohne Probleme. Kann es
Anwenden und Nutzen. Bin dan zur nächsten Stufe gegangen und das ist für
mich I2C, die übertragung der Daten vom Slave zum Master und Anzeige auf
einem Display. Bei anderen Controller habe ich das relativ einfach
hinbekommen. Leider ist das Beispiel für einen funktionierenden Slave
sehr gross und für mich in einigen Sachen nicht verständlich. Deshalb
einfach die Frage nach Hilfe dabei.
Hannes schrieb:> Hast Du hier schon mal geschaut> Beitrag "ATtiny841 I2C Slave Beispiel"
Ja, diesen Beitrag kenne ich. Er ist auch Grundlage für meinen Slave.
Mein Programm funktioniert damit, noch ein paar Anpassungen und es geht.
Was ich daran nicht verstehe ist die ISR. Die ist doch so gross.
Geht das nicht auch kleiner?
Hallo Hannes
Es geht haupsächlich darum es zu verstehen.
Habe jetzt im Netz gesucht und noch einiges gefunden.
Einfache Frage dazu:
Warum braucht der Attiny 441
- void Timer0_init(void)
- ISR(TIMER0_COMPA_vect)
- ISR(TWI_SLAVE_vect)
Da ich den Attiny 441(841) in verschiedenen Schaltungen verwenden
möchte, kann es dazu führen 16 Bit oder 8 Bit oder mehrfache 8 Bit (z.B.
2 oder 4 x ADC) oder (schnelle) Schalterstelleungen zu übertragen. Das
nutze ich z.B. um eine Tasterentprellung zu machen. Dadurch kann man
Tasten verschieden nutzen. Oder einen Enkoder als universeller Eingabe
zu verwenden oder ein Joystick.
Teilweise sind Teile da von schon lauffähig, andere warten noch auf das
Programm.
LG Heiner
Heiner schrieb:> Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere> Typen mit dem gleichen Protokoll.
Alle Mikrocontroller mit I²C (bzw. TWI), also eigentlich fast alle außer
ein paar wenige Ausnahmen die nur USI haben. Die sind noch schwieriger
zu programmieren.
Heiner schrieb:> Vom Hersteller dieser Attiny werden noch andere Typen produziert. Gibt> es andere Typen die die gleiche Hardware haben? Bei denen man auch mit> der gleichen Software arbeiten kann?
Was soll denn diese Frage? Andere Typen mit gleicher hardware wirst du
genau so wenig programmieren können. Bleibe mal lieber auf dem Weg zur
Problemlösung.
Hallo,
ehrlich gesagt verstehe ich dein Problem, Heiner, so langsam auch nicht
mehr. Wenn du es bei anderen Controllern hinbekommen hast, woran
scheitert es dann beim ATtiny? Das kam noch nie zur Sprache. Schau mal
ob du damit was anfangen kannst.
http://www.peterfleury.epizy.com/avr-software.html#libs
Es ist auch keine Schande sich die Arduino Quellen anzuschauen oder gar
zu nutzen. Im Grunde brauchst du dir nur die Quellen von Spencekonde
anschauen.
https://github.com/SpenceKonde/ATTinyCore/tree/master/avr/libraries/Wire
Jetzt bist du dran.
Es scheitert daran, daß manche AVR
- Kein I²C interface haben
- andere kein USI Interface besitzen
- wieder andere keins von Beiden und mittels Software selbst eines
gebastelt werden muss
- Unverständliche Software mit unverständlichen Bibliotheken aus aller
Herren Länder verwurstelt werden muß.
-> Schmeiß den Dreck aus dem Konntrolle und installiere Bascom. Damit
geht es am Einfachsten und es gibt jeweils ein Beispielprogramm in der
Hilfe.
Veit D. schrieb:> Schau mal> ob du damit was anfangen kannst.> http://www.peterfleury.epizy.com/avr-software.html#libs
Die Datein und Programme von Peter verwende ich bereits. Besonders für
I2C und das Display. Seine Programme sind auch Grundlage bei anderen
Sachen von mir.
Leider ist der Attiny 441 mit seinem I2C Bus anders als die anderen.
Nach Quellen im Netz haben die es total anders gemacht. Mit den anderen
Programmen die auf den slaves laufen geht es nicht. Teilweise sind die
Register anders.
Da muss ich mich weiter durchkämpfen.
LG Heiner
Stefan ⛄ F. schrieb:> Was soll denn diese Frage? Andere Typen mit gleicher hardware wirst du> genau so wenig programmieren können. Bleibe mal lieber auf dem Weg zur> Problemlösung.
Habe gehofft einen anderen IC zu finden mit der gleichen Hardware, wo es
vielleicht besser passende Software.
Heiner schrieb:> Stefan ⛄ F. schrieb:>> Was soll denn diese Frage? Andere Typen mit gleicher hardware wirst du>> genau so wenig programmieren können. Bleibe mal lieber auf dem Weg zur>> Problemlösung.>> Habe gehofft einen anderen IC zu finden mit der gleichen Hardware, wo es> vielleicht besser passende Software.
Naja, wenn's die gleiche Hardware ist, wird's wohl auch die gleiche
Software sein ...
Denke, es wäre zielführend, wenn Du mal ALLE (!) Deine bislang für
dieses Projekt erstellten Sourcen hier zur Verfügung stellen würdest;
vielleicht könnte man dann besser Hilfe geben.
Und wenn Du GENAU erklärst, was Deine Zielsetzung ist - z.B "mit dem
ATiny 841 ADC Werte (8Bit) einlesen, mittels I2C an den Master
(ATMega128) übertragen und diese Werte mittels I2C an ein LCD schicken
zwecks Anzeige der 8-Bit ADC Werte" - eine klar umrissene
Aufgabenstellung...
mfg
Egonwalter M. schrieb:> Und wenn Du GENAU erklärst, was Deine Zielsetzung ist - z.B "mit dem> ATiny 841 ADC Werte (8Bit) einlesen, mittels I2C an den Master> (ATMega128) übertragen und diese Werte mittels I2C an ein LCD schicken> zwecks Anzeige der 8-Bit ADC Werte" - eine klar umrissene> Aufgabenstellung...
Du hast es bereits gesagt. Genauso will ich es machen. Die gesamte
vorhanden Software steht bereits oben drin. ADC funktioniert dank eurer
Hilfe. Jetzt bleibt noch die Werte zum Master zuschicken und dann
anzuzeigen
Hallo Heiner
Ich versteh's nicht - Du hast doch Dein Programm von
Beitrag "Re: ATtiny841 I2C Slave Beispiel"
- dieses Programm soll doch funktionieren, speziell nach den
Zeit-Anpassungen beim Master
- Was funktioniert denn bei Deinem Programm nicht?
- Beim o.a. Programm sind ja DEBUG Ausgaben, damit man feststellen kann,
was und wo's klemmt...
- eigentlich müsstest Du doch das o.a. Programm problemlos übernehmen
können, da es für den Attiny 841 ist und einen Sendebuffer von 4 Bytes
beim Slave (Attiny 841) hat ...
mfg
Ja das stimmt genau. Das Programm funktioniert korrekt. Was ich noch
machen muss, die Anpassung an 8 oder 16 Bit und die passende übertragung
dazu.
Was mich bei diesem Programm verunsicht ist die Grösse. Dadurch ist es
für mich sehr unübersichtlich und kompliziert. Programme bei anderen
slaves sind übersichtlicher und damit besser zu verstehen.
Deshalb auch die Frage dazu, geht es nicht kürzer bzw. einfacher.
Hallo Heiner
Grundgütiger!
Wenn die Übertragung und die Anpassung an 8 bzw 16 Bit noch nicht
gemacht ist, funktioniert Dein Programm noch NICHT - ganz klar!
Und das Programm kürzer machen - geht bestimmt, dann musst Du es aber
auch mal zeigen, meine Glaskugel ist derzeit in Reparatur 🤷♂️.
Das Stück SW, das Du oben reingestellt hast ist gelinde gesagt …
Zeig was Du hast, sonst kann man Dir nicht helfen 🤷♂️
Eine schwammige Aussage wie “kann man das Programm nicht kleiner oder
kürzer machen” ist Unsinn
Mit freundlichen Grüßen
Egonwalter M. schrieb:> Hallo Heiner
Beim grundgütigen Egonwalter sollte man sich erst mal seinen
ureigensten Thread reinziehen bevor man darüber urteilt ob
er hier kompetente Hilfestellung geben kann oder nicht.
Beitrag "Arduino UNO USART Daten fehlen"
Hier fehlt es einfach an Programmiererfahrung und Wissen. Es gibt an
sich gar kein Problem. Und per default ist das ADC Ergebnis sowieso
schon am LSB ausgerichtet. Die Makros machen den Rest. D.h. man liest
einfach ADCW und hat den 16 Bit Wert. Wer unbedingt den 8 Bit Wert will,
setzt das entsprechende Bit für die Umschaltung der Ausrichtung und kann
dann einfach ADCL lesen.
Das ist alles lächerlich einfach. Wer sich damit so überfordert fühlt
der soll einfach mal einen Gang zurückschalten und nochmal zur
blinkenden LED zurückgehen.
Und vor allem: I2C Slave an den AVRs, nein an allen Controller, würde
ich vermeiden. Vor allem für so unsichere Anfänger. Einfach nicht
machen.
Heiner schrieb:> Was mich bei diesem Programm verunsicht ist die Grösse. Dadurch ist es> für mich sehr unübersichtlich und kompliziert. Programme bei anderen> slaves sind übersichtlicher und damit besser zu verstehen.
Wohl kaum. Das Programm ist (noch nicht einmal ganz) komplex genug, um
das Protokoll abbilden zu können. Es gibt nunmal für einen I2C-slave so
und so viele mögliche Stati und wenn man einen vollwertigen Slave
implementieren will, muss man die halt auch alle unterstützen, also im
Programm behandeln.
Einsparungen können sich nur dann ergeben, wenn man auf Teile der
Möglichkeiten des Protokolls verzichtet, z.B. halt auf die Möglichkeit,
mehr als ein Payload-Byte pro Transaktion zwischen Master und Slave zu
bewegen. Und/oder gar auf die Möglichkeit, überhaupt Payload in eine der
beiden Richtungen zu transferieren. Am allermeisten spart man
allerdings, wenn man überhaupt keinen Transport von Payload vorsieht.
Und du wirst lachen: selbst dafür gibt es denkbare Anwendungen.
Dein Problem ist offensichtlich: du kennst das I2C-Protokoll nicht und
scheinst auch nicht gewillt zu sein, zu lernen, wie es funktioniert.
Dann hat man NATÜRLICH erhebliche Probleme, zu verstehen, wie ein
Programm funktioniert, welches dieses Protokoll implementiert.
Insbesondere dann, wenn es das Protokoll vollständig implementiert, denn
dann erreicht es naturgemäß den größten Umfang.
Könnte es seindas es hier Unterschiede im Protokoll gibt. Man kann ja
Daten von einem Slave lesen, z.B. PCF8574 oder einem Attiny oder halt
einen anderen Prozessor. Beim PCF8574 ist die Sache ja relativ einfach,
ist Hardware mässig alles vorhanden. Die Software kommt in den Master.
Der Master liest die Daten aus dem Slave aus oder schreibt neue rein.
Weiter oben steht ein Hinweis auf das Protokoll. Das habe ich
durchgelesen, ist unterteilt in verschiedene Bereiche, wie Adresse,
Register und Daten.
Bei dem Attiny ist das was anderes für mich. Es gibt fertige
Bibliotheken dazu, da wurde jtronic genannt. Die kenne ich, sind aber
nur für bestimmte Typen brauchbar. Das passt alles nicht zum Attiny841.
Vergessen wir mal den Umfang. Bin dabei zu lesen. Da werde ich nichts
dran änder und alles so lassen wie es ist.
LG Heiner
Heiner schrieb:> Könnte es seindas es hier Unterschiede im Protokoll gibt.
Nein, das I2C-Protokoll ist immer das gleiche. Aber man kann es auf
unterschiedliche Art nutzen. Das ist dann ein übergeordnetes Protokoll.
Es entsteht ein Protokollstack.
Ganz genau dieselbe Soße wie z.B. im Netzwerkbereich. Da gibt es MAC,
darauf setzt z.B. IP auf, darauf wiederum z.B. TCP, darauf wiederum z.B.
HTTP usw. usf.
In deinem Anwendungsfall ist es halt einfach so, dass du das
übergeordnete Protokoll komplett frei definieren kannst, da du sowohl
master als auch slave selber implementierst.
Es gibt keinen verpflichtenden Standard dafür. Das einzige, was es
sicherstellen muss, ist die standardgerechte Nutzung des I2C-Protokolls,
was es als Transport-Protokoll benutzt.
Im µC-Bereich verschmelzen aber diese beiden Layer aus Effizienzgründen
oft, d.h.: man implementiert auf dem I2C-Layer nur das, was man für das
übergeordnete Protokoll tatsächlich benötigt.
> PCF8574
Wenn du einen Slave bauen willst, der mit dem Anwendungsprotokoll dieses
Teils kompatibel ist, dann musst du das halt einfach tun. Nur ist es
wohl nicht sonderlich sinnvoll. 8Bit-digital-IO (konfigurierbar) vs.
16bit-analog-out (nicht konfigurierbar)? Nur ein Idiot würde versuchen,
das kompatibel zu machen. Passt einfach nicht.
Vergiß' die Wichsvorlagen, lerne Denken.
Heiner schrieb:> Da liegt auch das Problem. Eine 16 Bit übertragung mit I2C habe ich noch> nie gemacht. Kennst du ein Beispiel dazu?
So weit waren wir am 12.06....und für mich ist der TO seitdem keinen
Schritt weiter gekommen. Sorry...glaube kaum, dass das noch was wird.
Gruß Rainer
Heiner hat 'nen neuen Thread bezgl I2C aufgemacht - wäre schön gewesen,
er hätte es auch hier kundgetan ...
siehe:
Beitrag "I2C Bus mit dem Attiny 841"
SCNR
Rainer V. schrieb:> So weit waren wir am 12.06....und für mich ist der TO seitdem keinen> Schritt weiter gekommen. Sorry...glaube kaum, dass das noch was wird.
Sehe ich auch so. Es sei denn, irgendwer erbarmt sich und liefert eine
fertige Wichsvorlage.
So, wie's aussieht, ist genau das, was der TO erreichen will. Er selber
ist offensichtlich unfähig, auch nur die Konzepte zu verstehen. Und
lernen mag er wohl auch nicht.
Staube über deinen Pessimismus. Es kommt so richtig negativ rüber.
Zu deiner Info. Das Programm funktioniert ohne Probleme. Kann es als 8
bit oder 10 Bit nutzen. Kann verschiedene Werte angeben. Habe
verschiedne Stufen drin. Habe das Programm für mich vollkommen
auskommentiert mit den Angaben im Datenblatt versehen. Die Einstellungen
die DB angegeben werden sind soweit klar. Teste noch Einstellungen mit
der Verstärkung, Differenzeingang und anderes. Da bin ich aber auch der
Hardware dran. Ansonsten habe ich angefangen die Werte per I2C am Bus zu
übertragen und Anzuzeigen.
Nach Anfang sieht das nicht mehr aus.
c-hater schrieb:> und liefert eine> fertige Wichsvorlage.
Auch das ist schon geschehen!
Veith sprach mehrfach vom "Spencer Arduino Core für Tinys"
https://github.com/SpenceKonde/ATTinyCore
OK, das ist C++ (zu einem großen Teil), aber das winzige Detail fällt
hier wohl nicht ins Gewicht.
Heiner schrieb:> Staube über deinen Pessimismus. Es kommt so richtig negativ rüber.
Entspricht meinem Gefühl beim Schreiben. Das WAR sehr negativ.
> Zu deiner Info. Das Programm funktioniert ohne Probleme.
Wenn das so ist: Warum sind deine beiden Threads noch nicht mit "Lösung
gefunden" und "Lösung sieht soundso aus" beendet?
Das wäre ja die logische Konsequenz, wenn stimmt, was du hier
behauptest...
Hallo Heiner
Wenn Dein Programm bezüglich ADC funktioniert-prima 👍.
Dann markiere DIESEN Thread als “erledigt”, damit keiner mehr meint, er
müsste seinen “Senf” dazugeben - und Du ersparst Dir Beleidigungen wie
von “c-hater” (schon sein Pseudonym ist Hinweis auf seine Einstellung
und seine vulgäre Sprache 🤮)
Egonwalter M. schrieb:> und Du ersparst Dir Beleidigungen wie> von “c-hater” (schon sein Pseudonym ist Hinweis auf seine Einstellung> und seine vulgäre Sprache 🤮)
Bullshit...c-hater drückt oftmals genau das aus, was manchmal einfach
ist! Nämlich unerträgliche Blödheit. Da schlägt man auch schon mal über
die Strenge, besonders wenn sich Blödheit, Unkenntnis und Arroganz
paaren. Geht mir oft auch so, auch wenn ich nicht immer einer Meinung
mit anderen bin... auch wenn es so scheint. An den TO speziell: du
scheinst zu den Leuten zu gehören, die extrem unflexibel und
schwerfällig bei der Horizonterweiterung agieren. Zudem gehörst du auch
offensichtlich zu den Leuten, die sich einfach umdrehen und weggehen,
wenn sie nicht das hören, was sie hören wollen. Das ist auch im
richtigen Leben richtig Sch...man macht keinen neuen Thread auf, nur
weil man im alten zu hören bekommt, dass das Problem mangels
Sachverstand nicht zu lösen sein wird. Aber was rede ich, ist ja alles
nicht neu und wird auch nicht das letzte mal sein...also auf in den
Biergarten :-)
Gruß Rainer
Zum ADC hatte ich gesagt es funktioniert und da der Titel nicht das
aussagt was ich wissen möchte, kommt ein anderer Thread.
Warum müssen alle so agressiv sein. Ich Frage weil ich es nicht weis. Es
kommen Hinweise, mal kleine oder mal grosse dazu. Ich will es nicht
geschenkt haben, aber ein Hinweise oder Infos über was falsches sind
sehr Hilfreich.
Leider bleibt mir der Inhalt der Datenblätter teilweise, auch mit
übersetzung, sehr verschlossen.
Ein paar freundliche Worte oder ein kleiner Anstoss wirken Wunder und
ist alle mal besser als seine Wut über das Wissen der anderen
auszudrücken.
Geh ruhig Biertrinke und beruhige dich. Geniesse das schöne Wetter und
lass uns gemeinsam anstossen.
Ich akzeptiere dein Friede-Freude...aber es ist halt relativ sinnlos!
Auch wenn du es nicht so empfinden wirst, ist hier zuallererst
Sachlichkeit gefordert. Und die wird durch angekündigte Unwissenheit
nicht einfach weggewischt. Hier meldet sich jeder zweite mit dem
Hinweis, dass er erstens überhaupt keine Ahnung hat und zweitens auch
gerade nicht weiß - also quasi ratlos ist - wie er überhaupt mehr Infos
zu seinem "Wißbegehren" (genau das ist es und genau das ist in dieser
Allgemeinheit in einem Fachforum eben fehl am Platz!) bekommen kann. Und
genau diese Haltung provoziert oft nach wenigen Einträgen halt Unwillen.
Wenn ich was zu Lebensfragen im allgemeinen Sinn wissen will, dann frage
ich bei "Wer weiß was" und wenn ich mich berufen fühle, darauf zu
Antworten, dann tu ich das dort. Aber hier ist kein "Wer weiß was" und
das soll auch so bleiben!!
Gruß Rainer
Heiner schrieb:> aber ein Hinweise oder Infos über was falsches sind> sehr Hilfreich.
Hmm ....
Ich würde richtige Hinweise als hilfreicher erachten, als falsche, oder
Hinweise auf falsches.
Heiner schrieb:> Leider bleibt mir der Inhalt der Datenblätter teilweise, auch mit> übersetzung, sehr verschlossen.
Das ist natürlich eine schwierige Situation.
Welche "wir" auch nicht ändern können.
Denn es gilt ja der Grundsatz:
> Selber lesen, macht selber schlau.
Arduino Fanboy D. schrieb:> OK, das ist C++ (zu einem großen Teil), aber das winzige Detail fällt> hier wohl nicht ins Gewicht.
Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".
Stefan ⛄ F. schrieb:> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".
Das ist so ziemlich die einzige vernünftige Entscheidung, die er
getroffen hat. Das muss man ihm zu Gute halten.
C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den
selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen
Umfang überblicken.
Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,
kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen
Umfang. Übrigens auch du nicht und auch der Fanboy nicht.
Wenn es nicht so banal wäre, würde ich schon verzetteln beim TO für
relativ unmöglich halten! Er kann sich gar nicht Verzetteln, weil er
überhaupt nur einen einzigen großen Zettel hat! Ein eindeutiges Zeichen
für vernünftiges Verhalten ist, seine Probleme verstehen zu können!!!
Hat mal irgendwer gesagt (Monty Python war es sicher nicht)
Rainer
c-hater schrieb:> C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den> selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen> Umfang überblicken.>> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.
Da muss ich dir ausnahmsweise mal zustimmen.
Ergänzend: Es ist OK und praktikabel, eine Programmiersprache nur
teilweise zu verwenden. Problematisch wird das erst, wenn man auf
fremden Code stößt, den man deswegen nicht versteht.
Das vollständige Verstehen von beliebigem fremden Code ist allerdings
eher etwas für die alten Hasen mit viel Berufserfahrung. C++ macht es da
einem besonders schwer, dicht gefolgt von Java. Diese voll zu
durchblicken sollte man nicht von Anfängern erwarten, das wäre gemein.
Es hat schon seinen guten Grund, warum immer wieder Programmiersprachen
erdacht werden, die einfach und dennoch ausreichend seien sollen. Wir
werden in 30 Jahren sehen, ob das jemandem mit Erfolg gelungen ist.
Vielversprechende Ansätze sind zu sehen, z.B.: Python und Go. Die sind
aber noch zu jung, um sie final zu bewerten, finde ich.
Assembler glänzt mit Einfachheit und der Gewissheit, dass man damit
wirklich ohne Einschränkung alles machen kann - irgendwie. Doch der
Sprache fehlt es am Mitteln zur übersichtlichen Gestaltung großer
Programme, der Unterstützung von Teamarbeit und statische Code-Analysen
zur Vermeidung von Fehlern.
Mit Assembler programmieren ist, als ob ich dich mit Spitzhacke, Schwert
und Feuerzeug bewaffnet vor einen Berg stelle und dir sage: Baue mir ein
Hotel - du hast 10 Monate Zeit.
Ist das machbar: Zweifellos! Will das jemand so machen?
Unwahrscheinlich, es sei denn derjenige nennt sich c-hater.
c-hater schrieb:> Stefan ⛄ F. schrieb:>>> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.
Nur jemand mit übersteigertem Selbstbewusstsein wird für sich in
Anspruch nehmen (wollen), dass er die selbst gewählte Sprache wirklich
in vollem Umfang beherrscht.
Egonwalter M. schrieb:> Nur jemand mit übersteigertem Selbstbewusstsein wird für sich in> Anspruch nehmen (wollen), dass er die selbst gewählte Sprache wirklich> in vollem Umfang beherrscht.
Oder jemand, der nur die primitivste Sprache akzeptiert, weil er sie
tatsächlich vollständig beherrschen kann.
Meinen Pelikan Füller kann ich vollständig beherrschen, aber ich kann
damit keine Enzyklopädie in angemessener Zeit und Qualität erstellen.
c-hater schrieb:> Stefan ⛄ F. schrieb:>>> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".>> Das ist so ziemlich die einzige vernünftige Entscheidung, die er> getroffen hat. Das muss man ihm zu Gute halten.>> C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den> selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen> Umfang überblicken.>> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.
Da ist er wieder der c-hater, und noch mehr C++ Hasser....
Meine Ansage lautet:
Wenn zur Wahl steht C oder C++ zu lernen, dann ist ganz klar C++ zu
bevorzugen.
Von den Gründen möchte ich hier mal nur 2 aufführen.
- Pointer vs. Referenzen.
Man kann viel mehr Mist mit Pointern bauen, als mit Referenzen.
- Array Index Überschreitungen
Ein Tipp oder logischer Fehler, bei der Indexberechnung in for
Schleifen, führt ganz fix ins Versagen.
Der RangeBasedForLoop vermeidet dieses.
Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle
evtl. eine Überforderung auftreten könnte ist dumm.
Damit ist die Entscheidung des TO dumm, weil ohne Fachkenntnis getroffen
und die Zustimmung des c-hassers sicherlich aus dem gleichen Grund
genauso dumm.
Dem TO, kann ich verzeihen da er es nicht besser weiß.
Aber der C-hater, der könnte es wissen, aber er hat wenn er C++ hört,
sofort so viel Schaum vorm Mund, dass es ihn blind macht.
Arduino Fanboy D. schrieb:> Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle> evtl. eine Überforderung auftreten könnte ist dumm.
Das ist nur dumm, wenn man davon ausgeht, irgendwann mal Fehler zu
machen. Der c-hater weiß aber, dass er so etwas nicht nötig hat, weil er
keine Fehler macht. Zumindest scheint er das zu glauben. Wir kennen ja
seine entsprechenden Vorträge.
Arduino Fanboy D. schrieb:> Meine Ansage lautet:> Wenn zur Wahl steht C oder C++ zu lernen, dann ist ganz klar C++ zu> bevorzugen.> >> Von den Gründen möchte ich hier mal nur 2 aufführen.>> - Pointer vs. Referenzen.> Man kann viel mehr Mist mit Pointern bauen, als mit Referenzen.>> - Array Index Überschreitungen> Ein Tipp oder logischer Fehler, bei der Indexberechnung in for> Schleifen, führt ganz fix ins Versagen.> Der RangeBasedForLoop vermeidet dieses.>> Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle> evtl. eine Überforderung auftreten könnte ist dumm.>> Damit ist die Entscheidung des TO dumm, weil ohne Fachkenntnis getroffen> und die Zustimmung des c-hassers sicherlich aus dem gleichen Grund> genauso dumm.>> Dem TO, kann ich verzeihen da er es nicht besser weiß.> Aber der C-hater, der könnte es wissen, aber er hat wenn er C++ hört,> sofort so viel Schaum vorm Mund, dass es ihn blind macht.
Das ist eine etwas ... arrogante ... Sichtweise, jemandes Entscheidung
als "dumm" zu bezeichnen, nur weil er sich für C und nicht C++
entschieden hat.
Ich kann auch kein C++, verwahre mich aber schärfstens dagegen, dass
irgendjemand meine Entscheidung als "dumm" bezeichnet.
Noch herrscht das Recht auf freie Entscheidung, und die ist zu
respektieren.
Egonwalter M. schrieb:> Ich kann auch kein C++, verwahre mich aber schärfstens dagegen, dass> irgendjemand meine Entscheidung als "dumm" bezeichnet.>> Noch herrscht das Recht auf freie Entscheidung, und die ist zu> respektieren.
Aber doch nicht hier! Schreibe hier mal beiläufig, daß Du z.B. mit
Bascom alle Deine Aufgaben erledigst. Binnen 5 Minuten liegst Du als
blank genagtes Skelett da.
Der Mensch beginnt hier erst mit der Benutzung von C.
Stefan ⛄ F. schrieb:> Mit Assembler programmieren ist, als ob ich dich mit Spitzhacke, Schwert> und Feuerzeug bewaffnet vor einen Berg stelle und dir sage: Baue mir ein> Hotel - du hast 10 Monate Zeit.
Oder man ist so schlau und baut sich damit erstmal bessere Werkzeuge...
Punkt 1:
Egonwalter M. schrieb:> Noch herrscht das Recht auf freie Entscheidung, und die ist zu> respektieren.
Da hast du wahr!
Natürlich darfst du eigene Entscheidungen treffen!
Wie könnte ich dir das verwehren?
Allerdings darf ich auch eine Meinung dazu haben, wie "schlau" diese
Entscheidung ist.
Und jetzt zu Punkt 2:
Natürlich darfst du dich auch so weit mit deinen Entscheidungen
identifiziere, so dass eine Kritik an dieser Entscheidung, also eine
Wertung dieser Entscheidung, dich beleidigt.
Das wäre allerdings schade, wenn du das konsequent so hältst....
Noch mal, ganz klar:
Es liegt nicht in meinem Interesse dich zu beleidigen.
Deine Entscheidung hatte ich eher für falsch, als richtig.
Hallo Arduino Fanboy
Kritik an meinen Entscheidungen sind ok, solange sie konstruktiv ist und
nicht destruktiv; dann ist sie willkommen, da sie einen Denkanstoß
liefert
Und natürlich darf jeder eine Meinung darüber haben, ob meine
Entscheidung klug war oder nicht
Ich denke, mit dieser Sichtweise sind wir beide gleicher Meinung 😉👍
Wie versprochen der ganze Code zur ADC Messung am Attiny 841. Habe die
Variante drin mit 8 Bit und 10 Bit. Die Anzeige erfolgt durch 3 x LED.
Beim drehen des Poti werden die LEDs nach einander eingeschaltet. Beim
zurückdrehen gehen sie wieder aus.
1
#define F_CPU 16000000UL // Angabe der Frequenz, wichtig für die Zeit
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung "single conversion"
14
while(ADCSRA&(1<<ADSC))
15
{// auf Abschluss der Konvertierung warten
16
}
17
}
18
19
uint16_tADC_Read()// ADC Einzelmessung
20
{
21
ADMUXA|=(1<<MUX1);// Register ADMUXA
22
// MUX - Auswahl welcher Eingang - 000010 - ADC2
23
ADCSRA|=(1<<ADSC);// Register ADCSRA
24
// ADSC - Start Konvertierung "single conversion"
25
ADCSRB|=(1<<ADLAR);// bei 8 Bit links
26
while(ADCSRA&(1<<ADSC))
27
{// auf Abschluss der Konvertierung warten
28
}
29
//return ADCW; // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
30
returnADCH;// ADC auslesen und mit 8 Bit zurück mit ADLAR=1
31
}
32
33
intmain(void)
34
{
35
DDRA=0b00101001;// Port A auf Ausgang schalten
36
PORTA=0b00101001;// Port A auf aus
37
uint8_tadcval;// 16 Bit mit ADCW
38
init_ADC();
39
while(1)
40
{
41
adcval=ADC_Read();
42
if(adcval>=58)// bei 8 Bit und 10 Bit
43
{
44
45
PORTA&=~(1<<PINA5);// LED2 ein
46
}
47
else
48
{
49
PORTA|=(1<<PINA5);// aus
50
}
51
if(adcval>128)// bei 8 Bit, bei 10 Bit 600
52
{
53
PORTA&=~(1<<PINA0);// LED3 ein
54
}
55
else
56
{
57
PORTA|=(1<<PINA0);// aus
58
}
59
if(adcval>228)// bei 8 Bit, bei 10 Bit 950
60
{
61
PORTA&=~(1<<PINA3);// LED4 ein
62
}
63
else
64
{
65
PORTA|=(1<<PINA3);// aus
66
}
67
}// while
68
}// main
Die 10 Bit habe ich auskommentieret. Programm läuft ohne Probleme bei
mir.
Wünsche viel Spass damit. Danke an Alle und entschuldigung für die
vielen blöden Fragen.
LG Heiner
Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die
erste Messung verwerfen 🤔
So wird’s jedenfalls vorgeschlagen im Netz (mache es selbst ebenso)
Naja 🤷♂️
Ja das stimmt. In dem DB steckt aber noch mehr. Das ist mein erstes
Programm dazu. Erweiterungen jederzeit möglich. Besonders bei der
eigentlichen Messung und übertragung. Da werde ich noch einiges machen
dazu.
Heiner schrieb:> Ja das stimmt. In dem DB steckt aber noch mehr. Das ist mein> erstes> Programm dazu. Erweiterungen jederzeit möglich. Besonders bei der> eigentlichen Messung und übertragung. Da werde ich noch einiges machen> dazu.
Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert
einlesen und den ersten verwerfen) in Deinem hier vorgestellten
Programm?
Und was hat das DB damit zu tun?
Im DB stehen die Register drin und die Anwendung dazu. Fange immer mit
einem leichten Programm an und nehme dann in dem nächsten Programm
weitere Sachen dazu. Lieber erst ein kleines und leichtes Programm zum
laufen bekommen als gleich mit dem schwersten anfangen.
Egonwalter M. schrieb:> Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert> einlesen und den ersten verwerfen) in Deinem hier vorgestellten> Programm?
Das habe ich in einem Versuch bereits drin. Da in dem ersten Programm
die Auswertung nur durch das ein- und ausschalten von LEDs erfolgt ist
das noch nicht notwendig.
Heiner schrieb:> Egonwalter M. schrieb:>> Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert>> einlesen und den ersten verwerfen) in Deinem hier vorgestellten>> Programm?>> Das habe ich in einem Versuch bereits drin. Da in dem ersten Programm> die Auswertung nur durch das ein- und ausschalten von LEDs erfolgt ist> das noch nicht notwendig.
Wenn Dein Programm hier als Vorlage dienen soll, sollte es auch korrekt
sein (mit mehrfachem Einlesen) damit eventuelle User nicht unliebsame
Überraschungen erleben, wenn sie es denn nehmen und für ihre Zwecke
verwenden.
Du möchtest ja auch nicht ein halb gares Programm nehmen, oder?
Wie auch immer - einmal einlesen ist Murks
Egonwalter M. schrieb:> Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die> erste Messung verwerfen 🤔
Das ist kein Vorschlag (aus dem Netz...) das steht in den diversen
Applikationen! Scheint etwas mit Einschwingverhalten zu tun haben...mit
was auch sonst...aber machen muß man es!!
Gruß Rainer
Heiner schrieb:> DDRA=0b00101001; // Port A auf Ausgang schalten> PORTA=0b00101001; // Port A auf aus> uint8_t adcval; // 16 Bit mit ADCW> if(adcval>=58) // bei 8 Bit und 10 Bit
Die Kommentare stiften mehr Verwirrung als zu helfen.
Arbeite nochmal an der Positionierung der Klammern. Ich empfehle, Tabs
durch 4 Leerzeichen zu ersetzen, das kannst du in deinem Editor bestimmt
einstellen.
> PORTA &=~(1<<PINA5); // LED2 ein
Dies würde ich in eine Funktion verschieben, die LED2_ein() heißt.
Dadurch wird der Code besser lesbar. Und keine Sorge, er wird dadurch
nicht größer oder langsamer.
Egonwalter M. schrieb:> Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die> erste Messung verwerfen
Nur wenn die Quelle zu hochohmig ist und man mehr als 8 Bit nutzen will.
Das macht man nicht für den ADC, sondern um Zeit für die äußere
Schaltung zu gewinnen.
Stefan ⛄ F. schrieb:>> Egonwalter M. schrieb:>> Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die>> erste Messung verwerfen>> Nur wenn die Quelle zu hochohmig ist und man mehr als 8 Bit nutzen will.> Das macht man nicht für den ADC, sondern um Zeit für die äußere> Schaltung zu gewinnen.
Generell sollte man den ersten gelesenen Wert des ADC verwerfen, egal ob
8 Bit oder 10 Bit, es sei denn, man will sich seltsame Effekte
einhandeln - und wer will das?
Hatte es so verstanden:
Da die erste Wandlung nicht korrekt, sollte man sie verwerfen. Bei ( Bit
streiten sich die Leute. Manche sagen: ist auf jeden Fall besser und die
letzten Stellen wackeln nicht so stark. Andere sagen: Bei 8 Bit ist es
nicht unbedingt notwendig.
In diesem Programm ist es relativ egal da das Auslesen mehrfach erfolgt
und die Anzeige mit LEDs erfolgt. Dabei ist keine grosse Genauigkeit
gefordert.
Stefan ⛄ F. schrieb:> Die Kommentare stiften mehr Verwirrung als zu helfen.>> Arbeite nochmal an der Positionierung der Klammern. Ich empfehle, Tabs> durch 4 Leerzeichen zu ersetzen, das kannst du in deinem Editor bestimmt> einstellen.>>> PORTA &=~(1<<PINA5); // LED2 ein
Danke für den Hinweis. Diese Kommentare sind eigentlich nur für mich,
das ich nicht vergesse die richtigen Stellen zu ändern.
Verwende auch Funktionen, doch bei diesem Programm geht es erst mal um
das Verständnis. Werde es aber auf jeden Fall machen.
LG Heiner
Heiner schrieb:> Hatte es so verstanden:> Da die erste Wandlung nicht korrekt, sollte man sie verwerfen. Bei ( Bit> streiten sich die Leute. Manche sagen: ist auf jeden Fall besser und die> letzten Stellen wackeln nicht so stark. Andere sagen: Bei 8 Bit ist es> nicht unbedingt notwendig.> In diesem Programm ist es relativ egal da das Auslesen mehrfach erfolgt> und die Anzeige mit LEDs erfolgt. Dabei ist keine grosse Genauigkeit> gefordert.>
Wenn ich weiß, dass es nicht korrekt ist und es trotzdem ignoriere …
Damit bin ich raus
Außerdem erfolgt das Auslesen nicht MEHRMALS, sondern EINMAL pro
Durchlauf Deiner while-Schleife, Kollege
Heiner schrieb:> Da die erste Wandlung nicht korrekt, sollte man sie verwerfen.
Im Datenblatt steht genau drin, wie viele Takte der ADC zur
Initialisierung benötigt und wann sich das Umschalten des Multiplexers
auswirkt. Wenn man diese Takte abwartet, dann misst der ADC von Anfang
an korrekt.
Warten kann man auf unterschiedliche Art - auch indem man den ADC
Messungen macht und verwirft. Aber das macht man, um Zeit zu schinden,
nicht um irgend etwas einschwingen zu lassen. Der ADC muss sich nicht
einschwingen.
Egonwalter M. schrieb:> Wenn ich weiß, dass es nicht korrekt ist und es trotzdem ignoriere …
Stimmt!
Man kann auch Wartezeiten, ohne Sinn und Verstand, einstreuen und wenn
das dann kritisiert wird, sauer von dannen ziehen.
Stefan ⛄ F. schrieb:> Wo denn?
Sorry, finde natürlich jetzt nichts...aber ich habe mir das für die
AVR's grundsätzlich als Merker weggeschrieben...und das habe ich mir
sicher so nicht ausgedacht. Die anderen Beispiele, die hier genannt
wurden, fallen auch eher in "falsche Beschaltung" und passen daher auch
nicht zu meinen Gedanken.
Gruß Rainer
Rainer V. schrieb:> ..und das habe ich mir> sicher so nicht ausgedacht.
Aber offensichtlich nicht verstanden!
Und darum falsch gemerkt und den Irrtum weiter verbreitet.
Die Umschaltung der Referenz, z.B. von Vcc zu Intern, benötigt Zeit.
Je größer der Kondensator an ARef, desto länger.
Auch ein (zu) hoher ADC Takt, klarer, zu kurze S&H Umladezeit, zu hohe
Eingangsimpedanz können eine zweite Messung nötig machen.
Aber das ist nicht in Stein gemeißelt und hier sehe ich auch keine
Anzeichen dafür.
Auch Multiplexerumschaltungen im FreeRunningMode erfordern das Verwerfen
von Werten.
Aber das ist wieder ein anderes Thema....
Du siehst....
Verallgemeinern gilt nicht.
Arduino Fanboy D. schrieb:> Die Umschaltung der Referenz, z.B. von Vcc zu Intern, benötigt Zeit.> Je größer der Kondensator an ARef, desto länger.
Richtig.
> Auch ein (zu) hoher ADC Takt, klarer, zu kurze S&H Umladezeit, zu hohe> Eingangsimpedanz können eine zweite Messung nötig machen.
Ebenfalls richtig.
> Auch Multiplexerumschaltungen im FreeRunningMode erfordern das Verwerfen> von Werten.
Das ist falsch. Das ist höchstens dann zutreffend, wenn man das
Zeitverhalten seines Codes nicht im Griff hat.
Das Umschalten des Multiplexers wirkt sich auf die nächste Messung aus,
nicht auf die gerade laufende Messung. Das ist des Pudels Kern, so steht
das auch im Datenblatt.
Für die Art, wie der TO hier den ADC nutzt, ist dieses Detail
irrelevant.
Stefan ⛄ F. schrieb:> Das Umschalten des Multiplexers wirkt sich auf die nächste Messung aus,> nicht auf die gerade laufende Messung. Das ist des Pudels Kern, so steht> das auch im Datenblatt.
So ist es, aber trotzdem nur die halbe Wahrheit.
Im FreeRunning-Mode gibt es nämlich die Möglichkeit für Quirks, wenn man
den Multiplexer in der ADC-ISR umschaltet. Da kann es nämlich passieren,
dass die neue Multiplexer-Konfiguration noch für den gerade laufenden
(durch FreeRun automatisch gestarteten) ADC-Zyklus wirksam wird, nämlich
dann, wenn die ISR wenig Overhead hat und auch gerade nicht durch eine
konkurrierende ISR verzögert wurde.
OK: Bei in C geschriebenen ISRs ist es relativ unwahrscheinlich, dass
das passiert, aber eben nicht unmöglich. In Asm hingegen ist das ein
absolut relevantes Thema, welches man natürlich entsprechend
berücksichtigen muss.
Und übrigens, ohne Quirks: Die Multiplexer-Konfiguration, wird im
nächsten Zyklus gültig, d.h.: das daraus resultierende Ergebnis ist erst
das ÜBERNÄCHSTE.
Wie auch immer, seine AD-Wandlungen im Auge zu behalten, ist nie
verkehrt! Und in den seltensten Fällen wird man genau auf diese, erste
Wandlung angewiesen sein...also...
Rainer V. schrieb:> Wie auch immer, seine AD-Wandlungen im Auge zu behalten, ist nie> verkehrt! Und in den seltensten Fällen wird man genau auf diese, erste> Wandlung angewiesen sein...also...
😉👍
Rainer V. schrieb:> ...Egonwalter M. schrieb:> ...
Alles klar...
Bestenfalls 30% verstanden.
Im Grundsatz widerlegt worden, aber miteinander, wie bei einem Sieg
abklatschen.
Wow...
Soviel Chuzpe hätte ich nicht!
Meinen Glückwunsch.
c-hater schrieb:> Im FreeRunning-Mode gibt es nämlich die Möglichkeit für Quirks, wenn man> den Multiplexer in der ADC-ISR umschaltet.
Ja, der FreeRunning-Mode ist häßlich. Daher benutze ich ihn nur, wenn
nur ein Eingang eingelesen werden muß.
Bei Prescaler 128 muß man sonst 128 CPU-Zyklen warten, bis der MUX
umgeschaltet werden darf.
Peter D. schrieb:> Daher benutze ich ihn nur, wenn> nur ein Eingang eingelesen werden muß.
Naja...
Auch eine Möglichkeit des Ausblendens.
Peter D. schrieb:> Bei Prescaler 128 muß man sonst 128 CPU-Zyklen warten, bis der MUX> umgeschaltet werden darf.
Die Alternative ist, wenn man nicht weiß, in welchen ADC Takt man ihn
erwischt hat, ist das verwerfen des ersten Ergebnisses nach der
Umschaltung. Und wenn auch andere ISR im Spiel sind KANN man das nicht
wissen.
Wozu der c-hater dann sagt:
c-hater schrieb:> Das ist falsch.
Arduino Fanboy D. schrieb:> Die Alternative ist, wenn man nicht weiß, in welchen ADC Takt man ihn> erwischt hat, ist das verwerfen des ersten Ergebnisses nach der> Umschaltung.
Das kostet ja noch viel mehr Zeit.
Warum nicht einfach in der ISR den MUX umschalten und dann die neue
Messung starten?
Wie gesagt, der FreeRunning-Mode ist nicht gut durchdacht.
Helmut L. schrieb:> Peter D. schrieb:>> Wie gesagt, der FreeRunning-Mode ist nicht gut durchdacht.>> Das wird wohl beim Design des ADC sich einfach so ergeben haben.
Das mußte eben schnellgehen. Heißt ja: Free running und nicht
"Langsam einlesing"
Arduino Fanboy D. schrieb:> Die Alternative ist, wenn man nicht weiß, in welchen ADC Takt man ihn> erwischt hat, ist das verwerfen des ersten Ergebnisses nach der> Umschaltung. Und wenn auch andere ISR im Spiel sind KANN man das nicht> wissen.
Doch, natürlich kann man das wissen. Wenn man halt das Laufzeitverhalten
seiner Anwendung vollständig im Griff hat. Dann kann man für JEDE
einzelne ISR EXAKT vorhersehen, wie hoch die Latenz mindestens und
höchstens ausfallen wird.
Und dann hat man noch die Wahl zwischen zwei Varianten. Wenn es nur
wenige konkurrierende ISRs gibt und/oder man die Zeit ihrer exklusiven
Ausführung kurz genug halten kann, dann kann man den ADC regulär und
zuverlässig im "Quirks-Bereich" nutzen. Bis jetzt habe ich das noch in
jeder Anwendung geschafft, in der sich FreeRunning anbot.
Und falls das mal nicht möglich sein sollte, hat man immer noch die
Möglichkeit, die ADC-ISR so zu gestalten, dass die Wartezeit für den
Fall der Minimal-Latenz keine verlorene Zeit ist, sondern sinnvoll
genutzt werden kann.
> Wozu der c-hater dann sagt:> c-hater schrieb:>> Das ist falsch.
Ist es halt auch wirklich. In meiner Welt der berechenbaren
Laufzeiten...
c-hater schrieb:> Wenn man halt das Laufzeitverhalten> seiner Anwendung vollständig im Griff hat.
Ah ja. Ein NOP hinzugefügt oder weggenommen und das Kartenhaus bricht
zusammen...
> Dann kann man für JEDE> einzelne ISR EXAKT vorhersehen, wie hoch die Latenz mindestens und> höchstens ausfallen wird.
Schön. Und wenn Du eine Kleinigkeit am Code änderst, fängt die
Rechnerei, ob alles noch passt von vorne an.
Kann man machen.
Oder man programmiert robust und defensiv...
Bernd schrieb:> Ah ja. Ein NOP hinzugefügt oder weggenommen und das Kartenhaus bricht> zusammen...
Nun, in gut geplante Kartenhauser braucht man halt nichts mehr
hinzufügen oder wegnehmen. Die stehen ewig.
> Oder man programmiert robust und defensiv...
Das Vorgehen für diese Variante hatte ich doch ebenfalls beschrieben. Da
geht es dann nur noch darum, in der ADC-ISR genug Rechenzeit sinnvoll zu
benutzen, statt sinnlos zu verwarten. Das ist dann endgültig eine
wirklich einfache Aufgabe, der vielleicht sogar Leute wie du gewachsen
sein könnten...
Hallo
Habe zu der ADC Messung am Attiny 841 die Mittelwertbildund dazu
genommen:
1
uint16_tADC_lesen1()// ADC Einzelmessung
2
{
3
ADMUXA|=(1<<MUX1);// Register ADMUXA
4
// MUX - Auswahl welcher Eingang - 000010 - ADC2
5
ADCSRA|=(1<<ADSC);// Register ADCSRA
6
// ADSC - Start Konvertierung "single conversion"
7
ADCSRB|=(1<<ADLAR);// bei 8 Bit links
8
while(ADCSRA&(1<<ADSC))
9
{// auf Abschluss der Konvertierung warten
10
}
11
//return ADCW; // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
12
returnADCH;// ADC auslesen und mit 8 Bit zurück mit ADLAR=1
13
}
14
15
uint16_tADC_lesen_avg(uint8_tanzahlmessung)
16
{
17
uint16_tsummemessung=0;
18
for(uint8_ti=0;i<anzahlmessung;++i)
19
{
20
summemessung+=ADC_lesen1();
21
}
22
return(summemessung/anzahlmessung);// Durchschnitt errechnen und zurück
23
}
Den Aufruf und übertragung zum Master über den I2C Bus erfolgt damit:
1
intmain(void)
2
{
3
init_I2C();
4
init_ADC();
5
while(1)
6
{
7
//wert1= ADC_lesen1();
8
wert1=ADC_lesen_avg(5);
9
if(command!=0x00)
10
{
11
switch(command)
12
{
13
case0x01:
14
// Test Daten
15
tx_buf[0]=wert1;
16
tx_buf[1]=2;
17
tx_buf[2]=3;
18
tx_buf[3]=14;
19
tx_buf_index=0;
20
break;
21
}
22
command=0x00;
23
}
24
}
25
}
Bei einem Aufruf des Mittelwertes mit wert1= ADC_lesen_avg(5); werden
für alle 4 tex_buf unterschiedliche Werte angezeigt. Bei jeder änderung
des wert1 ändert sich auch tx_buf 1,2,3. Wenn ich nur mit wert1=
ADC_lesen1(); den ADC Wert übertrage stimmen die Werte. Leider ist mir
nicht klar warum das so ist.
LG Heiner
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung "single conversion"
79
while(ADCSRA&(1<<ADSC))
80
{// auf Abschluss der Konvertierung warten
81
}
82
}
83
84
uint16_tADC_lesen1()// ADC Einzelmessung
85
{
86
ADMUXA|=(1<<MUX1);// Register ADMUXA
87
// MUX - Auswahl welcher Eingang - 000010 - ADC2
88
ADCSRA|=(1<<ADSC);// Register ADCSRA
89
// ADSC - Start Konvertierung "single conversion"
90
ADCSRB|=(1<<ADLAR);// bei 8 Bit links
91
while(ADCSRA&(1<<ADSC))
92
{// auf Abschluss der Konvertierung warten
93
}
94
//return ADCW; // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
95
returnADCH;// ADC auslesen und mit 8 Bit zurück mit ADLAR=1
96
}
97
98
uint16_tADC_lesen_avg(uint8_tanzahlmessung)
99
{
100
uint16_tsummemessung=0;
101
for(uint8_ti=0;i<anzahlmessung;++i)
102
{
103
summemessung+=ADC_lesen1();
104
}
105
return(summemessung/anzahlmessung);// Durchschnitt errechnen und zurück
106
}
107
108
intmain(void)
109
{
110
init_I2C();
111
init_ADC();
112
while(1)
113
{
114
//wert1= ADC_lesen1();
115
wert1=ADC_lesen_avg(5);
116
if(command!=0x00)
117
{
118
switch(command)
119
{
120
case0x01:
121
// Test Daten
122
tx_buf[0]=wert1;
123
tx_buf[1]=2;
124
tx_buf[2]=3;
125
tx_buf[3]=14;
126
tx_buf_index=0;
127
break;
128
}
129
command=0x00;
130
}
131
}
132
}
Auf die tx_buf 1,2,3 wird nur an dieser Stelle zugegriffen. Wenn ich das
gleiche mit wert1=ADC_lesen1(); mache ändern sich die Werte nicht.
Habe noch die ganzen Kommentare drin.
Ich sehe da auf Anhieb keinen Fehler.
Eine Frage um das Problem einzukreisen:
Bist du sicher dass sich tx_buf[1] bis [3] verändern oder schließt du
das aus den Daten, die dein Mikrocontroller auf dem I²C Bus sendet?
Und noch eine: Wird der Stack-Pointer richtig initialisiert?
Kontrolliere mal dessen Wert.
ist mit
volatile uint8_t tx_buf[4];
angegeben, da ich nur 8 Bit per Bus übertrage.
Mir ist noch was anderes aufgefallen. Wenn ich schreibe
1
wert1=ADC_lesen1();
2
//wert1= ADC_lesen_avg(5);
3
if(command!=0x00)
4
{
5
switch(command)
6
{
7
case0x01:
8
// Test Daten
9
tx_buf[0]=12;
10
tx_buf[1]=2;
11
tx_buf[2]=3;
12
tx_buf[3]=14;
13
tx_buf_index=0;
14
break;
15
}
16
command=0x00;
17
}
werden genau diese 4 Werte übertragen.
Schreibe ich aber
{c]
{
//wert1= ADC_lesen1();
wert1= ADC_lesen_avg(5);
if(command != 0x00)
{
switch(command)
{
case 0x01:
// Test Daten
tx_buf[0] = 12;
tx_buf[1] = 2;
tx_buf[2] = 3;
tx_buf[3] = 14;
tx_buf_index = 0;
break;
}
command = 0x00;
}
}
[/c]
bekomme ich bei jeder Abfrage unterschiedliche Werte.
Wieso? Die Werte für tx_buf[..] sind doch immer gleich.
Ich glaube ich hab es:
Wenn der Master Daten anfordert, antwortest die ISR immer sofort mit den
4 Bytes des Buffers, auf die tx_buf_index zeigt.
Während dessen läuft vielleicht gerade deine langsame 5-fache ADC
Messung. Dann merkst du dass ein Kommando empfangen wurde und dann setzt
du tx_buf_index index einfach auf 0 ohne zu berücksichtigen, in welchem
Status sich die I²C Übertragung gerade befindet.
Es könnte sein, dass tx_buf_index gerade den Wert 1 oder 2 oder 3 hat
und du setzt es dann einfach "unerlaubt" auf 0 zurück. Als nächstest
sendet die ISR du dann erneut tx_buf[0] an den Master anstatt das
richtige Byte das eigentlich an der Reihe gewesen wäre.
Das ist eine klassische Race Condition, Willkommen in der Welt der
Nebenläufigkeit. Dir fehlt eine Synchronisation der beiden parallelen
Vorgänge:
a) ADC auslesen (in main)
b) Messwerte senden (in der ISR)
Diese beiden Threads dürfen nur abwechselnd auf den Buffer zugreifen.
Dir fehlt eine entsprechende Ablaufsteuerung. Wenn du diese einführst
dann brauchst du wohl auch Clock-Stretching, denn du musst dem Master
irgendwie mitteilen, dass er bitte warten soll weil du gerade die von
ihm angeforderte Messung durchführst und eben deswegen jetzt nicht
sofort antworten kannst.
Alternative: Du machst drei Kommandos:
1) Messung starten. Es gibt keine Antwort (außer natürlich das ACK).
2) Abfrage ob die Messung fertig ist. Antwort ist 0 oder 1.
3) Messergebnis abfragen. Antwort sind die 4 Bytes.
Dann muss der Master den Status wiederholt pollen und die Daten erst
dann abholen, wenn dein Slave dazu bereit ist.
Muss ganz ehrlich sagen, habe deine Antwort erst mehrmals lesen müssen
um es vielleicht zu verstehen. Es klingt recht plausibel. Was ich daran
nicht verstehe, ohne Mittewertberechnung bzw. Aufruf geht es mit geht es
nicht. Kann alles damit zusammenhängen.
Das andere Problem für mich ist die Lösung. Habe null Peilung wie ich
das machen kann, da für mich so ein Problem noch nie aufgetreten ist.
Die ADC Messung (einfach) habe ich ja in den Griff bekommen, tja der
Rest ist noch unbekannt.
Stefan ⛄ F. schrieb:> a) ADC auslesen (in main)> b) Messwerte senden (in der ISR)
Wenn ich deine Worte richtig verstanden habe, muss das ADC auslesen
fertig sein und dann darf erst Messwerte senden erfolgen. Damit sind
korrekte Messwerte gegeben.
Dazu brauch ich doch die Info das das ADC auslesen fertig ist und dann
über Freigabe 0 oder 1 die Werte zum Auslesen freigebe.
Sehe ich das richtig?
Heiner schrieb:> Was ich daran> nicht verstehe, ohne Mittewertberechnung bzw. Aufruf geht es
Weil dann die Messung immer schneller als die I²C Übertragung ist. Das
Messergebnis steht immer rechtzeitig bereit.
> ...> Sehe ich das richtig?
Ja
Das ist wirklich kein einfaches Thema. Aber da musst du durch - es sei
denn du nutzt Clock-Stretching und machst die Messung innerhalb der ISR.
Dann hast du nämlich nur einen Thread, der auf die Messergebnisse
zugreift. Zugriffskonflikte sind dann unmöglich.
Stefan ⛄ F. schrieb:> Das ist wirklich kein einfaches Thema. Aber da musst du durch - es sei> denn du nutzt Clock-Stretching und machst die Messung innerhalb der ISR.
Messung innerhalb der ISR ??? Dabei wird init_ADC gemacht wie bisher.
Dann muss man innerhalb der ISR, Bereich Daten einlesen, auf die ADC
Mittelwertbildung zugreifen. Die Mittelwertbildung greift dann ja wieder
auf die eigentlich ADC Messung zu.
Habe ich das richtig verstanden?
Stefan ⛄ F. schrieb:> Das ist wirklich kein einfaches Thema.
Da gebe ich dir Recht. Konnte auch sehr wenig im Netz dazu finden was
ich verstehe. Gerade beim Attiny 841 gibt es scheinbar garnichts dazu.
Sicher sagen einige, ist kein Problem. Für mich leider schon. Vielleicht
gibt es noch ein Paar Tips dazu. Vielleicht....
Heiner schrieb:> Messung innerhalb der ISR ???> Habe ich das richtig verstanden?
Nein, ich meinte dass dein Mikrocontroller nach Empfang des Kommandos
die 5 Messungen innerhalb der ISR macht, den Mittelwert bildet und erst
dann das Kommando mit ACK bestätigt. Danach sendest du die Antwort an
den Master.
Die unschöne Konsequenz aus dieser simplen Umsetzung ist aber, dass das
ACK erheblich verzöger wird, nämlich so lange wie die 5 ADC Messungen
dauern. Um dies zu ermöglichen, musst du das Clock-Stretching Feature
von I²C benutzen (welches der Raspberry Pi übrigens nicht unterstützt).
Die zweite unschöne Konsequenz ist, dass der Mikrocontroller während
dieser Zeit vermutlich nicht anderes mehr tun kann, weil die ISR den
Ablauf der main() eben so lange blockiert. Du kannst höchsten noch
andere höher priorisierte ISR gleichzeitig ausführen, falls der µC das
überhaupt unterstützt (die klassischen AVR tun es nicht).
Heiner schrieb:> Gerade beim Attiny 841 gibt es scheinbar garnichts dazu.
Für den Anfang verwendest du besser einen Mikrocontroller, der unter
Hobbyelektronikern beliebt und schon lange etabliert ist, denn dann
findest du dazu die meisten leicht verständlichen Anleitungen. Vor ein
paar Jahren war das noch der Atmega8, inzwischen wurde er (dank Arduino)
durch den ATmega328 abgelöst. Bestelle dir einfach mal ein 5er Pack
Arduino Nano Module, die kannst du immer mal gebrauchen. Zum
Programmieren musst du ja nicht die Arduino IDE benutzen, es geht um die
praktische Hardware.
Habe mir das Datenblatt vorgenommem. Unter 20.3.7 steht was dazu. Leider
für mich sehr unklar.
Habe im Netz dazu gesucht. Auch leider alles relativ theoretisch
gehalten.
Habe aber eine Frage dazu.
Was passiert wenn ich verschiedene ADC abfrage ohne Mittelwertbildung.
Da ja 4 Werte übertragen kann, kann ich 2x ADC mit jewels 8 Bit nehmen.
Tritt dann das Problem auch auf? Sorry, meine Hardware ist noch nicht so
weit um zu testen.
Stefan ⛄ F. schrieb:> 2) Abfrage ob die Messung fertig ist. Antwort ist 0 oder 1.
Kann man einfach die übertragung der Werte stoppen bevor die ADC Messung
und Mittelwertbildung fertig ist?
Heiner schrieb:> Tritt dann das Problem auch auf?
Ja, denn es ist ein Timing Problem. DU kannst froh sein, dass du
wenigstens eine ADC Abfrage auf diese Art machen kannst. Takte den mal
langsamer, dann geht nicht einmal das mehr.
Heiner schrieb:> Kann man einfach die übertragung der Werte stoppen bevor die ADC Messung> und Mittelwertbildung fertig ist?
Dazu dient das von mir genannte Clock Stretching. Lies doch mal, was
dieser Begriff beim I²C Bus bedeutet. Ich hoffe du hast die
Spezifikation vorliegen:
https://www.nxp.com/docs/en/user-guide/UM10204.pdf Das ist für dich
Pflichtlektüre!
Stefan ⛄ F. schrieb:> Heiner schrieb:>> Gerade beim Attiny 841 gibt es scheinbar garnichts dazu.
Der ATtiny841 ist eine Spätgeburt. D.h. viele haben schon mit früheren
AVRs angefangen und benutzen diese weiterhin.
Auch benutzen viele Bastler gerne MCs, die noch als DIP verfügbar sind.
Die kann man schnell mal auf ein Steckbrett friemeln.
Peter D. schrieb:> Der ATtiny841 ist eine Spätgeburt. D.h. viele haben schon mit früheren> AVRs angefangen und benutzen diese weiterhin.> Auch benutzen viele Bastler gerne MCs, die noch als DIP verfügbar sind.> Die kann man schnell mal auf ein Steckbrett friemeln.
Aber auch da kommt man nicht umhin, sich mit Clockstretching
auseinanderzusetzen 😉 (dürfte da aber einfacher zu haendeln sein)
Genug der Vorrede. Habt mir genug Angst gemacht. Es wird Zeit etwas zu
machen. Habe angefangen das von NXP zu lesen. Habe mir schon einiges im
Netz gesucht. Im Netz gibt es aber das Problem, das viele Sachen auf den
Atmega 8 oder die älteren Attiny laufen. Da ja der Atiiny 841 etwas
anders ist liegt dabei das Problem.
Heiner schrieb:> Im Netz gibt es aber das Problem, das viele Sachen auf den> Atmega 8 oder die älteren Attiny laufen. Da ja der Atiiny 841 etwas> anders ist liegt dabei das Problem.
Das Problem ist, dass du ohne Code aus dem Netz anscheinend gar nichts
machen kannst. Mir ist es doch völlig egal ob es Code für diesen oder
jenen Controller nicht gibt. Ich nehme das Datenblatt und programmiere
für MEINEN Controller. Lerne programmieren. Dieses Defizit springt hier
aus jedem deiner Posts geradezu heraus.
Cyblord -. schrieb:> Das Problem ist, dass du ohne Code aus dem Netz anscheinend gar nichts> machen kannst. Mir ist es doch völlig egal ob es Code für diesen oder> jenen Controller nicht gibt. Ich nehme das Datenblatt und programmiere> für MEINEN Controller. Lerne programmieren. Dieses Defizit springt hier> aus jedem deiner Posts geradezu heraus.
Kann man nichts gegen sagen, allerdings hat der TO wohl das Problem,
dass er das Datenblatt (da in Englisch) nicht ohne Übersetzer lesen (und
umsetzen) kann ... und die Übersetzung ist wohl manchmal nicht so
zielführend...
Außerdem möchte der TO wohl ganz gerne den Code "mundgerecht" ;-)
Egonwalter M. schrieb:> Kann man nichts gegen sagen, allerdings hat der TO wohl das Problem,> dass er das Datenblatt (da in Englisch) nicht ohne Übersetzer lesen (und> umsetzen) kann ... und die Übersetzung ist wohl manchmal nicht so> zielführend...
Ein englisches Datenblatt ist grundlegendes Handwerkszeug im Umgang mit
Digitaltechnik. Da kommt man nicht drum rum. Aber technisches Englisch
ist nicht besonders schwierig.
Ein Problem, was noch auffällt: deine 'ADC_lesen_avg()' returniert ein
uint16_t, aber du schickst das ohne Typecast auf ein uint8_t Array. Das
kann klappen, muss aber nicht.
Matthias S. schrieb:> Ein Problem, was noch auffällt: deine 'ADC_lesen_avg()' returniert ein> uint16_t, aber du schickst das ohne Typecast auf ein uint8_t Array. Das> kann klappen, muss aber nicht.
Das habe ich auch gesehen und bereits korregiert.
Egonwalter M. schrieb:> Außerdem möchte der TO wohl ganz gerne den Code "mundgerecht" ;-)
Möchte den Code nicht "mundgerecht" haben. Man kann das Datenblat
auswendig lernen oder die englische Version als Grundlage nehmen, alles
geht. Es gibt verschiedene Wege etwas zu machen. Ein Lehrling lernt aus
Erfahrung und Erkenntnis was zu machen ist. Wenn ich ein Stück Code
nehme und es zerlege und schaue wie es andere machen, lerne ich daran
mehr als ein DB auswendig zu lernen. Für mich ist es zielführend wenn
man nicht ständig auf ein Lehrbuch verwiesen wird und ständig als "Nicht
Wissender" in der Edelforn genannt wird. Ein Anfänger hat den Vorteil
oder auch Nachteil nicht alles zu wissen. Hat aber die Aufgabe den
Lehrer zu fragen. Und der Lehrer kann es als Hinweis für eine LKösung
machen.
Heiner schrieb:> Möchte den Code nicht "mundgerecht" haben. Man kann das Datenblat> auswendig lernen oder die englische Version als Grundlage nehmen, alles> geht. Es gibt verschiedene Wege etwas zu machen.
Kranke und nicht zielführende Einstellung. Man muss das Datenblatt nicht
auswendig lernen, man hat es ja jederzeit zur Hand.
Man muss es nur verstehen und danach programmieren können. Daran
scheitert es. Alles andere ist nur Rechtfertigung für diesen einfachen
Umstand.
Und NATÜRLICH ist das englische Datenblatt die Grundlage. Nichts
anderes.
Da das DB die Grundlage ist, habe ich darin zwei Sachen gefunden, TWDIF
und TWASIF. Da gibs den Hinweis im Register TWSSRA das SCL so lange auf
GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist
leider bisher das einzige was gefunden habe.
Heiner schrieb:> Da das DB die Grundlage ist, habe ich darin zwei Sachen gefunden, TWDIF> und TWASIF. Da gibs den Hinweis im Register TWSSRA das SCL so lange auf> GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist> leider bisher das einzige was gefunden habe.
Das Datenblatt ist ja auch nicht dazu da dir den I2C Bus zu erklären,
sondern wie du mit diesem Controller am Bus teilnimmst. Um den I2C Bus
mit all seinen Spielarten zu verstehen gibt es andere Dokumente. Sobald
du dann weißt WAS du eigentlich auf dem Bus tun willst, kann dir das
Datenblatt sagen WIE du den Controller dazu bringst das zu tun.
Heiner schrieb:> Da ja der Atiiny 841 etwas> anders ist liegt dabei das Problem.
Ich bin absolut sicher, dass ein älterer AVR bei dem aktuellen Problem
technisch gesehen kein bisschen einfacher ist.
Cyblord -. schrieb:> Das Datenblatt ist ja auch nicht dazu da dir den I2C Bus zu erklären
So ist es. Das Datenblatt setzt voraus, dass du mit der Funktionsweise
des I²C vertraut bist, bevor du eigene Programme dafür schreibst. Das
gilt für alle Schnittstellen die irgendein Protokoll fahren.
In der Bedienungsanleitung deines Autos werden auch nicht die
Verkehrsregeln erklärt, z.B. wann man links blinken soll und wie man
korrekt überholt. Die Anleitung erklärt nur, worauf du dazu drücken
musst.
Ich persönlich habe den I²C Bus lange Zeit mit der sogenannten
"bit-banging" Methode genutzt. Das bedeutet: Ich habe dafür zwei simple
I/O generische Pins verwendet, anstatt die spezielle I²C Hardware.
Angefangen hatte ich mit dem Parallel-Port meines PC, von dem ich
einfach die Leitungen D0 und D1 zweckentfremdete*. Auf der Gegenseite
habe ich fertige Slaves benutzt bei denen ich sicher sein konnte, dass
sie sich an die Regeln halten.
*) Ich hatte eine I/O Karte mit bidirektionalem parallel-Port, nicht den
einfachen unidirektionalen Standard von IBM. Mit DOS Programmen konnte
man darauf damals noch "einfach so" zugreifen, genau wie der
Mikrocontroller auf seine I/O Pins zugreift.
Wenn ich als Anfänger Master und Slave gleichzeitig programmiere, habe
ich zwei Baustellen gleichzeitig. So will ich nicht lernen, ist mir viel
zu unsicher. Wer so arbeitet kann auch einfach behaupten, dass der
Himmel grün sei. Solange sich alle Komponenten darüber einig sind (und
das sind sie, weil ich sie gemacht habe) fällt der Fehler nicht auf. Das
ist nicht gut.
Heiner schrieb:> Da gibs den Hinweis im Register TWSSRA das SCL so lange auf> GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist> leider bisher das einzige was gefunden habe.
Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,
zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit
blockiert man den Bus, andere Übertragungen müssen dann ebenfalls
warten.
Habe die letzten Tage damit zugebracht im Netz Beschreibungen und
Angaben zu Clock Stretching zu suchen und zu lesen. Dazu zählen auch die
Angaben von Atmel und Nachfolger. Leider ist sehr viel Rede von den
allgemeinen Angaben, wie z.B. kurze Beschreibungen und allgemeine
technische Angaben.
Stefan ⛄ F. schrieb:> Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,> zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit> blockiert man den Bus, andere Übertragungen müssen dann ebenfalls> warten.
Diese Aussage ist schon fast das wichtigste was drin steht.
Warum gibt es dazu so gut wie keine Angaben? Weder in den Datenblättern
noch in den Schriften der Hersteller steht was konkretes. Alle möglichen
Leute beziehen sich darauf oder suchen was dazu, doch keiner nennt was
konkretes.
Gibt es dieses Problem nur wenn man einen Attiny oder anderes kleines
als Slave nutzt?
Heiner schrieb:> Warum gibt es dazu so gut wie keine Angaben?
Weil Clock-Stretching einfach fester Bestandteil der I²C-Spezifikation
ist. Alles, was was taugt und I²C-kompatibel sein will, hat es zu
unterstützen.
Das betrifft natürlich nur Master. Ein Client, der kein Clockstretching
benötigt, um seine Aufgabe erledigen zu können, braucht über
Clock-Stretching auch nichts zu wissen.
In deinem konkreten Fall (TWI-Client der Tiny 441/841) weiß allerdings
die Client-Hardware bereits alles nötige über Clock-Stretching und
wendet das ganz automatisch an, wenn der Programmierer ihr keine andere
Wahl läßt. Das ist auch überhaupt kein Problem, jeder standardgerecht
Master hat damit lt. Standard problemlos klarzukommen.
D.h.: normalerweise ist bereits der Drops gelutscht, egal wie Scheiße du
als Programmierer bist. Nur dann, wenn der Master standardwidrig unfähig
ist, mit Clock-Stretching umzugehen, dann ist es nicht mehr egal. Dann
ist dein Job, dafür zu sorgen, dass der Client kein Clock-Stretching
mehr anwenden muss. D.h. im Kern, dass dein Code schlicht in jeder
denkbaren Situation schnell genug sinnvoll auf den Interrupt der
TWI-Slave-Hardware reagieren muss.
> Leute beziehen sich darauf oder suchen was dazu, doch keiner nennt was> konkretes.
Diese Leute haben wohl alle den Standard gelesen und verstanden. Das ist
alles.
> Gibt es dieses Problem nur wenn man einen Attiny oder anderes kleines> als Slave nutzt?
Nein. Das Problem gibt es vielmehr nur, wenn man nicht
Clock-Stretching-fähige (d.h.: nicht standardgerechte) Master benutzt.
Heiner schrieb:> Warum gibt es dazu so gut wie keine Angaben?
na weil das doch quasi trivial ist! Stefan und andere haben das doch
schon beschrieben. Man muß sich eher Gedanken machen, wie man die
Blockade in seinem Programm sinnvoll bearbeitet. Ich weiß nicht, ob das
bei den diversen Programmpaketen drin ist, aber ich (als ASM) würde da
auf jeden Fall sowas wie ein "timeout" einbauen, damit das System nicht
auf ewig festhängt. Am Besten wäre doch für den TO einfach mal Spielen
:-)
Gruß Rainer
Stefan ⛄ F. schrieb:> Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,> zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit> blockiert man den Bus, andere Übertragungen müssen dann ebenfalls> warten.
...was bitte verstehst du daran nicht???
Rainer V. schrieb:> Stefan ⛄ F. schrieb:>> Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,>> zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit>> blockiert man den Bus, andere Übertragungen müssen dann ebenfalls>> warten.>> ...was bitte verstehst du daran nicht???
Das verstehe ich sehr wohl und bin daran was zu machen.
Darüber steht aber auch die Aussage:
c-hater schrieb:> Nein. Das Problem gibt es vielmehr nur, wenn man nicht> Clock-Stretching-fähige (d.h.: nicht standardgerechte) Master benutzt.
Wie gesagt kannst du einfach innerhalb der ISR deine 5 ADC abfragen
machen, bevor du damit beginnst, die Antwort (das ACK) zurück zu
liefern.
Zur Erinnerung: Das ist die Zeile wo du das ACK sendest:
> TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
Mehr ist da gar nicht zu tun, der Rest (das Clock Stretching) ergibt
sich dann von ganz alleine.
In diesem Bereich erfolgt das lesen der ADC Wert im Slave:
1
if(TWSSRA&(1<<TWDIR))// Master fordert Daten vom Slave an
2
{
3
if(tx_buf_index>=sizeof(tx_buf))
4
{
5
tx_buf_index=0;
6
}
7
TWSD=tx_buf[tx_buf_index];// Daten in Sendepuffer
8
tx_buf_index++;
9
TWSCRB=((1<<TWCMD1)|(1<<TWCMD0));//Das ist die Zeile wo das ACK sendet
10
}
Wenn ich die Funktion richtig verstanden habe
- fordert der Master vom Slave Daten ab mit if (TWSSRA & (1 << TWDIR))
- diese Daten stehen dann im TWSD (Datenpuffer)
- tx_buf_index steht auf 0 und wird so oft hochgezählt wie es angegeben
ist
- es werden die Daten in TWSD geladen mit tx_buf und dem tx_buf_index
- tx_buf_index wird hochgezählt
- mit TWSCRB = ((1<<TWCMD1)|(1<<TWCMD0)) erfolgt die übertragung der
Daten zum Master
Dann müsste in der Zeile da vor die Abfrage ob ADC fertig ist bzw. die
Verzögerung von SCL.
Noch eins zur Hardware. Möchte das ganze auch auf einen Joystick mit 2 x
ADC, Encoder und vielleicht auf entprellte Taster (nach Peter)
verwenden.
Habe das im DB gefunden:
Das Datenregister wird beim Senden und Empfangen von Daten verwendet.
Während der Übertragung werden die Daten vom/zum TWSD-Register und
zum/vom Bus geschoben. Daher kann während der Byte-Übertragung nicht auf
das Datenregister zugegriffen werden. Dies ist in der Hardware
geschützt. Auf das Datenregister kann nur zugegriffen werden, wenn die
SCL-Leitung vom Slave auf Low gehalten wird, d. h. wenn TWCH gesetzt
ist.
... und das wird im TWSSRA gemacht.
LG Heiner
Stefan ⛄ F. schrieb:> Zur Erinnerung: Das ist die Zeile wo du das ACK sendest:>> TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));>> Mehr ist da gar nicht zu tun, der Rest (das Clock Stretching) ergibt> sich dann von ganz alleine.
Habe dazu die Tabelle 20-2 gefunden. Dort steht
TWCMD[1:0] TWDIR Betrieb/Operation
00 X Keine Aktion
01 X Reserviert
10 Wird verwendet, um die Transaktion abzuschließen
0 Acknowledge-Aktion ausführen, dann auf eine START (S/Sr)-Bedingung
warten
1 Warten auf eine beliebige START (S/Sr)-Bedingung
11 Wird als Antwort auf ein Adressbyte verwendet (TWASIF ist gesetzt)
0 Acknowledge-Aktion ausführen, dann nächstes Byte empfangen
1 Acknowledge-Aktion ausführen, dann TWDIF setzenVerwendet als Antwort
auf ein Datenbyte (TWDIF ist gesetzt)
0 Acknowledge-Aktion ausführen, dann auf nächstes Byte warten
1 Keine Aktion
Hoffe das die Formatierung auch so rüber kommt wie im ori.
In der Tabelle werden TWCMD 1 und 0 und TWDIR angegeben und ACK bzw.
Einstellungen dazu.
Habe ich das richtig verstanden das TWCMD1=1 und TWCMD0=1 und TWDIR=0
sein muss und damit Clock Stretching eingeschaltet wird?
Sorry, ist mir ganz unklar.
Ich habe gerade die Augen verdreht. Ist das denn wirklich so schwer?
Du sollst an dem Code für die Bits gar nichts ändern, sondern einfach
nach dem Empfang des Kommandos erst den ADC 5x abfragen und danach das
ACK senden. In der Zeitspanne zwischen ISR und dem Beschreiben des
TWSCRB Registers passiert das Clock-Stretching von ganz alleine.
1
ISR(TWI_SLAVE_vect)
2
{
3
uint8_tstatus=TWSSRA&0xC0;
4
if(status&I2C_DATA_INTERRUPT)
5
{
6
if(TWSSRA&(1<<TWDIR))// Master fordert Daten vom Slave an
TWDIR ist gar nicht zum Beschreiben vorgesehen. Dieses Bit kannst du nur
lesen. Es zeigt an, ob der Master dir gerade ein Kommando-Byte
gesendet hat, oder ob du ihm mit einem Daten-Byte antworten sollst.
1
Bit 1 – TWDIR: TWI Read/Write Direction
2
3
This bit indicates the direction bit from the last address packet received from a master. When this bit is one, a master read operation is in progress. When the bit is zero a master write operation is in progress.
Stefan ⛄ F. schrieb:> Ich habe gerade die Augen verdreht. Ist das denn wirklich so schwer?
Also manchmal bewundere ich wirklich deine Ausdauer und Geduld. Auch
wenn selbst du hier scheinbar langsam an deine Grenzen stößt.
Aber vielleicht musst du dich am Ende doch mit dem Schluß abfinden, dass
dieser Typ einfach mal vollständig lernresistent ist.
Das muss seinerseits kein böser Wille sein, aber wenn's das nicht ist,
bleibt nur: IQ-Defizit. Bitter (für ihn), aber nicht zu ändern (für
uns).
c-hater schrieb:> Aber vielleicht musst du dich am Ende doch mit dem Schluß abfinden, dass> dieser Typ einfach mal vollständig lernresistent ist.>> Das muss seinerseits kein böser Wille sein, aber wenn's das nicht ist,> bleibt nur: IQ-Defizit. Bitter (für ihn), aber nicht zu ändern (für> uns).
Es ist auf keinen Fall ein böser Wille von mir. Leider ist bei diesen
Sachen auch das Ende meines Verständnisses (IQ) erreicht.
Eine Sache habt ihr damit wunderbar geschafft, das ich das Datenblatt
lese. Muss ganz offen sagen, so gründlich und oft wie in diesem Fall
habe ich noch nie ein Datenblatt gelesen. Habe auch versucht (so weit
möglich für mich) die Zusammenhänge zwischen den einzelnen Registern und
Einstellungen nach zu vollziehen. Einige Sachen fehlen noch beim lesen.
Werde auf jeden Fall weiter machen mit dem Attiny 841 und dran arbeiten
es zu verstehen. Manches geht leichter für mich andere Sachen sind sehr
schwer zu verstehen.
Hatte einen anderen Rat befolgt und mit den Einstellungen probiert,
leider ohne Erfolg. Wie ich jetzt sehe war ich auf dem richtigen Weg
aber sehr halbherzig. Hatte nur die hälfte gemacht und den zweiten Teil
total vergessen.
Werde alles testen und berichten. Sicher helfen wir und besonders ihr
auch vielen anderen Lesern (Anfängern) beim programmieren und lernen.
Allein dafür gebürt euch mein grosser Dank.
LG Heiner