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?
hier ist der Sourcecode: C++ ::
1 | //*****************************************************************************
|
2 | //*
|
3 | //*
|
4 | //* ComDemo.cpp
|
5 | //*
|
6 | //*
|
7 | //*****************************************************************************
|
8 | |
9 | #include <conio.h> |
10 | #include <stdio.h> |
11 | #include <windows.h> |
12 | #include "ComTools.h" |
13 | #include <iostream> |
14 | using namespace std; |
15 | |
16 | |
17 | #define COM1 0
|
18 | #define COM2 1
|
19 | #define COM3 2
|
20 | #define COM4 3
|
21 | |
22 | #define ESC 27
|
23 | |
24 | |
25 | //*****************************************************************************
|
26 | //*
|
27 | //* main
|
28 | //*
|
29 | //*****************************************************************************
|
30 | int main(int argc, char* argv[]) |
31 | {
|
32 | int iLen; |
33 | char iKey[4]; |
34 | char cBuffer[65]; |
35 | |
36 | ComInit(); |
37 | |
38 | if(!ComOpen(COM1, 19200,P_NONE,S_1BIT,D_8BIT)) |
39 | {
|
40 | cout << "Kann die Schnittstelle nich oeffnen !" << endl << endl; |
41 | return -1; |
42 | }
|
43 | |
44 | while(true) { |
45 | |
46 | iKey[0] = 't'; iKey[1] = 't'; iKey[2] = 't'; iKey[3] = 't'; |
47 | ComWrite(COM1, iKey, 4); |
48 | cout << "GetComWriteCount:" << ComGetWriteCount(COM1) << endl; |
49 | cout << "GetComReadCount:" << ComGetReadCount(COM1) << endl << endl; |
50 | iLen=ComRead(COM1,cBuffer,64); |
51 | if(iLen>0){ |
52 | cBuffer[iLen]=0; |
53 | cout << "Emfpangen: "<< cBuffer << endl << endl; |
54 | }
|
55 | Sleep(1000); |
56 | |
57 | }
|
58 | |
59 | ComClose(COM1); |
60 | ComExit(); |
61 | |
62 | return 0; |
63 | }
|
µController ::
1 | #include <18F4550.h> |
2 | #include <stdio.h> |
3 | #include <string.h> |
4 | |
5 | #fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, NOLVP, NOVREGEN, CCP2B3, PUT
|
6 | |
7 | #use delay (clock=20000000)
|
8 | #use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
|
9 | |
10 | |
11 | void Init_Ports(void) |
12 | {
|
13 | |
14 | /* OUTPUT = 0; INPUT = 1; 0x0F => Pin 7..4=output, Pin 3..0=input*/
|
15 | |
16 | /************** ANALOG PORT A DEFINITIONS
|
17 | * A7 A6 A5 A4 A3 A2 A1 A0
|
18 | *
|
19 | * nc nc nc nc nc nc nc TACHO
|
20 | *
|
21 | ****************************************/
|
22 | SETUP_ADC_PORTS(AN0); |
23 | SETUP_ADC(ADC_CLOCK_INTERNAL); |
24 | SET_ADC_CHANNEL(0); |
25 | |
26 | /********************* PORT B DEFINITIONS
|
27 | * B7 B6 B5 B4 B3 B2 B1 B0
|
28 | *
|
29 | * nc nc IN1 IN2 PWM nc nc nc
|
30 | *
|
31 | * PGD PGC CCP2
|
32 | *
|
33 | ****************************************/
|
34 | SET_TRIS_B(0x00); |
35 | |
36 | /********************* PORT C DEFINITIONS
|
37 | * C7 C6 C5 C4 C3 C2 C1 C0
|
38 | *
|
39 | * AUX7 AUX6 AUX5 AUX4 n.a. AUX2 AUX1 AUX0
|
40 | *
|
41 | * CCP1
|
42 | *
|
43 | ****************************************/
|
44 | //SET_TRIS_C(0b00010000);
|
45 | |
46 | /********************* PORT D DEFINITIONS
|
47 | * D7 D6 D5 D4 D3 D2 D1 D0
|
48 | *
|
49 | * UA-0 UA-1 UA-2 UA-S nc nc nc nc
|
50 | *
|
51 | ****************************************/
|
52 | SET_TRIS_D(0xF0); |
53 | |
54 | OUTPUT_LOW(PIN_B5); |
55 | OUTPUT_LOW(PIN_B4); |
56 | |
57 | SETUP_CCP2(CCP_PWM); |
58 | SETUP_TIMER_2(T2_DIV_BY_1, 255, 1); // 19.53125kHz PWM -> Period: 51.2us |
59 | |
60 | SET_PWM2_DUTY(0); |
61 | |
62 | SETUP_TIMER_0(RTCC_INTERNAL); |
63 | }
|
64 | |
65 | |
66 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
67 | // Main Program
|
68 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
69 | void main() |
70 | {
|
71 | char _4recive[8]; |
72 | int _MODE = 0, _dRE = 0, _dAB = 0; |
73 | |
74 | |
75 | delay_ms( 500 ); |
76 | Init_Ports(); |
77 | delay_ms( 500 ); |
78 | puts("HALLO WELT"); |
79 | delay_ms( 500 ); |
80 | |
81 | while(1) |
82 | {
|
83 | |
84 | switch(_MODE){ |
85 | |
86 | case 0: |
87 | if (kbhit()) { |
88 | gets(_4recive); |
89 | if(_4recive[0] == 't' && _4recive[1] == 'r' && _4recive[2] == 's' && _4recive[3] == '2' && _4recive[4] == '3' && _4recive[5] == '2' && _4recive[6] == '0' && _4recive[7] == '0'){ |
90 | puts("RECIVED1"); |
91 | }
|
92 | else { |
93 | puts("no match"); |
94 | }
|
95 | }
|
96 | break; |
97 | |
98 | }
|
99 | |
100 | switch(_dRE){ |
101 | |
102 | case 0: |
103 | break; |
104 | |
105 | case 1: |
106 | puts("RELATIVE"); |
107 | break; |
108 | |
109 | }
|
110 | |
111 | switch(_dAB){ |
112 | |
113 | case 0: |
114 | break; |
115 | |
116 | case 1: |
117 | puts("ABSOLUTE"); |
118 | break; |
119 | |
120 | }
|
121 | |
122 | |
123 | }
|
124 | }
|
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:
1 | sDcb.fDtrControl = DTR_CONTROL_ENABLE; |
2 | sDcb.fRtsControl = RTS_CONTROL_ENABLE; |
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()????
Dein µC wartet aber auf den String "trs23200" und senden tust du "tttt". Jetzt die Frage was soll da passieren ?
> 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 | int main() |
2 | {
|
3 | char received[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....
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.