Ich hatte eine kleine RS232 Console benötigt, einfach um eine Benutzer-Controller Schnittstelle zu bekommen. Für den Fall, das noch ein anderer so etwas gebrauchen kann, hab ich das ganze ins Wiki gestellt (UAC Mikrocontroller ASCII Console). Kurz die Features: -Kann auf beliebigen Controllern eingesetzt werden. -definierbarer New-Line-String und Prompt -Kommandozeilen Befehle können in die uAC "eingehangen" werden. -Beliebig viele Kommandos können eingetragen werden. -Befehle können beliebige Parameter empfangen (argc,args). -Implementierung einer mini-printf-variante (%i,%s,%c,%u) -Variabler Anpassung um einen Kompromiss zwischen Speicherplatz und Komfort zu finden Falls das ganze auf Interesse stößt kann ich es noch weiter ausbauen (Doku oder Programm). MfG
@Thomas Ich habs zwar noch nicht getestet aber der Sourcecode sieht schonmal sehr gut aus. Auch die Möglichkeiten die du eingebaut hast (History, Erkennung auf doppelten Historyeintrag usw) find ich gut. Einziges Manko (wie ich finde) : Du baust dir die Befehlsliste dynamisch auf, und das braucht eben sehr viel RAM. Kleiner Vorschlag dahingehend : Nimm einen Satz feste Befehle (die dann im FLASH definiert sind, und über pgm_read_byte o.ä. im StringCompare verglichen werden) und einen Satz dynamische Befehle. So bist du noch flexibel, kannst aber gleichzeitig bei immer gleich bleibenden Befehlen RAM einsparen. Wenn du nichts dagegen hast würd ich mir das ein oder andere bei dir Abgucken für meine uShell bzw meinen Parser. Ansonsten echt sehr schön gemacht. Weiter so. Gefällt mir (selbst wenn ich mir schon selbst ne Console zusammengeklöppelt habe :-))
Hallo Rene, freut mich dass dir der code etwas bringt. Natürlich kannst du ihn verwenden oder ausschlachten wie du möchtest. Ich habe nicht vor irgendeine Lizenz daran zu knüpfen. Zur Befehlsliste: Richtig dynamisch bau ich sie nicht zusammen. Die Befehle liegen in einem struct von fest definierter Länge. Jeder Eintrag benötigt nur 2 Zeiger (einen auf einen String und einen auf die auszuführende Funktion). Das sollten 4 Byte pro Befehl sein. Ich denke das ist verkraftbar. Nerviger ist da der Puffer für ausgehende Zeichen. Von dem pgm_read_byte habe ich bisher noch nie etwas gehört. So wie ich das verstehe kann man damit Bytes aus dem Flash lesen. Was genau soll denn dann im Flash liegen? Die Funktion selbst ist ja bereits da. So wie ich den Compiler (avr-gcc) verstanden habe, Belässt er Zeichenketten auch im Flash und speichert sie nicht zusätzlich im RAM ab. In der Befehlsliste kopiere ich mir ja auch nicht die Zeichenketten. Ich hol mir ja nur nen Zeiger darauf. MfG
Zeichenketten (und auch sonstige Daten) die ohne PROGMEM gekennzeichnet sind liegen im RAM (und logischerweise auch im Flash). Z.b. : char text1 [] = "string im flash und RAM"; char text2 [] PROGMEM = "string nur im flash"; Daher ist es sinnig pgm_read_xxx zu verwenden. Erschwert das ganze aber auch z.T. Aber bei dir würd ich in der Datenstruktur für die Befehle evtl ein Flag mit reinnehmen wo man unterscheidet ob es aus dem RAM oder dem Flash kommt. Das erlaubt dir einerseits feste Befehle, wie dynamische Befehle :-). Die Überprüfung bzw verwendeten Stellen können dann ja wahlweise mit pgm_read_byte arbeiten oder eben "normal" :-) Schau dir vllt auch mal meinen Parser an : Beitrag "uParse - die zweite."
Endlich hatte ich mal wieder etwas Zeit mich mit dem uAC Projekt zu beschäftigen: Ich hab eine neuere Version von uAC anzubieten. Es gab einen Bug bei der Zahlenausgabe, der ist jetzt behoben. Des Weiteren sind die Funktionen in Kleinbuchstaben umbenannt (ist sonst nervig). Außerdem kann die uac_print() jetzt auch float bzw. double. Das mit den Zeichenketten im Flash abspeichern verstehe ich irgendwie nicht. Hast du eine Literaturempfehlung. Ich habs auf der Seite von avr-gcc probiert bin dort aber nicht richtig fündig geworden. MfG Link: http://www.mikrocontroller.net/articles/UAC_Mikrocontroller_ASCII_Console
Schau mal hier im AVR-GCC Tutorial nach. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Speicherzugriffe Das Ausgangsproblem liegt darin : Der AVR hat eine Harvard-Architektur was bedeutet das der Programm und Datenspeicher über GETRENNTE Adress und Datenbusse angesprochen wird. Demnach kann man nicht wie in einem klassischen von Neumann System den gesamten Speicher linear durchadressieren, sprich das RAM und ROM (bzw Flash) im selben Speicher liegen. Dadurch benötigt man für Zugriffe auf den Programmpeicher spezielle Befehle. Wenn du in C programmierst werden Daten die nicht mit einem PROGMEM gekennzeichnet sind erst ins RAM kopiert. Danach kannst wie du es gewohnt bist darauf zugreifen. So "arbeitet" ein printf z.b. beim Formatstring NUR mit Daten aus dem RAM. Ein printf_P holt sich den Formatstring NUR aus dem Flash (wohlgemerkt nur den Formatstring). Da das RAM aber sehr schnell voll ist (gerade wenn man viele Zeichenketten, Tabellen oder sonstige Daten hat), ist es sinniger die fixen Daten (die sich ja nicht mehr ändern sollen zur Laufzeit) im Flash zu belassen und eben nicht erst ins RAM kopieren (zu lassen) und dann damit zu arbeiten. Und genau das bewirkt das PROGMEM. Ein Verhindern des Kopierens der Daten vom Flash ins RAM. Zugreifen kannst du dann nur (dadurch das es zwei völlig von einander unabhängige Speicher sind) über die pgm_read_xxx Funktionen bzw Funktionen mit dem Zusatz "_P". Hoffe ich habe es einigermaßen erklären können.
Alles klar. Ich hab mir das mal durchgelesen und habe erste Experimente positiv abgeschlossen. Mein Fehler beim ersten Mal war, das ich "static" nicht angegeben habe. Dadurch hatte es nicht funktioniert und ich dachte ich hätte etwas flasch verstanden. Ok, du schlägst also vor das user interface so zu gestalten, dass man quasi einmal eine uac_print() und einmal eine uac_print_flash() funktion definiert? Eine andere Variante hätte ich auch nicht auf lager. Man könnte höchstens ein define machen, dass entscheidet ob die uac_print() den string aus dem ram oder dem flash liest. Das hätte aber den Nachteil, dass im ganzen Programm nur eine Variante verfügbar wäre. Vielen Dank! Thomas
Jups. Das ist mein Vorschlag :-)) Bei einem printf machen auf einem AVR beide Funktionen (also den Formatstring aus dem RAM oder dem Flash zu benutzen) sinn. Bei Systemen die entweder von-Neumann-Architektur haben, oder aber in C transparent auf den Flash/RAM zugreifen können obwohl es getrennte Speicherbereiche sind wäre das nicht nötig. Vllt noch ne kleine Anregung für die Namensgebung : Häng bei der "Flash"-Funktion einfach ein _P an. Also das du "uac_print(f)" und "uac_print(f)_P" hast. Dann kann man ganz normal mit printf "runtertippen" und beim umstellen auf deinen uAC einfach ein uac_ vor jedem printf schreiben (ich gestehe ich würd es ohnehin über ein #define machen um nicht alle printf's ersetzen zu müssen :-)) Über ein define welches entscheidet ob du aus dem RAM oder Flash liest wäre in der tat nicht so gut. Vor allem wenn sich dein Formatstring ändert bzw du Text aus dem RAM ausgeben möchtest. Man kann dann zwar immer noch mit einem festen String "%s" arbeiten, aber es ist einfacher nur uac_printf (textimram) anzugeben als uac_printf (PSTR ("%s"), textimram).
Ok, ich habe deine Vorschläge alle berücksichtigt und sie in der Version 0.3 eingebaut: http://www.mikrocontroller.net/articles/UAC_Mikrocontroller_ASCII_Console Nochmals vielen Dank für deine Tips und Anregungen MfG Thomas
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.