Hallo zusammen,
zur Zeit versuche ich eine RS232 Verbindung zwischen einem
PIC-µConrtroller (PIC18F450) und einem PC (WinXP) aufzubauen.
Es ist mir gelungen, den µController mit dem PC zu verbinden und ein
µController-Programm zum Senden und Empfangen von Daten zu schreiben.
Verbunden mit dem WinXP Hyperterminal funktioniert sowohl senden, als
auch empfangen wunderbar.
Letztlich soll der µController jedoch mit einem C++ Programm
kommunizieren. Dieses C++ Programm habe ich auf Basis von Anton Zechners
"ComTools" aufgebaut und die Kommunikation mit einem anderen PC (wieder
zum Hyperterminal) getestet. Auch hier funktioniert das Senden und
Empfangen zwischen C++ Programm und Hyperterminal einwandfrei.
Jetzt meine Frage: Verbinde ich nun C++ Programm und µController, so
scheint irgendetwas schief zu gehen. Jedenfalls kommt keine
ordnungsgemäß laufende Verbindung zu Stande.
Zu Testzwecken sendet das C++ Programm in einer Endlosschleife einen
String und der µController soll nach erfolgreichem Empfang seinerseits
ebenfalls einen definierten String zurücksenden. - Wie gesagt, mit dem
Hyperterminal als Gegenstück funktionieren beide Programme genauso, wie
sie es sollen....
Für die Kommunikation habe ich folgende Parameter ausgewählt:
- Bautrate 19200
- kein Paritätsbit
- 1 Stoppbit
- keine Flusssteuerung
Hat vielleicht jemand eine kluge Idee, woran es liegen könnte, dass
µController und C++ Programm nicht miteinander kommunizieren möchten?
Dank euch!
Christian
Möglicherweise "überfährst" Du Deinen µC, d.h. Du sendest ihm Daten
schneller, als er sie verarbeiten kann. Damit meine ich nicht die
Baudrate, sondern die (fehlende) Zeit zwischen einzelnen Zeichen bzw.
zwischen den einzelnen übertragenen Strings.
Möglicherweise zickt dein C++ Programm bzw. die C++-Library am
andersartigen Zeilenende rum auf das dein µC-Programm anders
Hyperterminal sendet. Würde man den Sourcecode sehen, bräuchte man nicht
raten...
Christian schrieb:> Letztlich soll der µController jedoch mit einem C++ Programm>> kommunizieren. Dieses C++ Programm habe ich auf Basis von Anton Zechners>> "ComTools" aufgebaut und die Kommunikation mit einem anderen PC (wieder>> zum Hyperterminal) getestet.
Aus diesem Satz schließe ich, dass die ComTools auf dem µC keinen
Programmcode erzeugen, der in der Lage ist, Zeichenketten zu erkennen
und bei Übereinstimmung, eine vorher festgelegte Aktions zu starten. Das
könnte das das Senden eines Antwortstrings sein.
Sehe ich das richtig?
Sendet dein puts ein Zeilenende mit?
Hast du eine 3-Draht-Verbindung oder eine Verbindung mit zusätzlicher
DTR/RTS Beschlaltung. Ich habe ComTools im Netz gefunden, die ein
CreateFile machen mit:
Wenn das gets hier
gets(_4recive);
auch nur ansatzweise wie ein normales gets funktioniert, dann wartet es
auf ein Carriage Return von der Gegenstelle, welches aber
iKey[0] = 't'; iKey[1] = 't'; iKey[2] = 't'; iKey[3] = 't';
ComWrite(COM1, iKey, 4);
niemals gesendet wird.
Und PS: du solltest dir in deinem C-Buch das Kapitel über Strings
nochmal durchlesen. Man kann, man muss aber nicht bei Strings ständig
auf Einzelzeichenebene rumkriechen.
Und noch ein 2.tes PS:
gets ist eine extrem gefährliche Funktion, deren Verwendung bei
Prügelstrafe verboten werden sollte.
Danke für eure Denkansätze! Ich habe das Problem nochmal ein wenig
untersucht und es scheint tatsächlich am carriage return zu liegen.
Ich habe nun in meinem C++ Programm die "Sendezeile" überarbeitet:
ComWrite(COM2, "test\r\n\0", 7);
Lasse ich nun zwei Instanzen von diesem Programm auf zwei Rechnern
miteinander kommunizieren, dann funktioniert das einwandfrei. Auch ein
carriage return scheint nun richtig implementiert zu sein.
Die Kommunikation mit dem µController funktioniert allerdings weiterhin
nicht!! :(
Grüß euch,
Christian
PS: Es mag durchaus sein, dass puts() keine gute Wahl ist. Ich bin kein
Informatiker und habe im Grunde genommen auch keine richtige Ahnung...
Was wäre denn eine bessere Wahl anstatt Puts() und Gets()????
> ComWrite(COM2, "test\r\n\0", 7);
Wozu das \0 Byte?
Ein direkt angegebener String ist sowieso immer automatisch mit einem \0
Byte abgeschlossen. Das macht der Compiler. Und das \0 Byte brauchst du
auch nicht zu übertragen.
Hast du auf dem µC neben der UART noch eine andere Möglichkeit um dir
irgendetwas ausgeben zu lassen? Zb ein LCD?
Wenn ja, dann vereinfache mal dein Empfängerprogramm. Schmeiss alles
raus, was du nicht brauchst und was das Programm nur in die Länge zieht.
Empfange eine Zeile und gibt sie am LCD aus. Die Devise heißt: Möglichst
wenig, was schief gehen kann. Bei dir können momentan 2 Dinge schief
gehen:
a) die Übertragung einer Text-Zeile vom PC zum µC
b) die Übertragung einer Text-Zeile vom µC zum PC
in einem von beiden steckt ein Problem und du weißt nicht in welchem.
Also musst du einen der beiden Problemkreise loswerden, damit ein
möglicher Fehlerfall wegfällt
(PS:
Woher weiß eigentlich das PC-Programm hier
cout << "GetComReadCount:" << ComGetReadCount(COM1) << endl << endl;
iLen=ComRead(COM1,cBuffer,64);
wann es eine Zeile empfangen hat?
Das wird so nicht funktionieren.
Wenn du zeilenweise überträgst, was ich dir sehr ans Herz legen würde,
dann musst du vom µC auch eine Zeile wegschicken.
puts("RECIVED1\n");
Jetzt ist es eine Zeile und du kannst am PC anhand des \n feststellen,
dass du eine Zeile bekommen hast.
> Es mag durchaus sein, dass puts() keine gute Wahl ist.
puts() ist nicht das Problem. gets() ist das Problem!
Beantworte doch einfach mal die Frage, wie dich gets() davor schützen
soll, dass die Gegenstelle mittels eines langen Strings deinen
char-Buffer überläuft? Dazu müsste gets() wissen, wie gross der Buffer
ist. Das geht aber mit der Schnittstelle nicht, gets hat keine Chance
das rauszufinden. Daher ist gets() eine 'Funktiona non grata'. fgets ist
besser.
Aber lass das erst mal. Deine Problem liegen noch viel einfacher. Erst
mal sieh zu, dass du die Kommunkation generell hinkriegst.
Wenn du kein LCD oder sowas hast, dann mach dein erstes Testprogramm so
einfach wie möglich. zb so
1
intmain()
2
{
3
charreceived[80];
4
5
....
6
7
while(1)
8
{
9
gets(received);
10
// ideal wäre es hier, wenn du eine LED toggeln könntest oder
11
// irgendwas anderes machen könntest, was dir zweifelsfrei mitteilt:
12
// gets hat eine Zeile geliefert
13
puts("*");
14
puts(received);
15
puts("*\n");
16
}
17
}
Also einfach nur zurückschicken.
Das testest du erst mal mit Hyperterminal und dann mit deinem
PC-Programm.
Wenns nicht funktioniert, dann konzentrierst du dich erst mal nur auf
dein PC-Programm. Das µC Programm ist einfach genug, dass da nicht viel
schief gehen kann. Solange deine Kontrolle durch zb eine LED mitteilt,
dass gets mit einem String zurückgekommen ist, ist µC seitig soweit
alles in Butter.
Und noch was
> Woher weiß eigentlich das PC-Programm hier>> cout << "GetComReadCount:" << ComGetReadCount(COM1) << endl << endl;> iLen=ComRead(COM1,cBuffer,64);>> wann es eine Zeile empfangen hat?> Das wird so nicht funktionieren.
Du scheinst hier anzunehmen, dass die ComTools irgendwie magisch wissen,
wann ein Text, den du vom µC mittels
puts("no match");
auf den Weg schickst, komplett übertragen wurde.
Das tun sie aber nicht!
Ein Computer kann nicht in die Zukunft schauen, ob da von der
Schnittstelle noch was kommen wird oder nicht.
ComGetReadCount(COM1) sagt dir, wieviele Zeichen bisher eingetrudelt
sind. Ob das schon alles war oder nicht, oder ob da noch was kommt oder
nicht, kann auch ComGetReadCount(COM1) nicht vorhersagen.
Insbsondere hast du keine Garantie dafür, dass ein einziger Aufruf von
ComRead mit einer kompletten Zeile zurückkommt. Er liefert das, was
bisher eingetroffen ist und wenn der Sender noch gar nicht alles
weggeschickt hat, dann liefert er eben nur den Teil, der bisher
übertragen wurde. Es liegt an dir, dein Programm so zu gestalten, dass
es damit klar kommt, eine komplette Zeile aus mehreren Übertragungen
wieder zusammenzusetzen.
Uwe schrieb:> Dein µC wartet aber auf den String "trs23200" und senden tust du> "tttt". Jetzt die Frage was soll da passieren ?
der µcontroller soll "no match" antworten.
Karl Heinz Buchegger schrieb:> Wozu das \0 Byte?
Ja ich weiß... ich dachte mir, ich probiert das einfach mal aus..
Karl Heinz Buchegger schrieb:> Hast du auf dem µC neben der UART noch eine andere Möglichkeit um dir> irgendetwas ausgeben zu lassen? Zb ein LCD?
Nein. Leider nicht. Die Platine ist vorgegeben.
Karl Heinz Buchegger schrieb:> Woher weiß eigentlich das PC-Programm hier>> cout << "GetComReadCount:" << ComGetReadCount(COM1) << endl << endl;> iLen=ComRead(COM1,cBuffer,64);>> wann es eine Zeile empfangen hat?> Das wird so nicht funktionieren.
Natürlich funktioniert das. Ich habe das getestet, indem ich den
µController per while 1 einfach permanent habe "irgendwas" senden
lassen.
Die Sache ist doch so: Wenn der PC etwas empfängt, dann liefert
ComGetReadCount(COM1) einen Wert größer 0. Falls nicht, dann ist der
Wert gleich 0.
Karl Heinz Buchegger schrieb:> Wenn du zeilenweise überträgst, was ich dir sehr ans Herz legen würde,> dann musst du vom µC auch eine Zeile wegschicken.> puts("RECIVED1\n");>> Jetzt ist es eine Zeile und du kannst am PC anhand des \n feststellen,> dass du eine Zeile bekommen hast.
In einer früheren Version meines Programms hatte ich das exakt so
geschrieben und mich dann gewundert, warum ich nach jedem Empfangen in
meiner Windows-Konsole immer 2(!) Absätze hatte. Ich kann nicht sagen
warum das so ist, aber puts("RECIVED1"); scheint schon ein "\n" zu
enthalten...
Karl Heinz Buchegger schrieb:> Aber lass das erst mal. Deine Problem liegen noch viel einfacher. Erst> mal sieh zu, dass du die Kommunkation generell hinkriegst.
Wenn ich das µController-Programm, so wie es jetzt ist, mit dem
Hyperterminal kommunizieren lasse, dann funktioniert es doch schon. Wenn
ich mein C++ mit dem Hyperterminal kommunizieren lasse, dann
funktioniert auch das C++ problemlos. Wenn ich zwei Instanzen des C++
Programms miteinander kommunizieren lasse, dann geht das auch. NUR, wenn
ich C++Programm und µController kommunizieren lassen möchte, dann
passiert garnichts... ^_^
Karl Heinz Buchegger schrieb:> Das tun sie aber nicht!> Ein Computer kann nicht in die Zukunft schauen, ob da von der> Schnittstelle noch was kommen wird oder nicht.> ComGetReadCount(COM1) sagt dir, wieviele Zeichen bisher eingetrudelt> sind. Ob das schon alles war oder nicht, oder ob da noch was kommt oder> nicht, kann auch ComGetReadCount(COM1) nicht vorhersagen.> Insbsondere hast du keine Garantie dafür, dass ein einziger Aufruf von> ComRead mit einer kompletten Zeile zurückkommt. Er liefert das, was> bisher eingetroffen ist und wenn der Sender noch gar nicht alles> weggeschickt hat, dann liefert er eben nur den Teil, der bisher> übertragen wurde. Es liegt an dir, dein Programm so zu gestalten, dass> es damit klar kommt, eine komplette Zeile aus mehreren Übertragungen> wieder zusammenzusetzen.
Jup. Aber das Programm bevor ich das Programm weiter ausbaue, sollte es
doch bis hierhin erstmal funktionieren.. :(
Christian schrieb:>> Wenn du zeilenweise überträgst, was ich dir sehr ans Herz legen würde,>> dann musst du vom µC auch eine Zeile wegschicken.>> puts("RECIVED1\n");>>>> Jetzt ist es eine Zeile und du kannst am PC anhand des \n feststellen,>> dass du eine Zeile bekommen hast.>> In einer früheren Version meines Programms hatte ich das exakt so> geschrieben und mich dann gewundert, warum ich nach jedem Empfangen in> meiner Windows-Konsole immer 2(!) Absätze hatte. Ich kann nicht sagen> warum das so ist, aber puts("RECIVED1"); scheint schon ein "\n" zu> enthalten...
Ja, du hast recht. puts hängt von sich aus ein \n an. Zumindest muss es
das tun, wenn es standardkonform ist.
Daran hab ich nicht mehr gedacht. fputs tut das nämlich nicht und ich
benutze die puts()/gets() calls praktisch nie, weil mir das eine zu
unflexibel und das andere zu gefährlich ist.
> NUR, wenn ich C++Programm und µController kommunizieren lassen> möchte, dann passiert garnichts... ^_^
OK, ok. Ich halt mich schon raus. Wenn du meinst, dass es nicht an
deinen Programmen liegt, oder der Art und Weise, wie du die Dinge
gehandhabt hast, dann sei es so.
eigentlich wollte ich damit nur sagen, dass die programme mit dem
hyperterminal schon funktionieren. du hattest ja vorgeschlagen, simple
programme mit dem hyperterminal kommunizieren zu lassen.
natürlich liegt der fehler irgendwo in meinen programmen!! wollte dich
nicht verärgern oder so....