margau hat geschrieben:Was ich zuerst zu sagen habe: So wie ich das sehe initialisiert der Arduino, bevor er in die Hauptschleife geht, auch noch diverse Timer die er für Dinge wie Delay oder millis() braucht. Das machst man beim reinen C natürlich nicht.
Desweiteren ist der Arduino darauf ausgelegt, mit Programmiertechnisch nicht ganz so begabten Leuten zu funktionieren. Jetzt erklär du denen mal, welchen Port sie wann setzten müssen, wo im 150-seitigen Datenblatt das steht.
Nein,wie Martin schon sagte, von der Arduino-typischen Initalisierung ist nix dabei, der Code den ich rausseziert habe wird bei jedem Aufruf von digitalWrite() ausgeführt.
Wo steht wie man die Ports beschaltet? Datenblatt, Kapitel "I/O Ports". Oder, in mundgerechte Happen zerlegt, im
Anfänger-Tutorial
Profipruckel hat geschrieben:Bauteiltöter hat geschrieben:Ein großer Kritikpunkt an Arduino ist ja vor allem die Performance die so viel schlechter ist ...
Einfache Aufgabe: Setze PD2 auf "high".
Ich weiß nicht, was Du uns sagen willst, aber einen Pin bekomme ich in der Arduino-IDE deutlich einfacher hoch:
Code: Alles auswählen
void setup() {
pinMode(8, OUTPUT); //LED
digitalWrite(8, HIGH);
}
void loop() {
// Endlosschleife
delay(500);
}
Vermutlich kann ich mir "
pinMode(8, OUTPUT);" auch noch ersparen, es wird zumindest nicht angemeckert.
Es ging mir darum herauszufinden was der Aufruf von digitalWrite() im Hintergrund bewirkt.
Und nein, pinMode() kannst du nicht weglassen... das ist vermutlich der einzige Punkt an dem die Arduino-IDE noch selber denken von dir verlangt, soll der Port Ein- oder Ausgang sein?
Der Compiler kann dich auch nicht vor allem retten, er warnt nur, wenn C-Regeln verletzt werden oder er C-Code sieht, der erfahrungsgemäß zwar legal ist, aber eigentlich nicht gewollt ist. (Klassiker wie if(a=true) oder if(bedinung);)
ferdimh hat geschrieben:Tatsächlich brauchst du MEHR Zeilen Code als in der "klassischen C-Lösung".
Der Punkt ist nicht, dass die Arduinolösung pauschal schlecht ist. Der Punkt ist, dass man die Lösung (bei gleichem Verhalten!) deutlich geschickter bauen könnte.
Das andere Problem ist, dass Menschen die Grenzen nicht sehen. Wer keinerlei technische Vorbildung hat und mit Arduino spielt, sieht die Grenzen nicht. Aber das ist die alte Leier...
Danke, das wollte ich mal aufzeigen. Mir ging es auch nicht darum, Arduino per se schlecht zu machen. Es heißt nur immer, "Arduino ist so langsam" und ich wollte das ganze mal mit Fakten untermauern.
Und um zu zeigen wie es effizient geht habe ichmal ein paar Makros gebastelt die sich genau so benutzen lassen wie digitalWrite()
Code: Alles auswählen
#include <avr/io.h>
/* spezialdefinitionen hier*/
#define LED B,1
void f1(void)
{
digitalWrite(LED,HIGH);
}
Als Makro ausgeführt wird das ganze zu ganzen 3 ASM-Befehlen (+Funktionsrücksprung):
Zwei der drei Befehle sind immernoch unnützer overhead (in/out), lassen sich aber bei weitem nicht so einfach vermeiden ohne an Komfort zu verlieren.
für ein digitalWrite(LED,LOW); compiliert es natürlich äquivalent in cbi...
Dazu habe ich noch passende Makros SET_OUTPUT, SET_INPUT, SET_PORT und RESET_PORT geschrieben die alle mit der Definition von LED funktionieren.
Die Verbindung zwischen Arduino-Nummern und Port-Pin-Konfiguration könnte man auch noch über ein paar Definitionen machen, z.B.
#define ARDU0 B,0
#define ARDU1 B,1
u.s.w.
Ein digitalRead() könnte man sicher auch recht einfach als Makro implementieren, das ganze hat mich jetzt vielleicht mit Beitrag schreiben 30min gekostet.
Das einzige, was meine Version anders macht: Sie überprüft nicht, ob der Benutzer den Pin vorher mit einem TImer verbunden hat (PWM-Out), das ist meiner Meinung nach aber auch... eher Überflüssig. Entweder PWM oder digitaler I/O, wenn man beides gleichzeitig an macht... nun, dann funktioniert es eben nicht richtig.
Hier der ganze Makro-Code:
Code: Alles auswählen
#include <avr/io.h>
#define digitalWritex(port, bit, state) do{PORT##port|=(state<<bit);PORT##port&=~(!state<<bit);}while(0);
#define digitalWrite(x, y) digitalWritex(x,y)
#define SET_PORTx(port, bit) do{PORT##port|=(1<<bit);}while(0)
#define SET_PORT(x) SET_PORTx(x)
#define RESET_PORTx(port, bit) do{PORT##port&=~(1<<bit);}while(0)
#define RESET_PORT(x) RESET_PORTx(x)
#define SET_OUTPUTx(port, bit) do{DDR##port|=(1<<bit);}while(0)
#define SET_OUTPUT(x) SET_OUTPUTx(x)
#define SET_INPUTx(port, bit) do{DDR##port&=~(1<<bit);}while(0)
#define SET_INPUT(x) SET_INPUTx(x)
#define HIGH 1
#define LOW 0
#define LED B,1
void f1(void)
{
digitalWrite(LED,HIGH);
}
Nicht von der komischen Makro-Syntax verschrecken lassen, davon würde man ja nichts sehen wenn man es in eine header-Datei auslagert und einfach nur benutzt. SO könnte es gehen bei gleichem Konfort und mit 25x weniger Code (zur Laufzeit).
Ich poste das hier weil ich mich direkt auf Antworten beziehe und das auch mein letzter Beitrag zu dem Thema wird (es sei denn, es kommen Rückfragen).