Hallo,
ein echt aufschlussreiches Forum hier. Habe schon einiges verwenden
können. Nun zu meiner Frage: Ich habe einen ATmega2561, der über die
serielle Schnittstelle mit mein PC Interruptgetriggert kommmuniziert.
Gibt es in C irgendeine Möglichkeit wie man einen String, z.B.
"SetPortA(0xaf);" in einen direkten Befehl an den Mikrocontroller
umwandeln kann.
Bisher ist mir nur eingefallen beim Empfang eines Strings, diesen dann
zu decodieren.
mfg Edgar
noch als kleine Info: Der String wird vom PC an den Mikrocontroller
gesendet und steht im Anschluss in einem Buffer, über den ich auf den
String zugreifen kann. Danke schon mal im Voraus über die hoffentlich
zügigen Antworten.:-)
Das gibts bei interpretierten Sprachen als "eval" (PHP, Perl,
JavaScript). In C funktioniert das so net. Da wirst du wohl mit
Tabellen mit Funktionszeigern schaffen müssen, was aber wiederum schnell
und elegant ist.
Danke für die schnelle Antwort. Du meinst, dass ich den abhängig von dem
String in eine Tabelle verzweige, in der die Funktionen aufgelistet
sind. Wie soll ich denn dann auf meinen Übergabewert kommen, ohne
Decodierung?
mfg
Ein Standard wäre RPC (Remote Procedure Call). Aber für einen kleinen
Microcontroller dürfte das weit überdimmensioniert sein.
Ich denke Du kommst um das decodieren des empfangenen Strings nicht
herum - auch um zu prüfen, ob überhaupt ein gültiger String angekommen
ist.
Was verstehst Du unter "decodieren" bzw. warum möchtest Du das
vermeiden?
Ich verstehe unter decodieren folgendes:
Eim gültiger String könnte mit einer Marke z.B. $ beginnen und mit einer
Marke enden. Parameter werden z.B. über ; abgetrennt. Der String um Port
A den Wert 0xff zuzuweisen könnte dann so aussehen $p;A;0xff$
Auf dem Microconroller liest Du die empfangenen Bytes solange ein, biss
ein $ -Zeichen kommt. Dann speicherst Du die darauffolgenden Zeichen,
bis ein ;-Zeichen kommt, ... bis das abschließende $-Zeichen kommt. Dann
rufst Du die Entsprechenden Funktionen auf.
Du brauchst letztlich eine Art Interpreter für eine Programmiersprache.
Da du mit einem ATmega2560 über relativ viel Platz verfügst, wäre
es eine Möglichkeit, einen ,,richtigen'' Scanner/Parser zu schreiben.
Dafür gibt es teilweise auch Werkzeuge. Die bekanntesten sind lex
und yacc. Für deren Opensource-Derivate flex und byacc könnte ich
dir Patches geben, mit denen man sie AVR-GCC-passend so verbiegt, dass
die relativ großen Tabellen, die für diese Werkzeuge typisch sind,
im Flash-ROM statt im SRAM abgelegt werden.
Exemplarisch habe ich damit mal einen einfachen BASIC-Interpreter
gezimmert, der aber mehr schlecht als recht funktioniert.
@Hans
So ungefähr habe ich das gemeint. Der Unterschied ist nur, dass der
String(also der Befehl), den ich an den µC sende, genau so aussehen
soll, wie die auszuführende Funktion im µC, z.B. SetPort(A, 0xF3);
Aber du hast wohl Recht. Ich werde vermutlich decodieren müssen.
Wenn Du natürlich die Möglichkeit hast einen Parser-Generator (yacc
etc.) zu verwenden ist das tausendmal besser, als die decodierung von
Hand zu machen.
Der von diesen Tools generierte Code ist in der Regel fehlerfrei (kommt
wirklich ganz ganz selten vor, dass man da 'nen Bug entdeckt). Bei von
Hand geschriebenem Code ist das - aus Erfahrung - ganz anders :-(
Vielleicht findest Du bei google ja schon eine fertige Grammatik für
Basic, Pascal, C, ... oder der Sprache in der Du die Befehle senden
möchtest.
Natürlich geben die Tools dann kein fertiges Programm aus. Ein bisschen
dazuprogrammieren muss man schon.
Jörg Wunsch wrote:
> Du brauchst letztlich eine Art Interpreter für eine Programmiersprache.>> Da du mit einem ATmega2560 über relativ viel Platz verfügst, wäre> es eine Möglichkeit, einen ,,richtigen'' Scanner/Parser zu schreiben.> Dafür gibt es teilweise auch Werkzeuge. Die bekanntesten sind lex> und yacc. Für deren Opensource-Derivate flex und byacc könnte ich> dir Patches geben, mit denen man sie AVR-GCC-passend so verbiegt, dass> die relativ großen Tabellen, die für diese Werkzeuge typisch sind,> im Flash-ROM statt im SRAM abgelegt werden.>> Exemplarisch habe ich damit mal einen einfachen BASIC-Interpreter> gezimmert, der aber mehr schlecht als recht funktioniert.
Hallo Jörg,
das Thema würde mich stark interessieren, das ich aus übertragenen
Funktelegrammen (mit Befehlen) Abläufe programmieren möchte. Kannst Du
mir bitte da mit Deinen Routinen helfen? Es geht nur um ein paar
Befehle. Wieviel Speicher verliere ich denn durch den Parser ?
Grüsse
Charly Grosse wrote:
> Kannst Du> mir bitte da mit Deinen Routinen helfen?
"Routinen" in dem Sinne habe ich nicht.
Ich hänge mal meine Patches für den flex-2.5.33 und byacc-20050813
an. Die originalen Quellen gibt's im Internet, die Patches schieben
die generierten Tabellen in den Flash-ROM und greifen mit pgm_read_...
darauf zu.
Folgende Optionen habe ich im flex-File noch genutzt (teilweise sind
diese notwendig, damit der Scanner überhaupt compilierbar wird):
%option noyywrap
%option always-interactive
%option case-insensitive
%option nounistd
> Es geht nur um ein paar> Befehle.
Dafür ist eine komplette formale Sprache sicher Overkill.
> Wieviel Speicher verliere ich denn durch den Parser ?
Verlieren wirst du keinen, denn er wird ja benutzt. ;-)
Das Ganze ist kein Leichtgewicht, aber für den ATmega256x des OPs
sicher nicht tragisch. Das ,,Grundrauschen'' einer derartigen
Scanner/Parser-Kombination ist recht hoch, ich erinnere mich an
ca. 12 KiB ROM-Verbrauch (der RAM-Verbrauch bleibt in Grenzen).
Der Vorteil ist nur, dass der Verbrauch für eine tatsächlich
implementierte Sprache dann nur ganz allmählich anwächst. Der
besagte BASIC-Interpreter hat es am Ende auf irgendwas um die 30 KiB
gebracht, aber das war mit kompletter Gleitkommaarithmetik und einer
einfachen Stringverarbeitung. Außerdem sind deartige Parser relativ
schnell.