Hallo miteinander
Ich bin gerade dabei für ein kleines Schulprojekt auf der PC Seite ein
Frame-Protokoll für die RS232-Schnittstelle aufzubauen.
Nach ein paar Anfangsschwierigkeiten konnte ich Daten senden und auch
empfangen, doch irgendwie macht das Programm nicht das, wass es sollte:
sorry wegen der Formatierung, aber das ganze ist noch im
Anfangsstadium...
// allItems.push_back(item); // Zeile in Vector speichern
12
switch(RS232_state){
13
casesendENQ:
14
ComWrite(COM4,ENQ);
15
richTextBoxMessage->AppendText("sendENQ\n");
16
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
17
RS232_state=waitACK;
18
break;
19
casewaitACK:
20
if(ComRead(COM4)!=-1){
21
if(ComRead(COM4)==ACK){
22
RS232_state=sendSOH;
23
}
24
else{
25
RS232_state=sendENQ;
26
}
27
}
28
richTextBoxMessage->AppendText("waitACK\n");
29
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
30
break;
31
casesendSOH:
32
ComWrite(COM4,SOH);
33
RS232_state=sendCONTR;
34
richTextBoxMessage->AppendText("sendSOH\n");
35
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
36
break;
37
casesendCONTR:
38
// ComWrite(COM4,0xE0);
39
// ComWrite(COM4,(atoi (allItems[0].c_str()) ) ); // String in Int umwandeln und senden
40
RS232_state=sendAXIS;
41
richTextBoxMessage->AppendText("sendCONTR\n");
42
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
43
break;
44
casesendAXIS:
45
// ComWrite(COM4,SOH);
46
RS232_state=sendCHK;
47
richTextBoxMessage->AppendText("sendAXIS\n");
48
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
49
break;
50
casesendCHK:
51
// ComWrite(COM4,SOH);
52
RS232_state=waitACK_CHK;
53
richTextBoxMessage->AppendText("sendCHK\n");
54
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
55
break;
56
casewaitACK_CHK:
57
if(ComRead(COM4)!=0){
58
if(ComRead(COM4)==ACK){
59
RS232_state=sendEOT;
60
}
61
else{
62
RS232_state=sendCONTR;
63
}
64
}
65
richTextBoxMessage->AppendText("waitACK_CHK\n");
66
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
67
break;
68
casesendEOT:
69
ComWrite(COM4,EOT);
70
RS232_state=sendENQ;
71
richTextBoxMessage->AppendText("sendEOT\n");
72
richTextBoxMessage->ScrollToCaret();// Ans Ende scrollen
73
break;
74
}
75
// }
76
}
77
fin.close();
78
fout.close();
79
}
Theoretisch sollte das Programm immer dann bei einem Case stehenbleiben,
wenn es ein ACK vom MCU erwarte, tut es aber nur gerade beim ersten mal:
Zu Debugg-Zwecken gebe ich jeweils die Case-Position noch an ein
Textfeld aus, und das sieht so aus:
> sendENQ> waitACK> waitACK> waitACK> waitACK> waitACK> waitACK> waitACK> sendSOH> sendCONTR> sendAXIS> sendCHK> waitACK_CHK> sendEOT> sendENQ> waitACK> sendSOH> sendCONTR> sendAXIS> sendCHK> waitACK_CHK> sendEOT> sendENQ> waitACK> sendSOH> sendCONTR> sendAXIS> sendCHK> waitACK_CHK> sendEOT> sendENQ> waitACK> .....
Meine Vermutung ist, da ich die ACK's vom MCU über einen Tastendrück
sende, dass bei der Abfrage "ComRead(COM4) != 0" der Buffer nie gelehrt
wird, denn so hat er immer ein ACK im RX-Buffer.
Die ganze Comtool-Read-Funktion sieht so aus:
Günstig wäre, das Protokoll etwas näher zu kennen.
Beispiel:
1
casewaitACK:
2
if(ComRead(COM4)!=-1){
3
if(ComRead(COM4)==ACK){
4
RS232_state=sendSOH;
5
}
6
else{
7
RS232_state=sendENQ;
8
}
9
}
D.h. das vor dem ACK irgendetwas gesendet werden muss, bevor es
weitergeht.
Wird nur ACK gesendet, wird nie der nächste Zustand erreicht.
Bei waitACK_CHK: muss zuerst 0x00 empfangen werden.
Die Frage ist, soll das vom Protokoll so sein, oder nicht?
Andere Baustelle: Das Update von UI-Elementen muss im Haupt/UI-Thread
gemacht werden, nicht in einem anderen (Timer/BackgroundWorker,
DataReceived etc).
Siehe Beitrag "VB2008.NET - Serielle Com Port ansteuerung"
Zum Protokoll:
PC sendet ENQ und der MCU antwortet mit ACK (MCU bereit für Daten).
Jetzt sendet der PC SOH, Controll-Byte, Achsen, CRC und wartet, ob die
übertragung Richtigt war, wenn ja, antwortet der MCU mit ACK und der PC
quitiert mit EOT. ansonsten muss noch mal vom Controll-Byte aus alles
gesendet werden.
Ok, werde mir mal den Tread anschauen.
MFG
Patrick
sry, doppelpost.
hab noch vergessen dass ComRead -1 ausgibt, wenn keine Daten vorhanden
sind. also wenn Daten da sind, soll überprüft werden was empfangen
wurde...
Ich hab das Problem beheben können.
Der Fehler lag nicht beim C++ sondern beim C auf dem MCU...
Die ACK's wurden mittels Tastendruck gesendet -> Entprellen vergessen.
so hat der MCu auch bei kurzem Druck ca 50 ACK's gesendet... welche alle
schön abgearbeitet wurden...
Das CPP Programm lief einfach schön die ACK's im Buffer ab...
Ich habe noch das
1
if(ComReadCOM4)!=-1){
2
if(ComRead(COM4)==ACK){
3
RS232_state=sendSOH;
4
}
5
else{
6
RS232_state=sendENQ;
7
}
8
}
mit
1
if(ComGetReadCount(COM4)!=0){
2
if(ComRead(COM4)==ACK){
3
RS232_state=sendSOH;
4
}
5
else{
6
RS232_state=sendENQ;
7
}
8
}
abgeändert.
Arc Net schrieb:
> Andere Baustelle: Das Update von UI-Elementen muss im Haupt/UI-Thread> gemacht werden, nicht in einem anderen (Timer/BackgroundWorker,> DataReceived etc).
was meinst du damit??? im main?
wie soll ich dann das Senden Zeitlich steuern??
Das ganze Frame sollte so maximal alle 30us gesendet werden. es werden
aber auch noch Verzögerungen benötigt...
soll ich beim Timerevent den Tag setzen und dann aus dem Main heraus
darauf abfragen damit ich das ENQ zeitlich gesteuert senden kann? der
rest wird dann einfach automatisch gesendet...
Patrick B. schrieb:
> Arc Net schrieb:>> Andere Baustelle: Das Update von UI-Elementen muss im Haupt/UI-Thread>> gemacht werden, nicht in einem anderen (Timer/BackgroundWorker,>> DataReceived etc).>> was meinst du damit??? im main?
Nein, das Update der Controls. Z.Z. steht z.B. in Timer_Tick
Arc Net schrieb:
> Das Problem ist, das die Controls nicht thread-safe sind d.h. greift man> aus einem anderen Thread (das kann ein BackgroundWorker-Thread sein,> kann aber u.a. auch ein Thread sein, der von einem System.Timer genutzt> wird) auf ein Control zu, gibt es eine Exception.
=> soll das soviel heissen wie timerEvent greifft auf richTextBox zu...
wie kann ich dies unterbinden?? so dass ich beim timerEven ein "Flag"
setzte auf welches ich aus der richTextBox abfrage und entsprechendes
setze...
korriegiere mich, wenn ich falsch liege..
MFG
Patrick
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspxhttp://msdn.microsoft.com/en-us/library/ms171728.aspx
p.s. bei der Gelegenheit, sollte man auch das Datei-Handling aus dem
Timer herausnehmen, u.a. deshalb, da falls dort irgendetwas zu lange
dauert, es durchaus passieren kann, dass Timer.Tick erneut aufgerufen
wird bevor der letzte Durchlauf beendet ist (mit allen Konsequenzen)
p.p.s. wie hier im Forum (und auch anderenorts) häufiger dargelegt, ist
jede Sprache != C++ besser, wenn man für das .NET Framework entwickelt.
Also vllt auch nochmal überlegen, ob es wirklich C++ bleiben soll/muss.
Arc Net schrieb:
> p.s. bei der Gelegenheit, sollte man auch das Datei-Handling aus dem> Timer herausnehmen, u.a. deshalb, da falls dort irgendetwas zu lange> dauert, es durchaus passieren kann, dass Timer.Tick erneut aufgerufen> wird bevor der letzte Durchlauf beendet ist (mit allen Konsequenzen)
Das ist sowieso eine themoräre Lösung: später sollte das ganze sehr viel
schneller laufen, das ENQ sollte maximal alle 30us gesendet werden, was
aber mit einem Faktor mutlipliziert wird, je nach Differenz zweier
Punkte in der TXT-Datei.
Nochmals später sollte das ganze über den d2xx.dll Treiber von FTDI
laufen.
> p.p.s. wie hier im Forum (und auch anderenorts) häufiger dargelegt, ist> jede Sprache != C++ besser, wenn man für das .NET Framework entwickelt.> Also vllt auch nochmal überlegen, ob es wirklich C++ bleiben soll/muss.
Ok, nur so zu meiner momentanen Situation:
- Ich habe seit 3 Jahren C in der Schule
- Seit dem Sommer sind wir an C++ (Borland VCL),
Zuhause aus eigenem Interesse mit Visual C++ Express 2008
- Hobbymässig für eine Homepage PHP, HTML und JS, nutze ich jetzt aber
nicht
mehr oft.
Bei C++ kann ich sehr viel aus dem C übernehmen, es sind einfach noch
komplexe Syntaxe und Klassen...
Was würdes du empfehlen??
MFG
Patrick