Guten Tag an alle!
Ich möchte über Terminal und RS232 aus mehreren Zeichen bestehende
Befehle an einen µC schicken und im µC die Befehle mit der Software
erkennen und ausführen. Ich habe mir überlegt, wie die Software zum
Erkennen der Befehle aufgebaut werden soll und zeige nachfolgend meine
Überlegungen und möchte euch um eure Meinungen (ob gut oder schlecht)
oder evtl. Vorschläge (wie besser) bitten.
Alle vorkommenden Befehle werden in dieser Form abgelegt:
1
typedefcharCmdString[5];
2
CmdStringCmdList[]={"befehl1\n",
3
"befehl2\n",
4
"befehl3\n"};
Die vom Uart empfangenen Zeichen werden in einem Puffer solange
abgelegt, bis ein Return-Zeichen kommt. Bei Return wird der
Puffer-Inhalt Zeichen für Zeichen mit dem ersten Befehl CmdList[1]
verglichen. Wenn keine Übereinstimmung mit dem 1. Befehl besteht,
erfolgt der Vergleich mit dem 2. Befehl und so weiter. Stimmt der
Puffer-Inhalt mit einem der Befehle aus CmdList überein, wird eine
Varible mit einem Wert aus einer enum-Liste gesetzt und dann wird in
einer switch-case-Struktur je nach Befehl der zugehörige Code
ausgeführt. Ist der Puffer-Inhalt mit keinem der abgelegten Befehle
übereinstimmend, wird eine Meldung ausgegeben.
Ist es sinnvoll, das so wie beschrieben zu machen. Oder habt ihr bessere
Konzepte vorzuschlagen? Vielleicht gibt es so etwas ähnliches irgend wo
schon fertig, das wäre natürlich ideal.
Ich danke für jeden Beitrag im Voraus!!!
Schau dir dazu mal die Funktion strstr und strtok. Du musst auch immer
davon ausgehen, dass man sich mal verschreibt, Groß/Kleinschreibung
nicht beachtet oder ein return nicht kommt. Deswegen lieber nicht jedes
Zeichen miteinander vergleichen (also nicht strcmp).
So kann man das schon machen, die Trennung aus Empfang von Zeichen und
der Verarbeitung empfangener Zeichenketten ist schon mal ein sinnvoller
Ansatz.
Du könntest allerdings Deine Datenstrukturen und die Decodierung
vereinfachen; wenn Du einen Strukturtyp vereinbarst, der die zu
erkennende Zeichenkette und einen Funktionspointer enthält, kannst Du
gleich nach dem Vergleich der Zeichenketten die Funktion aufrufen, ohne
den Umweg über einen enum und eine switch-case-Kette gehen zu müssen.
Den typedef schmeisst du am besten gleich wieder raus. Vor allen Dingen
deshalb, weil deine jetzigen Command-Strings schon länger als 4 Zeichen
sind. Und den \n braucht es auch nicht wirklich in der Befehlsliste.
Deine Empfangsroutine weiß wann eine Zeile zu Ende ist und gibt dir das
Empfangene in Form einer Zeile. Den \n braucht da niemand wirklich im
String. Wenn ihn die Empfangsroutine gleich rauswirft
* sparst du Speicher
* musst dich im weiteren auch nicht darum kümmern, ob der Sender
ein \n alleine, oder ein \r alleine, oder \r\n oder \n\r
gesendet hat.
1
constchar*CmdList={"befehl1",
2
"befehl2",
3
};
> erfolgt der Vergleich mit dem 2. Befehl und so weiter. Stimmt der> Puffer-Inhalt mit einem der Befehle aus CmdList überein, wird eine> Varible mit einem Wert aus einer enum-Liste gesetzt und dann wird in> einer switch-case-Struktur je nach Befehl der zugehörige Code> ausgeführt.
Den Umweg über einen enum braucht es nicht wirklich. Warum rufst du
nicht gleich bei Erkennen des Strings, nach dem strcmp, die
entsprechende Funktion auf?
> Ist es sinnvoll, das so wie beschrieben zu machen. Oder habt ihr bessere> Konzepte vorzuschlagen?
Sicher: Funktionspointer
http://www.mikrocontroller.net/articles/FAQ#Funktionszeiger
>Schau dir dazu mal die Funktion strstr und strtok. Du musst auch immer>davon ausgehen, dass man sich mal verschreibt, Groß/Kleinschreibung>nicht beachtet oder ein return nicht kommt. Deswegen lieber nicht jedes>Zeichen miteinander vergleichen (also nicht strcmp).
Ich bin ziemlich unerfahren im Programmieren und kenne die wenigsten
fertigen Funktionen. strcmp ist mir auch unbekannt, ich würde alles "zu
Fuß" programmieren. Darum bitte ich auch um Hinweise, welche fetige
Funktionen man in diesem Fall verwenden könnte ( wenn möglich mit der
Quellbibliothek).
Wie wäre es mit einem guten Buch und erst mal ein oder zwei gemütliche
Leseabende.
Merke: Wissen ist nicht durch Nichtwissen zu ersetzen.
Ausser vieleicht in der Finanzbranche und im Management. Da muss man nur
einen Sündenbock finden, laut jammern und trotzdem Boni kassieren.
Ein totaler Anfänger bin ich nicht. Ich habe 2 Semester Informatik aus
dem Studium und einiges aus Praxissemester und Übungen. Ein C-Buch habe
ich eigentlich schon. Das sehe ich schon ein, dass ich wissen sollte
welche Mittel mir die Standard-Bibl. bietet. Wie empfohlen, werde ich
mir demnächst mal ein Bild machen, was es alles für Funktionen gibt. Es
soll hier erst nur um Konzept gehen.
>Den typedef schmeisst du am besten gleich wieder raus. Vor allen Dingen>deshalb, weil deine jetzigen Command-Strings schon länger als 4 Zeichen>sind. Und den \n braucht es auch nicht wirklich in der Befehlsliste.>Deine Empfangsroutine weiß wann eine Zeile zu Ende ist und gibt dir das>Empfangene in Form einer Zeile. Den \n braucht da niemand wirklich im>String. Wenn ihn die Empfangsroutine gleich rauswirft> * sparst du Speicher> * musst dich im weiteren auch nicht darum kümmern, ob der Sender> ein \n alleine, oder ein \r alleine, oder \r\n oder \n\r> gesendet hat.>
1
>constchar*CmdList={"befehl1",
2
>"befehl2",
3
>};
Die Länge des definierten Typs würde ich dann schon richtig anpassen.
Was mir nicht klar ist, wie halte ich bei der vorgeschlagenen Liste die
Befehle auseinander. Sie können ja aus unterschiedlicher Anzahl an
Zeichen bestehen. Den \n habe ich deshalb angehängt, damit ich weiß wann
ein Befehl zu Ende ist. Es kann möglicherweise die Befehle "gpa" und
"gpad" geben und ich daran ob ein \n am Ende ist, würde ich erkennen ob
der Befehl aus der Liste weiter geht oder schon zu Ende ist. Der Sender
sendet am Ende des Befehls immer nur CR (ASCII-Wert 13) und den \n würde
ich dem gesendeten empfangenen Befehl vor dem Vergleich noch dranhängen.
Wie weiß die Empfangsroutine, wann eine Zeile zu Ende ist?
Beim Empfangen kannst du natürlich das Ende an \n oder so
einem Zeichen (Leerzeichen etc.) prima erkennen.
Aber dann muß man es nicht mehr speichern und vergleichen.
Wenn es auf Dauer etliche Befehle werden, würde ich nebenbei
wie schon empfohlen je Befehl eine struct mit Funktionszeiger
machen, alle solchen structs in einem sortierten Feld halten
und mit bsearch nach dem richtigen fahnden.
Dadurch muß nicht jedesmal die ganze Liste anageklappert werden
und die Suche geht deutlich schneller.
(Gleich vorweg: bsearch() braucht nur wenige Byte Code.)
noips schrieb:
> Ein totaler Anfänger bin ich nicht. Ich habe 2 Semester Informatik aus> dem Studium und einiges aus Praxissemester und Übungen. Ein C-Buch habe> ich eigentlich schon.
Dann solltest du darin auch mal schmökern.
Ich hab für vieles Verständnis, aber ich hab kein Verständnis dafür ein
C-Buch zu besitzen und die Familie der str... Funktionen nicht zu
kennen. Gleich nach dem Kapitel über Arrays gehts meistens in den
Büchern mit Strings weiter und ab dann werden gerade die str...
Funktionen bis zum Exzess eingesetzt.
>>const char* CmdList = { "befehl1",>> "befehl2",>> };[/c]>> Die Länge des definierten Typs würde ich dann schon richtig anpassen.
Lass das den Compiler machen. Der macht das zuverlässiger.
Und da du die Strings nicht verändern willst, reicht es völlig aus, wenn
du dir ein Array von Pointern auf die (konstanten) Strings einrichtest.
> Was mir nicht klar ist, wie halte ich bei der vorgeschlagenen Liste die> Befehle auseinander.
Jeder Pointer im Array zeigt auf einen String.
> Sie können ja aus unterschiedlicher Anzahl an> Zeichen bestehen. Den \n habe ich deshalb angehängt, damit ich weiß wann> ein Befehl zu Ende ist.
Jeder String in C hat IMMER ein \0 Zeichen am Ende! Daran wird das Ende
eines Strings erkannt. Das ist C-Konvention und du solltest dich
unbedingt daran halten und nicht dein eigenes Süppchen kochen. Eine
Abfolge von Zeichen die mit einem \0 Zeichen aufhört, ist in C per
Definition ein String.
Schreibst du also selber Zeichen in ein Array, so ist das solange kein
String, solange du die Abfolge der Zeichen nicht mit einem \0
abschliesst.
Aber das ist auch alles in dem Link über Stringverarbeitung enthalten,
den ich dir weiter oben gegeben habe. Allerdings: Dort findest du nur
das absolut Notwendigste zum Thema Stringverarbeitung.
> Es kann möglicherweise die Befehle "gpa" und> "gpad" geben und ich daran ob ein \n am Ende ist,
1
charbuffer[]="gpa";
2
3
if(strcmp(buffer,"gpa")==0)
4
// gpa wurde erkannt
5
6
elseif(strcmp(buffer,"gpad")==0)
7
// gpad wurde erkannt
> würde ich erkennen ob> der Befehl aus der Liste weiter geht oder schon zu Ende ist.
Pack dir einen C-Compiler auf deinen PC, nimm dein C-Buch und arbeite
die ersten paar Kapitel durch!
> Der Sender> sendet am Ende des Befehls immer nur CR (ASCII-Wert 13) und den \n würde> ich dem gesendeten empfangenen Befehl vor dem Vergleich noch dranhängen.>> Wie weiß die Empfangsroutine, wann eine Zeile zu Ende ist?
Wenn das Zeichen \n empfangen wurde?
@ Klaus Wachtler
>Beim Empfangen kannst du natürlich das Ende an \n oder so>einem Zeichen (Leerzeichen etc.) prima erkennen.>Aber dann muß man es nicht mehr speichern und vergleichen.
Durch \n will das Ende des Befehls nicht beim Emfangen erkennen sondern
beim Vergeleichen. Beim Emfangen erkenne ich das Ende der Befehlseingabe
am Carriage Return.
Warum muss man es dann nicht mehr speichern und vergleichen? Was meinst
du damit?
noips schrieb:
> @ Klaus Wachtler>>>Beim Empfangen kannst du natürlich das Ende an \n oder so>>einem Zeichen (Leerzeichen etc.) prima erkennen.>>Aber dann muß man es nicht mehr speichern und vergleichen.>> Durch \n will das Ende des Befehls nicht beim Emfangen erkennen sondern> beim Vergeleichen.
N E I N
Lies es von meinen Lippen, äh Tastendrücken ab:
Ein String wird mit einem \0 beendet.
Immer? Immer!
> Beim Emfangen erkenne ich das Ende der Befehlseingabe> am Carriage Return.
\n ist die C-Schreibweise für Carriage Return!
> Warum muss man es dann nicht mehr speichern und vergleichen?
Weil deine Zeile laut deiner Definition sowieso hinten dann immer einen
\n hat. Deine Befehle in der Befehlsliste haben hinten auch einen \n.
D.h. das letzte Zeichen stimmt in jedem Fall überein! Das muss man daher
auch nicht testen. Was man aber nicht testen muss, muss man auch nicht
speichern.
Bist du sicher, dass du Informatik studierst?
>Bist du sicher, dass du Informatik studierst?
Oh, Entschuldigung, ich habe mich weiter oben falsch ausgedrückt. Ich
wollte sagen, dass ich in meinem Studium (Elektrotechnik) 2 Semester
lang die Vorlesungen zu Informatik gehört und die Prüfungen bestanden
habe.
>\n ist die C-Schreibweise für Carriage Return!
\n ist nach meinem Wissen die Schreibweise für ASCII-Wert 000 und
Carriage Return hat den ASCII-Wert 013! Oder sehe ich da was falsch?
There are a few characters which can indicate a new line. The usual ones
are these two:
* '\n' or '0x0A' (10 in decimal) -> This character is called "Line
Feed" (LF).
* '\r' or '0x0D' (13 in decimal) -> This one is called "Carriage
return" (CR).
Different Operating Systems handle newlines in a different way. Here is
a short list of the most common ones:
* DOS and Windows
They expect a newline to be the combination of two characters,
namely '\r\n' (or 13 followed by 10).
* Unix (and hence Linux as well)
Unix uses a single '\n' to indicate a new line.
* Mac
Macs use a single '\r'.
noips schrieb:
>>\n ist die C-Schreibweise für Carriage Return!>> \n ist nach meinem Wissen die Schreibweise für ASCII-Wert 000 und> Carriage Return hat den ASCII-Wert 013! Oder sehe ich da was falsch?
Du siehst das falsch!
\0 ist die Schreibweise für das Zeichen mit dem ASCII Wert 0
\n ist genau genommen LineFeed und
\r ist genau genommen Carriage Return
Aber in den meisten Fällen kommt man damit durch, dass man bei der
Ausgabe über die Standard Ausgabefunktionen nur \n ausgeben muss bzw.
bei der Eingabe über die Standardfunktionen nur auf \n prüfen muss. Die
Standardfunktionen setzen \n dann auf die Form um, der auf dem konkreten
System üblich ist ( nur \n, nur \r, \r\n). Lediglich dann, wenn
Ein/Ausgabe an den Standardfunktionen vorbeilaufen, muss man auf diese
Feinheiten achten.
Schön langsam solltest auch du erkennen, dass deine Lücken so dermassen
gross sind, dass du UNBEDINGT als Allererstes dein Buch zur Hand nehmen
solltest.
>Schön langsam solltest auch du erkennen, dass deine Lücken so dermassen>gross sind, dass du UNBEDINGT als Allererstes dein Buch zur Hand nehmen>solltest.
Hm.. Schön langsam erkenne ich es auch!
>Pack dir einen C-Compiler auf deinen PC, nimm dein C-Buch und arbeite>die ersten paar Kapitel durch!
Gern! Könntest du mir einen C-Compiler empfehlen?
noips schrieb:
> Es ist ja nicht so, dass ich das ganze ohne auszuprobieren mache. Ich> programmiere in AVR-Studio.AVR-Studio hilft dir da nicht viel, weil du die Programme nicht auf dem
PC laufen lassen kannst. Dadurch wird erst einmal das Debuggen des
Programms erschwert.
Grundlagen in C lassen sich am besten auf dem PC lernen. Da
funktionieren erst einmal alle Programme aus deinem Buch ohne
Änderungen. Die Ein/Ausgabe ist soweit eingerichtet, dass alles was du
per printf ausgibst, auf der Konsole landet. Und das ist für die ersten
Schritte ein mehr als nur dicker Plus-Punkt. Bei einem AVR muss man da
selber Hand anlegen und schon definitiv wissen was man tut, ehe ein
printf über die serielle Schnittstelle oder auf einem LCD ausgeben kann.
Um die Grundlagen C zu lernen kannstdu im Prinzip jeden Compiler nehmen.
Die Unterschiede sind da eher in der IDE zu suchen. Aber die Fähigkeiten
C Quelltext in ausführbare Programme korrekt umzusetzen, beherrschen die
alle aus dem efef
Empfehlen kann ich dir keinen, weil ich seit Jahren auf die Microsoft
Compiler angewiesen bin. Von MS gibts auch eine kostenlose Version. Auch
den gcc gibts in unterschiedliche Pakete eingepackt als freien Compiler.
>Grundlagen in C lassen sich am besten auf dem PC lernen.
Das habe ich mir auch gedacht. Allerdings muss ich die Grundlagen nicht
neu lernen. Ich muss meine Lücken schließen und das Wissen erfrischen.
Gibt es einen Freeware C-Compiler, den man zum lernen am PC verwenden
könnte?
Hallo nochmals!
Ich habe mir jetzt die String-Funktionen aus der Standard Library
angeschaut und mit dem Visual Studio C++ Exspress ausprobiert.
Dann habe ich ein Programm im Visual Studion geschrieben, in dem ich
Befehle mit scanf einlese, mit den Befehlen aus einer Liste vergleiche
und bei Erkennung den entspr. Befehl ausführe. Die Ausführung besteht
dabei nur aus der Ausgabe vom Text in der Konsole mit printf. Die
Auswertung und Ausführung mache ich wie von euch weiter oben empfohlen.
Das ging im VS auch einwandfrei.
Nun habe ich dieses Programm für den µC angepasst. Statt printf benutze
ich da die Funktion vSendText. Das Einlesen geht so:
Zeichen vom Terminal werden vom UART (per Interrupt) solange im
caCmdBuffer gepuffert, bis Eingabetaste kommt. Nach Eingabetaste wird
eine Flag-Variable gesetzt, worauf im Hauptprogramm die Auswertung des
Puffers und Ausführung des Befehls erfolgt.
Beim Compilieren wird aber ein Linker Error gemeldet:
undefined first referenced
symbol in file
--------- ----------------
vSentText ./SPI_master.obj
Ich sitze schon längere Zeit und komme nicht drauf, was falsch ist! Drum
bitte ich um eure Hilfe, falls jemand sich das anschauen möchte. Danke
im Voraus für eure Hinweise!!!
1
#include"msp430x54x.h"
2
#include"SPI_master.h"
3
#include"stdint.h"
4
#include"string.h"
5
6
#define STRINGSIZE 15 // max. size of the input variable
noips schrieb:
> Ich sitze schon längere Zeit und komme nicht drauf, was falsch ist!
Steht doch da
symbol in file
--------- ----------------
vSentText ./SPI_master.obj
Gesucht wird die Funktion SentText (mit einem harten t)
Deine Funktion heißt aber SendText (mit einem weichen d)
PS:
>Beim Compilieren wird aber ein Linker Error gemeldet:
Das ist ein Widerspruch in sich.
Compilieren und Linken sind 2 verschiedene Dinge
Compilieren: Übersetzen der Einzelteile in Maschinensprache
Linken: Zusammenfügen der übersetzten Einzelteil zum
kompletten Programm
Wenn du daher beim Linken einen Fehler hast, dann ist das kein
C-Syntaxfehler mehr (den hätte der Compiler gefunden) sondern du benutzt
einen Namen, den es so nicht gibt. Oft ist das einfach nur ein
Tippfehler, Zeichendreher etc.
-> Den Namen, den der Linker anmäkelt genau ansehen und auf derartige
Flüchtigkeitsfehler absuchen.
Es fällt mir jetzt noch auf, dass ich vergessen habe, die innere
while(1)-Schleife zu entfernen. Außerdem muss ich natürlich noch die
Flag-Variable und den Buffer-Pointer rücksetzen. Aber das wirkt sich
nicht auf den gemeldeten Linker-Fehler aus.
Uuups! So peinlich! Ich vermute den Fehler in fehlenden Prototypen, in
falscher Parameterübergabe und sonstiges, und der Steckt in einem
einfachen Tipp-Fehler. Besten Dank für den Hinweis!!
Mit dem Compilieren und Linken wusste ich eigentlich schon, dass das
nicht dasselbe ist. Nur habe ich keinen Begriff gefunden, mit dem man
beides verbinden kann. Das was in der IDE "Build" heißt.
Vielen Dank!
Weil die solchen zumindest sprachlich d und t nicht
auseinanderhalten, ebensowenig wie b und B.
Beim Sprechen ist das jeweils exakt gleich.
Beim Buchstabieren hört sich das dann so an:
"A wie Anton, weiches b wie Bertha, hartes b wie Baula,
d wie Dora, d wie Deodor,..."
(siehe Antwort von KHB:
> ...mit einem harten t...mit einem weichen d...
, das liest sich auch eher süddeutsch).
In Norddeutschland habe ich noch niemandem beim Buchstabieren
von hart und weich reden hören, da hört man es schon beim
Sprechen von d oder t, was gemeint ist.
Wäre jetzt interessant, wenn sich das auch aufs Schreiben
auswirkt: SentText <> SendText.
noips schrieb:
> Uuups! So peinlich! Ich vermute den Fehler in fehlenden Prototypen,...
Naja letztlich schon.
Wenn du beim Kompilieren die Warnungen einschaltest und auch
beachtest und beispielsweise vSendText deklarierst, aber
einmal versehentlich vSentText aufrufst, wird dir jeder
vernünftige Compiler dann eine Warnung ausgeben von wegen
irgendwas undeclared.
Verschreiben ist nicht peinlich, Warnungen ignorieren schon :-)
>Naja letztlich schon.>Wenn du beim Kompilieren die Warnungen einschaltest und auch>beachtest und beispielsweise vSendText deklarierst, aber>einmal versehentlich vSentText aufrufst, wird dir jeder>vernünftige Compiler dann eine Warnung ausgeben von wegen>irgendwas undeclared.>>Verschreiben ist nicht peinlich, Warnungen ignorieren schon :-)
Hmm... hier hat der Compiler keine Warnung gebracht! Meistens schaue ich
mir die Warnungen auch an. Spätestens wenn ich vor so einem Problem
stehe wie dieses Mal. Und mit dem Aktivieren muss ich mir noch
anschauen, was sich da Einstellen lässt.
Was das Verschreiben und meine Herkunft angeht: Ich wohne seit 1996 in
Südbayern, Augsburger Gegend, bin ursprünglich aber Russlandsdeutscher.
In der Schule habe ich auch schon änhliche Fehler gehabt. Hab z.B. statt
Mord Mort geschrieben, obwohl ich wusste wie es richtig geschrieben
wird.
Habe jetzt ein Problem in einem Unterprogramm (Auszug unten). Der Aufruf
von sscanf bewirkt irgendwie gar nichts in diesem Unterprogramm. D. h.
wenn ich im Debugger diese Zeile ausführe, ändert sich der Inhalt der
Variable iOut nicht. Dagegen funktioniert bei dem gleichen Code im
Hauptprogramm alles wie erwartet. Ich habe vermutet, dass es an den
Optimazer-Einstellungen liegen könnte. Die Änderungen an den
Einstellungen hat aber auch nichts gebracht. Weiß vielleicht jemand,
woran dieses Problem liegt? Programmiert wird ein MSP430 mit CCE von
Texas Instruments.
noips schrieb:
> Habe jetzt ein Problem in einem Unterprogramm (Auszug unten). Der Aufruf> von sscanf bewirkt irgendwie gar nichts in diesem Unterprogramm. D. h.> wenn ich im Debugger diese Zeile ausführe, ändert sich der Inhalt der> Variable iOut nicht.
Lass dir doch mal caCmdBuffer ausgeben, damit du siehst, ob da überhaupt
das drinnen steht, was deiner Meinung nach drinnen stehen sollte. Ich
wette, dass da nichts für sscanf verwertbares enthalten ist.
Bei der Fehlersuche immer vorne anfangen. Als erstes werden die Eingaben
überprüft, dann die Verarbeitung. Nichts als gegeben annehmen, alles in
Frage stellen und sei es noch so trivial.
Also:
>Lass dir doch mal caCmdBuffer ausgeben, damit du siehst, ob da überhaupt>das drinnen steht, was deiner Meinung nach drinnen stehen sollte. Ich>wette, dass da nichts für sscanf verwertbares enthalten ist.
Danke für den Rat! Das hat mich ein Stück weiter gebracht. In
caCmdBuffer stand auch tatsächlich das, was ich an sscanf weitergeben
wollte. Ich sehe das im Watch-Fensters des Debuggers. Aber aus irgend
einem Grund wurde bei der Übergabe von caCmdBuffer als Parameter nicht
die richtige Adresse übergeben. Bei diesem Code
vSendText(caCmdBuffer);// caCmdBuffer wird falsch übergeben
8
sscanf(caCmdBuffer,"%x",&iOut);
9
sprintf(temp,"%i",iOut);
10
vSendText(temp);
bewirkte die Zeile vSendText(caCmdBuffer); die Ausgabe "Ausgangswerte
eingeben (hexadezimal):" von weiter oben. Warum, ist mir ein Rätsel!
Dagegen bei diesem Code
geht alles wie erwartet. Außerdem wenn man den ersten Code (in diesem
Posting) im Hauptprogramm hatte ging alles auch wie erwartet. Das würde
mich interessieren, was der Grund ist?
>vSendText(caCmdBuffer);// caCmdBuffer wird falsch übergeben
8
>sscanf(caCmdBuffer,"%x",&iOut);
9
>sprintf(temp,"%i",iOut);
10
>vSendText(temp);
11
>
> bewirkte die Zeile vSendText(caCmdBuffer); die Ausgabe "Ausgangswerte> eingeben (hexadezimal):" von weiter oben.
D.h. du siehst den Text dann 2-mal auf deiner Ausgabe?
1
Ausgangswerte eingeben (hexadezimal):
2
123 <- Hier gibts du ein
3
Ausgangswerte eingeben (hexadezimal):
4
0 <- Das kommt dann vom sprintf
> Warum, ist mir ein Rätsel!
Da geht irgendwas grauslich schief.
Kompletten Code herzeigen
Jetzt geht alles! Ich habe alle Break-Pointer entfernt und das Programm
einfach ununterbrochen laufen lassen, und jetzt geht alles auch mit der
1. Code-Variante. Wahrscheinlich gab es wegen dem Anhalten der
Codeausführung durch Debugger Probleme in der Kommunikation mit Terminal
per UART.
Wenn du den Code aber trotzdem anschauen willst:
1
#include"msp430x54x.h" // Standard Definition Control Register
2
#include"SPI_master.h"
3
#include"stdint.h"
4
#include"string.h"
5
#include"stdio.h"
6
7
#define STRINGSIZE 15 // max. size of the input variable
... um
Du willst zuerst warten ob die USART bereit ist und erst dann das
Zeichen los werden.
1
//
2
// transmit string via RS232
3
//
4
voidvSendText(constchar*Text)
5
{
6
while(*Text!='\0')
7
{
8
// USCI_A1 TX buffer ready?
9
while(!(UCA1IFG&UCTXIFG))
10
;
11
12
UCA1TXBUF=*Text++;
13
}
14
}
Auch solltest du an deinen Codeformatierungen arbeiten. Insbesondere
konsistente Formatierung bei { } Blöcken und Einrückungen.
So etwas
1
voidvResEeprom(void){vSendText("ResEeprom\r");
2
}
geht gar nicht. Jetzt ist dein Programm noch klein und überschaubar.
Aber wenn es wächst, wirst du dir mit inkonsistenter Formatierung immer
wieder selbst ein Bein stellen.
Aus Speicherplatzgründen wäre es auch besser, die konstanten
Zeichenketten (die Befehle) mit progmem zu verlagern.
Also in der Form:
static const char entry1[] PROGMEM = "send_pb";
in der Struktur schreibst du dann
struct sCmd sCmdList[] = {
{entry1 , vSendProfibus},
};
wobei diese eigentlich auch konstant ist und ausgelagert werden kann.