Guten Tag! Ich habe wieder eine Frage: Yalu X hat für mich sehr interessante Lösung mit Attribut "cleanup" erklärt. Beitrag "Re: Lokale Variable statt static, aber optimiert. Wie?" Vielleicht gibt es eine ähnliche Möglichkeit, um für die Ausführungszeit einer Funktion bestimmte Flags setzen und danach löschen (oder umgekehrt) ? Z.B. möchte ich Zugang zu SPI aus ISR. Z.B. aus Timer-ISR, wo Systempuls gemacht wird. Aber SPI kann in dieser Zeit andere Operationen aus mehreren byte-Sendungen ausführen, die nicht zu unterbrechen sind (in diesem Fall sollte Zugriff aus ISR nicht stattfinden, und wenn ISR wieder kommt, dann wieder versuchen). Natürlich kann ich "per Hand" am Anfang einer solchen Operation Flag "SPI besetzt" setzen, und am Ende dieser Operation wieder löschen. Aber es wäre doch schön, einfach wie bei cleanup "SPI_SAVE;" schreiben und nicht mehr denken, daß später Flag gelöscht sein sollte. Nach dieser Art könnten auch viele andere ähnliche Fälle gelöst werden... Ist das in GCC auch möglich? Vielen Dank für die Antwort im voraus!
:
Bearbeitet durch User
Maxim B. schrieb: > Vielleicht gibt es eine ähnliche Möglichkeit, um für die Ausführungszeit > einer Funktion bestimmte Flags setzen und danach löschen (oder > umgekehrt) ? Ich nehme weiterhin an, es geht um C? In C++ einfach machbar (Stichwort: RAII).
Ja, ich möchte bei C bleiben. Ich denke, dort wo ich mich jetzt befinde, sollte ich besser alle Möglichkeiten von C und GCC bestens kennenlernen. Wenn ATMega nicht mehr produziert werden, mein JTAGICEII kaputt geht und ich nach mehr Möglichkeiten suchen werde, als ATMega geben kann - dann kommt Zeit für C++.
:
Bearbeitet durch User
Maxim B. schrieb: > Ja, ich möchte bei C bleiben. Ok, aber schade. Mal als Anregung: https://www.youtube.com/watch?v=YnWhqhNdYyk > Ich denke, dort wo ich mich jetzt befinde, sollte ich besser alle > Möglichkeiten von C und GCC bestens kennenlernen. Warum? > Wenn ATMega nicht mehr produziert werden, mein JTAGICEII kaputt geht und > ich nach mehr Möglichkeiten suchen werde, als ATMega geben kann - dann > kommt Zeit für C++. ???
Maxim B. schrieb: > Aber es wäre doch schön, einfach wie bei cleanup "SPI_SAVE;" schreiben > und nicht mehr denken, daß später Flag gelöscht sein sollte. Sowas?
1 | void tuWas() |
2 | {
|
3 | SPI_SAVE(SPI1) |
4 | {
|
5 | // hier tuwas mit SPI1
|
6 | }
|
7 | }
|
Dann schaue dir das ATOMIC_BLOCK makro an, das tut es so!
Wilhelm M. schrieb: > Warum? > > ??? Weil die Profis sagen: mit C++ kann man viel leichter als mit C etwas schlechtes und unverständliches machen. Und auch weil ich nicht genau weiß, wie man mit AVR Studio 4.19 etwas auf C++ macht. Umstellen auf eine andere Version von Studio möchte ich jetzt nicht, da JTAG mit ihr gut arbeitet. Wenn ich auf spätere Versionen von Studio gehe, dann sind Kosten für Upgrade zu hoch: ich brauche neuen Laptop, fast alle Programme neu und noch neuen JTAG-Emulator. Ich möchte schon vorhandene Technik bis zu Ende benutzen, und erst wenn es nicht weiter geht, nur dann ersetzen. Manche Programme kosten alleine vergleichbar mit einem Laptop.
:
Bearbeitet durch User
Maxim B. schrieb: > Wilhelm M. schrieb: >> Warum? >> >> ??? > > Weil die Profis sagen: > mit C++ kann man viel leichter als mit C etwas schlechtes und > unverständliches machen. Das sind ja tolle Profis ;-) M.E. ist die Reihenfolge C -> C++ sehr ungünstig, vor allem, wenn man damit auf dem µC anfängt. Man lernt dabei sehr schlecht bis gar nicht, in Abstraktionen zu denken. Besser ist in meinen Augen ein Start auf dem PC mit C++, dann C++ auf dem µC, wobei automatisch die prozeduralen (und generischen) Anteile in den Vordergrund rücken.
Maxim B. schrieb: > Aber SPI kann in dieser Zeit andere Operationen aus > mehreren byte-Sendungen ausführen, die nicht zu unterbrechen sind Für den Fall bietet sich der SPI-Interrupt geradezu an. Man legt ein Array von Callbacks (Funktionspointer) an, die der SPI-Interrupt aufruft. Ein Indexzähler zeigt dann jeweils auf das auszuführende Callback. Ist es fertig, löscht es sich aus der Liste (Nullpointer) und setzt den Index eine Stelle weiter. Ist die Liste leer, disabled sich der SPI-Interrupt. Wird ein SPI-Job in die Liste eingetragen, enabled er den SPI-Interrupt wieder. Jedes Callback behandelt immer nur ein Byte, d.h. muß sich den Bytezähler selber merken. Oder der Bytezähler wird mit in der Liste gespeichert und dem Callback übergeben. Der Timerinterrupt trägt seinen Callback dann in die nächste freie Stelle ein. Ich würde dafür folgende Funktionen implementieren: void spi_job_init(void); bool spi_job_add(fp *fptr); void spi_job_advance(void); P.S.: Für den Bytezähler reicht eine Variable, da ja die Jobs nicht gleichzeitig ausgeführt werden können. Er muß also nicht mit ins Array.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Warum? > > ??? Ach, lass ihn... Ein gutes C Programm ist immer noch schöner, als ein schlechtes in C++. C++ lernen ist mit ein paar Hürden verbunden. Mittlerweile habe ich etwas C++ Übung, und ich kann sagen: > Wenn man das Licht am Ende des Tunnels, meint zu sehen, > dann ist es meist ein Zug, der auf einen zu kommt.
Arduino Fanboy D. schrieb: > Wilhelm M. schrieb: >> Warum? >> >> ??? > > Ach, lass ihn... Mich interessieren die Antworten auf solche Fragen. > Ein gutes C Programm ist immer noch schöner, als ein schlechtes in C++. Man kann es aber in C++ wesentlich schöner machen ... > C++ lernen ist mit ein paar Hürden verbunden. Eigentlich nur, wenn man schlechte Bücher und/oder schlechte Lehrer hat.
Maxim B. schrieb: > Ich denke, dort wo ich mich jetzt befinde, sollte ich besser alle > Möglichkeiten von C und GCC bestens kennenlernen. In C geht so etwas nicht vernünftig. Alle obskuren Möglichkeiten von GCC ausloten um es nachzubauen macht dich vom GCC abhängig, ist wenig übertragbar und erweiterbar, man findet nicht viel dazu im Netz oder Büchern, funktioniert mit anderen Compilern & Plattformen nicht. Da ist es doch sinnvoller die gut bekannten, verbreiteten und flexiblen Möglichkeiten von C++ zu lernen. Viel mehr Leute dürften zumindest die hier benötigten Grundzüge von C++ kennen, als alle Details und Erweiterungen des GCC. Maxim B. schrieb: > Und auch weil ich nicht genau weiß, wie man mit AVR Studio 4.19 etwas > auf C++ macht. Die Quellcode-Datei nach .cpp umbenennen. Maxim B. schrieb: > Umstellen auf eine andere Version von Studio möchte ich > jetzt nicht, da JTAG mit ihr gut arbeitet. C++ Programme werden exakt genauso per JTAG übertragen. Maxim B. schrieb: > Wenn ATMega nicht mehr produziert werden, mein JTAGICEII kaputt geht und > ich nach mehr Möglichkeiten suchen werde, als ATMega geben kann - dann > kommt Zeit für C++. Du würdest also auch erst Auto Fahren lernen wenn es keine Pferde und Kutschen mehr gibt? Maxim B. schrieb: > Wenn ich auf spätere > Versionen von Studio gehe, dann sind Kosten für Upgrade zu hoch: ich > brauche neuen Laptop, fast alle Programme neu und noch neuen > JTAG-Emulator. Wie alt ist dieses Laptop, und wie sehr möchtest du dich durch Sparen einschränken... Halbwegs aktuelle PC-Hardware bekommt man (gebraucht) für 300€ oder so. Ansonsten ist die Antwort auf deine Frage: Genau so wie in Beitrag "Re: Lokale Variable statt static, aber optimiert. Wie?"
Es gibt bei Mikrocontrollern nur einen harten Grund gegen C++: Mikrocontroller ohne RAM können C++ Programme nicht ausführen. Nur: Wann hat hier jemand zuletzt mit so einem µC zu tun gehabt?
Peter D. schrieb: > Für den Fall bietet sich der SPI-Interrupt geradezu an. > Man legt ein Array von Callbacks (Funktionspointer) an, die der > SPI-Interrupt aufruft. Ein Indexzähler zeigt dann jeweils auf das > auszuführende Callback. Vielen Dank! Sehr interessante Idee! Im Moment kam das Problem bei mir, weil ich alle auf meiner Platine eingebauten Geräte noch teste und Grundfunktionen schreibe. Hauptschleife. Drehgeber sollte aber besser jede ms abgefragt werden, mit steigender Zahl von Aufgaben in der Hauptschleife hat Drehgeber seine Grenze erreicht, deshalb sollte ich aus ISR abfragen. In der Zukunft möchte ich aber von mir früher (aus einer Idee von einem Anderen) entworfenen Planer benutzen, dort gibt es Prioritäten und mit jeder Aufgabe wird noch eine 32bit-Variable gespeichert (nichts steht im Wege (außer Leistung), auch 64bit-Variable zu speichern). Dort wird das einfacher: wird eine Aufgabe, die SPI braucht, merken, daß SPI besetzt wird, dann stellt sich selber die Aufgabe wieder auf die Reihe, ein paar ms später. Aber für mich ist interessant, alle Varianten auszuprobieren. Ich denke, die Arbeit mit ISR ist besonders für I2C und USART von Wert. Bei SPI kommen lange mehrbytes-Übertragungen. Z.B. wenn ich meine graphische Anzeige bediene, die über MCP23S17 geschalet wurde, wird für jeden Bytes in Display 12 bytes per SPI übertragen (d.h. ein ASCII-Zeichen kostet 72 bytes). Beim Lesen noch mehr (alles in 3-bytes-Einheiten). LCD braucht in SPI-Mode (mit 4bit-parallel habe ich wenig Glück gehabt) auch je 3 bytes ununterbrochen in Serie (aber mit langsamer Geschwindigkeit als andere Geräte). SPI-RAM kann blockweise lange Übertragungen machen, auch für 1 bytes sind 5 bytes notwendig. Kleinstmögliche Einheit kann man wohl nach CS bestimmen. Ja, es gibt was zu überlegen noch...
Dr. Sommer schrieb: > Wie alt ist dieses Laptop, und wie sehr möchtest du dich durch Sparen > einschränken... Halbwegs aktuelle PC-Hardware bekommt man (gebraucht) > für 300€ oder so. Na, etwa schon 9 Jahre. Problem ist nicht und nicht nur Laptop selbst sondern alles, was auf dem steht. Ursprünglich stand auf dem Laptop Windows 7, aber ich habe auf gut mir bekanne Windows XP umgestellt (ich konnte noch Treiber finden), was Geschwindigkeit spürbar verbesserte. Ich habe eine Menge von Programmen, die mit Windows 10 nicht laufen, manche auch mit Windows 7, die ich aber täglich brauche. Extra nur für Mikrocontrollern Laptop zu halten ist auch nicht so bequem, da ich zu dem Laptop gewöhne und ständige Wechsel nicht komfortabel ist (das habe ich erlebt, wie ich versuchte, zweiten Laptop mit Kubuntu parallel zu nutzen). Ich habe Festplatte 2 TB und 4 GB RAM (davon kann XP 3,5 benutzen, was auch nicht so schlecht ist) installiert, und zuerst reicht mir das für alles.
:
Bearbeitet durch User
Maxim B. schrieb: > wird für jeden Bytes > in Display 12 bytes per SPI übertragen Vielleicht ist für dich ein kleiner ARM-Controller (z.B. STM32F103) mit DMA sinnvoll. Der kann (nahezu) beliebig viele Bytes auf einmal ohne Software-Arbeit übertragen. Maxim B. schrieb: > SPI-RAM kann blockweise lange Übertragungen machen SPI-RAM braucht man dann wahrscheinlich auch nicht mehr, weil die viel RAM integriert haben. Weitere Vorteile: C++ läuft besser da Standard-Bibliothek vorhanden, kein __flash oder PROGMEM benötigt, JTAG-Adapter sehr billig, komplett Open Source Toolchains verfügbar (geht auch super mit Linux, was auf alten PCs gut geht)... Maxim B. schrieb: > Ursprünglich stand auf dem Laptop > Windows 7, aber ich habe auf gut mir bekanne Windows XP umgestellt (ich > konnte noch Treiber finden), was Geschwindigkeit spürbar verbesserte. Damit sollten aber auch aktuellere Toolchains laufen, auch für ARM. Wobei ich mir schon Gedanken machen würde ob man die uralte Software wirklich braucht und die nicht per VM geht und ob man davon wirklich so viel abhängig machen möchte.
Windows 10 möchte ich prinzipiell nicht benutzen: vor 2 Jahren habe ich Laptop mit Windows 10 gekauft, alles war sehr sehr langsam. Dann habe ich Kubuntu installiert, dort eine virtuelle Maschine und dort noch Windows XP und Windows 7. Komisch: Windows XP über Kubuntu und virtuelle Maschine läuft deutlich besser und schneller, als Windows 10 direkt!!! Was haben dort die Programmierer aus Microsoft gemacht, keine Ahnung. Aber man braucht bestimmt viel Talent, um aus einem nicht besonders schlechten Laptop eine Bremse zu machen!
:
Bearbeitet durch User
Dr. Sommer schrieb: > Vielleicht ist für dich ein kleiner ARM-Controller (z.B. STM32F103) mit > DMA sinnvoll. Der kann (nahezu) beliebig viele Bytes auf einmal ohne > Software-Arbeit übertragen. Ich finde es viel bequemer mit einem Mikrocontroller mit 5 Volt Speisung: so kann ich auch blauen und weißen LED direkt an Pins schalten, ohne Pegelwandler. Auch für MOSFET ist 5 Volt besser als 3. Es ist normalerweise leichter, Pegel von 5 auf 3 Volt zu reduzieren als umgekehrt. Ich möchte zuerst alle vorhandenen ATMega bis zu Verschleiß ausnutzen. Danach kenne ich C bestimmt viel besser und kann dann wohl mit STM etwas machen. Ich mag es außerdem, die IC auf selbstgebaute Leiterplatte zu löten, ohne Zwischenstufe. STM mit 0,5 mm zwischen Pins ist für meinen Augen eine Herausforderung. Nach Möglichkeit gehe ich nicht unter 1,27 mm, notfalls 0,8 mm.
:
Bearbeitet durch User
Maxim B. schrieb: > Ich finde es viel bequemer mit einem Mikrocontroller mit 5 Volt > Speisung: so kann ich auch blauen und weißen LED direkt an Pins > schalten, ohne Pegelwandler. Kompromisslösung:
1 | +-----------------------------------------------------+ |
2 | | | |
3 | 5V o---+---[3,3V Regler]---[Mikrocontroller]---[===]---|<|---+ |
4 | |
5 | LED |
Auf meiner Platte gibt es auch 3V3: für SD-Card und für LCD... Für diese Platte habe ich mit Absicht ATMega in DIP40 genommen: nach Verschleiß (10 000 Umprogrammierungen versprochen) kann ich die wechseln, ohne zu löten. So hoffe ich, damit lange spielen zu dürfen. Ich habe sozusagen hauseigene Standard für Module entwickelt, so möchte ich Erweiterungsplatten für alles mögliche machen (eine mit MIDI-Buchsen und Optokoppler ist schon gemacht).
Maxim B. schrieb: > Windows 10 möchte ich prinzipiell nicht benutzen: vor 2 Jahren > habe ich > Laptop mit Windows 10 gekauft, alles war sehr sehr langsam. Auch nachdem alle Updates installiert, alle Bloatware gelöscht und alle Treiber aktualisiert waren (oder besser: komplett neu installiert wurde)? Naja, aktuelle Toolchains gehen wie gesagt sogar mit XP, wobei ich mir das nicht antun würde (allein schon weil man damit aus Sicherheitsgründen natürlich nicht mehr ins Netz gehen sollte). Auf meinem auch nicht mehr ganz neuen Laptop (einfaches Office-Gerät von 2013) läuft Win10 super flüssig. Maxim B. schrieb: > Ich finde es viel bequemer mit einem Mikrocontroller mit 5 Volt > Speisung: Na dann, du musst wissen ob die 5V-Bequemlichkeit wichtiger ist als die Software-Bequemlichkeit (bessere Toolchains, besseres Debugging, viel mehr Leistung/Ressourcen, ...). Maxim B. schrieb: > Danach kenne ich C bestimmt viel besser und muss alle schlechten C-Angewohnheiten wieder un-lernen wenn du dann doch mal auf C++ wechseln möchtest... Maxim B. schrieb: > STM mit 0,5 mm zwischen Pins ist für meinen Augen > eine Herausforderung. Nach Möglichkeit gehe ich nicht unter 1,27 mm, > notfalls 0,8 mm. Der STM32G031J6 hat ein 1.27mm SO-8 Gehäuse. Ist allerdings eine ziemliche Ausnahme. Es gibt aber sehr billige handliche Breakout-Boards... Maxim B. schrieb: > Für diese Platte habe ich mit Absicht ATMega in DIP40 genommen: nach > Verschleiß (10 000 Umprogrammierungen versprochen) Die 10.000 hat noch nie jemand erreicht... Vorher grillt man die per ESD oder so.
Dr. Sommer schrieb: > Naja, aktuelle Toolchains gehen wie gesagt sogar mit XP Ich habe mir Toolchain aus einer aktuellen Atmel Studio herausgenommen. Dafür habe ich unter Kubuntu, virtueller Maschine und Windows 7 die installiert (sehr langsam!), Daten kopiert und danach alle gleichnahmigen Daten in dem vorhandenen Toolchain ersetzt. > Der STM32G031J6 hat ein 1.27mm SO-8 Gehäuse. 2x Vcc und Gnd. Dann wohl auch Reset? Und was bleibt fürs Leben? Wozu so ein Leben überhaupt? > Die 10.000 hat noch nie jemand erreicht... Vorher grillt man die per ESD > > oder so. Macht nichts. Ich habe welche parat :) Einfach neue stecken und los... Auch stehen zwei 20xBuchsen parallel zu MC, so habe ich alle MC-Leitungen auch für externe Steckbrett. Es gibt auch Buchsenreihen für GND, 5 und 3,3 Volt. Als Anregung diente mir diese Platte: http://shop.easyelectronics.ru/index.php?productID=153 Die habe ich auch gekauft, wie ich in Moskau war (ich sollte lange warten, bis sie aus Sybirien kommt!). Aber sie ist für etwas anderes gedacht. Ich habe überlegt, ich mache mir lieber eine eigene, mit anderen Akzenten. Alles, was ich für besonders häufigen Gebrauch schätze und was auch für Debug gut sein kann, habe ich auf dieser Platte integriert: 2x LCD (Symbol- und graphische), digitale Anzeige (aus China mit max7219) und eine Baranzeige (auch max7219), 5 Tasten und Drehgeber, DS3234 und SPI-RAM mit 1,5 F Kondensator, MicroSD-Steckdose mit Pegelwandler, 3 chinesischen WunderLED WS2812B... Alles außer SD-Card schon getestet. Alles andere sollte extern kommen, per Buchsen.
:
Bearbeitet durch User
Maxim B. schrieb: > Ich habe mir Toolchain aus einer aktuellen Atmel Studio herausgenommen. Dir ist klar dass man die auch separat herunterladen kann... Auch für Linux! Maxim B. schrieb: > Einfach neue stecken und los... Ich dachte die sollen direkt auf die Platine. Ob Sockel oder Mini-Breakout-Board ist auch kein großer Unterschied... z.B.: https://www.st.com/en/evaluation-tools/nucleo-l432kc.html Das hat sogar den Debugger mit dabei. Maxim B. schrieb: > Als Anregung diente mir diese Platte: Was für ein Monstrum! Für ARM gibt es natürlich auch eine riesige Vielfalt an Platinen/Eval-Boards. Und dank einheitlicher Plattform kannst du die alle (von allen Herstellern) mit der selben Software und dem selben JTAG-Adapter programmieren (sofern du einen herstellerübergreifenden hast, z.B. J-Link).
Dr. Sommer schrieb: > Dir ist klar dass man die auch separat herunterladen kann... Ich habe nichts passendes gefunden. Bei allen neueren Versionen, wenn ich die direkt zu installieren versuchte, war Problem mit Make. Deshalb habe ich letzte Version, wo Make drin ist und gut arbeitet (avr-toolchain-installer-3.4.2.1573-win32.win32.x86.exe), danach avr8-gnu-toolchain-installer-3.6.0.1734 dazu noch gebracht. > Was für ein Monstrum! Was Autor wirklich gut gemacht hat: es gibt eine Reihe von Artikel von ihm, wo er stufenweise für Anfänger mit dieser Platte erklärt, wie alles geht. Alles mit Beispiel. Z.B. wie man graphische Anzeige bedient oder wie man TWI als ISR-Automat macht. Was aber dem Autor nicht gelungen wurde: gute Speisesystem. Auch eingebaute JTAG ICE Generation 1 ist für mich nicht von Wert. Dagegen gibt es mit seiner Platte Problem, USART mit XCK zu nutzen. Ich wollte schon mit ARM (mit STM) beginnen. Aber dann fand ich, daß ich lieber zuerst mit einfacheren AT Mega lerne. Speisesystem: ich habe für nur 5 Volt die Platte gemacht (es gibt Geräte mit 3V3, aber MC hat 5 Volt). Grund war: manche IC wollen doch lieber 5 Volt und arbeiten von 3V3 schlecht oder gar nicht (max7219 oder auch WS2812B ). Von anderer Seite, wenn ich später einiges vom Code voanders verwende, dann geht das genau so auch mit 3 Volt oder auch 4 oder auch 1,8 Volt (nur F_CPU anpassen). OKI-78SR benutze ich schon seit langem, immer stabile gute Arbeit. 1,5 A bei 5 Volt reicht meistens für alles. Vin kann 9, 12, 24 Volt sein, alles akzeptabel, da Impulswandler. Und es steht noch LD1117 für 3,3 Volt - auch mit Absicht keine modernere genommen, da hier Sparsamkeit unwichtig ist, aber Fähigkeit von Wert, notfalls auch Strom zu nehmen.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Das sind ja tolle Profis ;-) > M.E. ist die Reihenfolge C -> C++ sehr ungünstig, vor allem, wenn man > damit auf dem µC anfängt. Man lernt dabei sehr schlecht bis gar nicht, > in Abstraktionen zu denken. Besser ist in meinen Augen ein Start auf dem > PC mit C++, dann C++ auf dem µC, wobei automatisch die prozeduralen (und > generischen) Anteile in den Vordergrund rücken. Es ist wurscht, welche Sprache du verwendest. Man muss unabhängig von der Sprache und unabhängig von der SW-Entwicklung in Abstraktionen denken können. Der Entwurf (= das funktionale Design) eines Programms oder einer Applikation sollte deine prozeduralen Anteile bereits beinhalten. Deine generischen Anteile kommen aus der Architektur, die nach und folgend aus dem Design erstellt wird. kopfschüttel Man lernt programmieren vielleicht mit Beispielen in einer Sprache. Die Sprache definiert aber keinesfalls was und wie du denken können sollst. Glaub mir, es gibt C++-Software-Entwickler, die gerne in einer einzigen C++-Quelldatei 10 Klassen runterschreiben, die sich zu 95% gleichen. Diese Art von "Entwickler" hat kein abstraktes Denken gelernt. Die Sprache unterstützt diese armen Menschen daher garnicht beim Anwenden einer bestimmten Denkweise.
PS Bis die Architektur steht, ist übrigens noch keine einzige Zeile Code da.
ein Profi schrieb: > Man lernt programmieren vielleicht mit Beispielen in einer Sprache. Die > Sprache definiert aber keinesfalls was und wie du denken können sollst. Erzähle das mal den Leuten, die Frameworks vermarkten, die der Nabel der Welt sein wollen.
Wilhelm M. schrieb: > Mich interessieren die Antworten auf solche Fragen. Mich eher nicht. Denn die Antwort ist offensichtlich! Wer vor der Entscheidung steht, C oder C++ zu lernen, hat noch nicht die nötige Kompetenz/Wissen/Erfahrung um diese Entscheidung objektiv zu treffen. Also wird die Entscheidung aus dem Bauch heraus getroffen. Damit ist sie automatisch irrational(?). Diese Art der Entscheidungsfindung wurde uns von der Evolution für Notlagen mitgegeben. Denn wenn einen ein Tiger in den Hintern beißen will, ist keine Zeit für Abwägungen, kundig machen usw. Damit hat sich die Frage "Warum?" eigentlich erübrigt. Es gibt kein ursprüngliches "Warum?", bestenfalls eine nachgeschobene Rechtfertigung. Ich behaupte: 99% aller Entscheidungen beruhen nicht auf klare Fakten, sondern werden aus dem Bauch heraus getroffen. Danach wird ein Großteil der Intelligenz darauf verplempert, sich und anderen, den Mist schön zu reden, den man gerade verzapft. Beispiel: Durch die Kurve bin ich schon hundert mal gefahren, die konnte ich schon immer schneiden, da ist mir noch nie einer entgegen gekommen. Meine Erfahrung sagt: (habe das einige male beobachten dürfen) Leute, welche aus der prozeduralen Ecke (z.B. C) kommen, tun sich mit der OOP (z.B. C++) recht schwer. Sind quasi verdorben für die OOP. Andersrum ist es einfacher. Bei der OOP, bekommt man die prozedurale Sicht geschenkt dazu. Es ist also schon so, dass die verwendete Sprache/Verfahren das Denken formt.
Arduino Fanboy D. schrieb: > Wer vor der Entscheidung steht, C oder C++ zu lernen, hat noch nicht die > nötige Kompetenz/Wissen/Erfahrung um diese Entscheidung objektiv zu > treffen. Na, ich kann sagen, warum ich mit C begonnen habe: ich höre herum: C und C und nochmal C, dann "void" - und verstehe nichts! So etwas kann ich nie dulden. Deshalb :) Ich habe früher C51 mit Maschinencode programmiert - und komischerweise funktionierte das. Noch ohne Computer. So ist Denken mit Register, Speicherzellen usw. für mich verständlicher als mit Abstraktionen.
:
Bearbeitet durch User
Beitrag #5957778 wurde von einem Moderator gelöscht.
Maxim B. schrieb: > So ist Denken mit Register, > Speicherzellen usw. für mich verständlicher als mit Abstraktionen. Die Angst vor dem fremden/neuen? ;-) ;-)
Maxim B. schrieb: > Na, ich kann sagen, warum ich mit C begonnen habe: > ich höre herum: C und C und nochmal C, dann "void" - und verstehe > nichts! So etwas kann ich nie dulden. > Deshalb :) Du verstehst 'void' nicht?
Arduino Fanboy D. schrieb: > Die Angst vor dem fremden/neuen? Ja, ich mag alles haben "wie immer" :)
Maxim B. schrieb: > Ja, ich mag alles haben "wie immer" :) Ich verstehe das... Möglichst viel Assembler Denke mit in C einschleppen. Und dann 3 Jahre später, möglichst C Artig in C++ weiter machen. Ja, so kann man das Optimum auch aus diesem Problem raus holen. Da ist nix seltsames dran, alles total menschlich.
Arduino Fanboy D. schrieb: > Sowas?void tuWas() > { > SPI_SAVE(SPI1) > { > // hier tuwas mit SPI1 > } > } > > Dann schaue dir das ATOMIC_BLOCK makro an, das tut es so! Ja!!! Ich glaube, das hat geklappt!
1 | // spi_atomic.h
|
2 | #ifndef SPI_ATOMIC_H
|
3 | #define SPI_ATOMIC_H
|
4 | |
5 | #include <avr/io.h> |
6 | #include <avr/interrupt.h> |
7 | |
8 | #include "main.h" |
9 | |
10 | static __inline__ uint8_t __iSetSpiBesetztRetVal(void) |
11 | {
|
12 | FLAGG |= (1<<SPI_BS); |
13 | return 1; |
14 | }
|
15 | |
16 | static __inline__ void __iResSpiBesetztParam(const uint8_t *__s) |
17 | {
|
18 | FLAGG &= ~(1<<SPI_BS); |
19 | __asm__ volatile ("" ::: "memory"); |
20 | (void)__s; |
21 | }
|
22 | |
23 | #define SPI_BLOCK(type) for ( type, __ToDo = __iSetSpiBesetztRetVal(); \
|
24 | __ToDo ; __ToDo = 0 )
|
25 | |
26 | #define SPI_FORCEON uint8_t spi_save \
|
27 | __attribute__((__cleanup__(__iResSpiBesetztParam))) = 0
|
28 | |
29 | |
30 | #endif /* SPI_ATOMIC_H */ |
Dann
1 | SPI_BLOCK(SPI_FORCEON){ |
2 | lcd_adrmode(); |
3 | spi_intern_start(); |
4 | |
5 | spi_master_transmit(0x1f); |
6 | spi_master_transmit(data & 0x0f); |
7 | spi_master_transmit(data >> 4); |
8 | |
9 | spi_intern_stop(); |
10 | }
|
In Disassembler ist alles wie gedacht. Was mir noch stört: Code arbeitet, aber ich kapiere noch nicht ganz, wie genau :) Und noch eins: Da ich RESTORESTATE nicht benutze, ist spi_save eigentlich überflüssig? Aber ohne will Compiler nichts machen!
:
Bearbeitet durch User
Maxim B. schrieb: > __iSetSpiBesetztRetVal Bezeichner mit 2 Unterstrichen, oder Unterstrich + Großbuchstabe, sind in C und C++ reserviert und der Standard Bibliothek vorenthalten. Maxim B. schrieb: > _asm_ volatile ("" ::: "memory"); Das ist hier wohl unnötig (bzw. kann für suboptimalen Code sorgen) und ein Überbleibsel von ATOMIC_BLOCK. Manche Leute beschweren sich über die kryptische Syntax von C++, obwohl sie vielen bekannt ist und es viele Bücher darüber gibt. Andere schreiben wilde C Makros mit Compiler spezifischen Erweiterungen...
Dr. Sommer schrieb: > Das ist hier wohl unnötig (bzw. kann für suboptimalen Code sorgen) und > ein Überbleibsel von ATOMIC_BLOCK. Ja, das ist Überbleibsel. Compiliert wird in sbi-cbi an vorgesehenen Stellen. Ich habe schon Angst, Zeichen zu wechseln, da endlich funktioniert :) Ich habe die Namen für SpiBesetztRestore usw. ersetzt. > Andere schreiben wilde C Makros mit Compiler spezifischen Erweiterungen... Wie schrieb J.S.Bach in seiner Kantate BWV 163...
:
Bearbeitet durch User
Peter D. schrieb: > Man legt ein Array von Callbacks (Funktionspointer) an, die der > SPI-Interrupt aufruft. Ein Indexzähler zeigt dann jeweils auf das > auszuführende Callback. Ist es fertig, löscht es sich aus der Liste > (Nullpointer) und setzt den Index eine Stelle weiter. Ist die Liste > leer, disabled sich der SPI-Interrupt. Wird ein SPI-Job in die Liste > eingetragen, enabled er den SPI-Interrupt wieder. Jedes Callback > behandelt immer nur ein Byte, d.h. muß sich den Bytezähler selber > merken. Oder der Bytezähler wird mit in der Liste gespeichert und dem > Callback übergeben. > Der Timerinterrupt trägt seinen Callback dann in die nächste freie > Stelle ein. Ein Problem sehe ich hier: SPI-Intrface ist sozusagen eine halbfertige Schnittstelle. SPI-Interface senden byte und nimmt byte, aber es ist nichts in Interface bzg. CS definiert. Sendungen können 1 byte, 2 bytes, 3 bytes und auch hunderte bytes zwischen CS low und CS high sein. Deshalb die Worte "Jedes Callback > behandelt immer nur ein Byte" scheinen mir etwas zweifelhaft zu sein. Eine Funktion, die aus Array gerufen wird, sollte vollständige Übertragung beinhalten: CS-Adresse einstellen (je nach System entweder entsprechende CS-Pin wählen, oder wie bei mir 3 Bit für HC138), CS runter, alle bytes wie es sind, CS rüber. Vor Einstellung der Adresse bis "CS rüber" darf die Sendung nicht unterbrochen werden. Wenn SPI in ISR gleich die Serien von bytes senden sollte, dann braucht man vielleicht FIFO-Array von Structuren, wo Datenarray selbst, Bytezahl, SPI-Adresse und SPI-Einstellungen (Mode, Geschwindigkeit und Bitordnung) gespeichert werden. Alles das ist natürlich möglich...
:
Bearbeitet durch User
Maxim B. schrieb: > Ein Problem sehe ich hier: > SPI-Intrface ist sozusagen eine halbfertige Schnittstelle. SPI-Interface > senden byte und nimmt byte, aber es ist nichts in Interface bzg. CS > definiert. Sendungen können 1 byte, 2 bytes, 3 bytes und auch hunderte > bytes zwischen CS low und CS high sein. Deshalb die Worte "Jedes > Callback >> behandelt immer nur ein Byte" scheinen mir etwas zweifelhaft zu sein. Eine > Funktion, die aus Array gerufen wird, sollte vollständige Übertragung beinhalten: > CS-Adresse einstellen (je nach System entweder entsprechende CS-Pin wählen, oder > wie bei mir 3 Bit für HC138), CS runter, alle bytes wie es sind, CS rüber. Vor > Einstellung der Adresse bis "CS rüber" darf die Sendung nicht unterbrochen werden. > > Wenn SPI in ISR gleich die Serien von bytes senden sollte, dann braucht > man vielleicht FIFO-Array von Structuren, wo Datenarray selbst, > Bytezahl, SPI-Adresse und SPI-Einstellungen (Mode, Geschwindigkeit und > Bitordnung) gespeichert werden. Alles das ist natürlich möglich... ... und wir sind bei function-overloading angekommen
Ich fürchte, dann wird Array von Structuren, wo jede Structur auch Array für zu sendende Daten hat, zu groß für Mikrocontroller. Deshalb bleibt vielleicht bessere Lösung: FIFO für Aufgaben, die auch aus ISR gestellt sein können, gemacht werden aber alle in der Hauptschleife.
:
Bearbeitet durch User
Wilhelm M. schrieb: >> Wenn SPI in ISR gleich die Serien von bytes senden sollte, dann braucht >> man vielleicht FIFO-Array von Structuren, wo Datenarray selbst, >> Bytezahl, SPI-Adresse und SPI-Einstellungen (Mode, Geschwindigkeit und >> Bitordnung) gespeichert werden. Alles das ist natürlich möglich... > > ... und wir sind bei function-overloading angekommen Ich wollte noch hinzufügen, war aber zu langsam mit dem Bearbeiten: viele denken, C++ sei eine objektorientierte Sprache. Das stimmt nur bedingt, denn C++ ist eine Multiparadigmen-Sprache, OOP ist nur ein Aspekt von vielen anderen Paradigmen dabei.
Ich werde mich freuen, wenn ich einmal mit C gut vertraut werde. Zu viele Aufgaben auf einmal sind nicht nur für Mikrocontroller, sondern auch für Menschen nicht wünschenswert.
1 | int main(void){ |
2 | |
3 | 1. init |
4 | 2. Aufgaben starten, die im Hintergrund laufen sollten |
5 | while(1){ |
6 | wdt_reset(); |
7 | TaskManager(); |
8 | }
|
9 | return 0; |
10 | }
|
Deshalb habe ich für LCD je zwei Versionen von data_out und command_out vorgesehen: mit Verzögerung danach (für Init) und ohne Verzögerung (für Arbeit mit TaskManager).
:
Bearbeitet durch User
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.