Hallo Leute, habe folgendes Problem : Ich habe mit VisualBasic.net eine Bedienoberfläche programmiert, mit der ich Daten von meiner Microcontrollerplatine über die RS232 empfange. Die Oberfläche zeichnet die Daten wie bei einem Oszilloskop über die Zeit auf. Um dem PC genügend Zeit zu geben, die Daten einzulesen und auszuwerten, habe ich nach jeder kompletten "Frame" die vom µC gesendet wird, eine Pause in dessen Programm angehängt. Die Pausenzeit bis zur nächsten Controller Frame wurde so gewählt, das der Empfangspuffer des PC´s konstant bleibt und nicht überläuft. Ansonsten werden falsche Daten empfangen was man im Diagramm als Linienabrisse sofort erkennen kann. Das alles wurde auf meinem Desktoprechner mit Windows-XP und einer On-Board Rs232 Schnittstelle programmiert. Prozessor ist ein Athlon64 3000+ mit 2GB Ram Wenn ich jetzt das Programm auf meinem Laptop laufen lasse (Intel Core 2 Duo 3GB Ram mit dem Serial RS-232 Expresscard Adapter EX-1370 und Windows Vista Home Premium), läuft mir mit den selben Einstellungen der Empfangspuffer in windeseile voll. Was mir dabei aber aufiel, ist das es scheinbar zu keinem Datenverlust führt wenn der Puffer überläuft, jedoch ist das Zeichnen alles andere als flüssig, vielmehr werden die Daten "Etappenweise" in der Picturebox gezeichnet, und irgendwann hängt sich das ganze dann komplett auf. Die Prozessorauslastung beider Kerne ist gerad einmal 20%.Auf Handshake Verfahren will ich aufgrund fehlender Pinbelegung am Controller verzichten , da es ja auch auf meinem Desktop-PC ohne klappt. Wo könnte hier das Problem liegen ? An Leistungsdefiziten des Laptops kann es ja nicht liegen. Evtl. aber an der Seriellen Schnittstelle über die Expresscard ?? Danke fürs lesen gruss Maggus ;)
Das kann sehr wohl an der Schnittstelle in der ExpressCard liegen. Die wird nämlich mit recht hoher Wahrscheinlichkeit als USB-Seriell-Adapter implementiert sein - ja, das sieht die ExpressCard-Spezifikation vor. Das kannst Du selbst herausfinden, indem Du mal im Gerätemanager nachsiehst, a) was für ein Devicetreiber verwendet wird und b) Dir mal die Eigenschaften des Gerätes ansiehst. Üblicherweise wird dort ein "Ort" genannt, und bei USB-Geräten steht dort korrekt "USB" ...
Du kannst ja auch ohne zusätzliche Pins Handshake implementieren, und zwar auf Protokoll-Ebene. Du definierst also um die eigentlichen Nutzdaten noch einen Header am Anfang, bzw. eine Checksumme und ein spezielles Zeichen am Ende als Endeerkennung und zur Synchronisierung. Der Controller sendet dieses Paket zum Rechner. Wenn der PC das Päckchen ordnungsgemäß empfangen und geprüft hat (Längenangabe aus Header und Checksumme okay), gibt er dem Controller ein ACK, und der µC sendet das nächste Paket, andernfalls gibts ein NACK, und der µC sendet das gleiche Paket nochmal. Da brauchst du dann kein Timeout etc. Eine andere Möglichkeit wäre, den Rx-Buffer einfach höher zu setzen. Du gehst davon aus, dass die Abläufe unter Vista die gleichen sind wie bei XP. Ist definitiv nicht so. Erstens hast du eine andere "Schnittstelle" vom PC-Prozessor bis zu deinen RS232-Pins (einmal fest aufm Board und einmal über Karte) und somit ein anderes Verhalten (Timing, Ansteuerung, etc.). Zweitens wird denke ich der Ablauf mit .NET unter Vista anders sein als bei XP. Die Ruckler können z.B. auch auftreten, wenn du erstens die Datenverarbeitung nicht sauber von der Ausgabe getrennt hast, also die Ausgabe besser in einem eigenen Thread laufen lassen (z.B. mit der BackGroundWorker-Klasse in .NET). Zweitens wird Vista halt viel mehr Krimskrams im Hintergrund laufen haben als XP, da könnt ich mir vorstellen, das wegen Klickibunti die wichtigen Sachen wie Schnittstellen weniger Priorität bekommen haben. Und dann kommts noch drauf an, wie du den Buffer ausliest (Ereignis oder Polling) und wie du bei Ereignissteuerung triggerst (jedes Byte oder nach einer bestimmten Anzahl Bytes das Ereignis auslösen). Ralf
>Zitat von Rufus >Das kannst Du selbst herausfinden, indem Du mal im Gerätemanager >nachsiehst, a) was für ein Devicetreiber verwendet wird und b) Dir mal >die Eigenschaften des Gerätes ansiehst. Üblicherweise wird dort ein >"Ort" genannt, und bei USB-Geräten steht dort korrekt "USB" ... Devicetreiber : OXCB950 Cardbus UART Gerätetyp : Multifunktionsadapter Hersteller : Enhanced Ports Gerät : PCI Bus 13, Gerät 4 >Zitat von Ralf >Wenn der PC das Päckchen >ordnungsgemäß empfangen und geprüft hat (Längenangabe aus Header und >Checksumme okay), gibt er dem Controller ein ACK, und der µC sendet das >nächste Paket Der Controller darf möglichst keine Unterbrechnungen bei seinem Programmablauf haben. Zweck der Oberfläche ist das darstellen von Reglergrössen. Der Controller wird später mal als Regelung für eine Art aktives Pendel verwendet. Mit der Oberfläche soll es möglich sein, die internen Abläufe Grafisch darzustellen. Und damit das µC Programm möglichst unterbrechnungsfrei laufen soll, hab ich die Sache mit der Kurzen Pause am Ende einer gesendeten Frame geschrieben. Dann kann man wenigstens mit festen Pausen Rechnen. Die Darstellung darf hierbei nicht den Controller behindern. Deshalb wäre dabei ein Pufferüberlauf evtl. sogar verschmerzbar , aber nicht wüschenswert. Zum Quellcode :
1 | If cp.ReadChar = 2 Then |
2 | Try |
3 | strString = "" |
4 | Dim i As Integer = 0 |
5 | Do |
6 | intChar(i) = cp.ReadByte |
7 | i += 1 |
8 | |
9 | Loop While intChar(i - 1) <> 3 |
10 | Dim temp(3) As Byte |
11 | newFrame.bytFC = intChar(0) |
12 | temp(0) = intChar(4) |
13 | temp(1) = intChar(3) |
14 | temp(2) = intChar(2) |
15 | temp(3) = intChar(1) |
16 | newFrame.sngValue = System.BitConverter.ToSingle(temp, 0) |
17 | |
18 | strString += "FC:(" & Hex(intChar(0)) & ")" & "Value : (" & CStr(newFrame.sngValue) & ")" & vbCrLf |
19 | |
20 | ' Schreibt anhand des erhaltenen Funktionscodes an die entsprechende Eigenschaft den Übergebenen Wert |
21 | setValues(intChar(0), newFrame.sngValue) |
22 | |
23 | |
24 | Me.Invoke(Aktualisieren) |
Ich reagiere auf jedes Empfangene Byte durch das Empfangen Ereignis der SerialPort Klasse. Nur Wenn das erste empfangene Zeichen (cp.ReadChar = 2) ist, wird die Frame aufgenommen. In Einer Schleife frage ich jedes folgende Byte ab, bis das Endzeichen erhalten wird (Loop While intChar(i - 1) <> 3). So hab ich alle Bytes der Frame dann in dem Array ( intChar() ), das ich dann weiter verarbeite. Das der Code nichts professionelles darstellt ist kein Geheimnis, aber er sollte funktionieren.Was er ja auch tut unter XP.Zumindest sollte er nicht das bewirken was es unter Vista bewirkt. Ich bleib auf jedenfall dran, werde es mal an meinen alten XP Rechner ausprobieren. Sollte Vista das Problem sein, muss man mit den Konsequenzen eben klarkommen.
Hallo, ich vermute mal das Problem wird sein das du beim empfangen gleich die Daten anzeigst. Soetwas sollte man vermeiden!. In PC mit mehr als 1GHz langweilt sich wenn du daten von einem µC mit ein paar Mhz kommen. Versuche mal das lesen ser Seriellen schnittstelle und das Anzeigen zu trennen. Sobalt man etwas aus einem Programm anzeigt ist man von Windows abhängig, das vernichtet jedes Timing.
Markus wrote: >>Zitat von Rufus > >>Das kannst Du selbst herausfinden, indem Du mal im Gerätemanager >>nachsiehst, a) was für ein Devicetreiber verwendet wird und b) Dir mal >>die Eigenschaften des Gerätes ansiehst. Üblicherweise wird dort ein >>"Ort" genannt, und bei USB-Geräten steht dort korrekt "USB" ... > > Devicetreiber : OXCB950 Cardbus UART > Gerätetyp : Multifunktionsadapter > Hersteller : Enhanced Ports > Gerät : PCI Bus 13, Gerät 4 OK, dann hast Du eine ausreichend hochwertige Karte gekauft. Dennoch gibt es einen Hardwareunterschied zwischen den Onboard-UARTs und der in dieser Karte verbauten - nämlich die Fifo-Größe. Die beträgt bei den Onboard-UARTs im PC 16 Byte (das ist der Standard-16550 von NSC), aber bei den UARTs von Oxford Semiconductor ganz erheblich mehr. Der Empfangs-Fifo der UART wirkt sich auf zwei Arten auf den Empfang von Daten aus. Der Empfangs-Interrupt wird ausgelöst, wenn der Fifo voll ist, aber auch, wenn der Fifo nicht voll ist, und eine gewisse Wartezeit vergangen ist. Diese kann für das von Dir geschilderte Phänomen zuständig sein. Abhilfe: Im Gerätemanager die Interruptschwelle für den Empfangs-Fifo der Oxford-UART auf den gleichen Wert stellen, wie auf dem PC mit Standard-UARTs, das dürfte 14 sein.
Ok, eben klappts. Ich schreibs mal ausführlich für alle die den Post evtl. verfolgen : Im "Gerätemanager/Anschlüsse(COM1)" unter dem Reiter FIFO´s gibts zwei Gruppen, nämlich FIFO Interrupt Trigger Levels und Receive FIFO Flow Control Thresholds Wenn ich bei Interrupt Trigger Level den Schwellwert für Receiver auf 1 setzte, läuft mein Programm so wie es soll. Vorher war hier der Wert 100 eingetragen. Ich interpretiere das jetz mal einfach so, das das Abarbeiten der Empfangenen Zeichen vom Controller erst ausgelöst wurde, wenn er 100 Bytes Empfangen hatte.Ich war aber auch der Meinung, das ich das selbst in meinem Code festlegen kann ab wieviel Byte das Empfangs Ereignis ausgelöst wird. Aber vermutlich vergleiche ich hier Äpfel mit Birnen, kann das sein ?
>Zitat von Peter > >Versuche mal das lesen ser Seriellen schnittstelle und das Anzeigen zu >trennen. Ich dachte hierfür sei der invoke Befehl (Me.Invoke(Aktualisieren) ). Dieser Startet nämlich das aktualisieren der Werte in der Form über einen eigenen Thread. VB.net lässt es auch garnicht zu, das ich die Daten direkt in die Form schreibe, sondern ich muss in diesem Fall den umweg über die Eigenschaften meiner Oszilloskopklasse gehen. Die Methode "Aktualisieren" die mit invoke ausgelöst wird, kümmert sich dann darum , das die vorhanden Daten (stecken jetzt ja in den Eigenschaften der Osziklasse ) in der Form gezeichnet werden. Oder lieg ich hier evtl. auch falsch ? Auf jedenfall funktioniert jetzt alles, vielen Dank nochmals ;)
> Wenn ich bei Interrupt Trigger Level den Schwellwert für Receiver auf 1 > setzte, läuft mein Programm so wie es soll. Naja, das löst für jedes einzelne Zeichen einen Interrupt aus. Das entspricht dem Verhalten der Fifolosen uralt-UART 8250, wie man sie früher in PCs verwendet hatte. Bei hohen Datenraten ist das recht ineffizient, womit ich wörtlich Datenraten im Sinne von übertragene Bytes pro Sekunde meine, nicht die Baudrate an sich; man kann auch mit 19200 Baud nur vier Zeichen pro Sekunde übertragen. > Vorher war hier der Wert 100 eingetragen. Naja, wie ich bereits riet, solltest Du mal nachsehen, mit welchem Wert der XP-Rechner arbeitet, dessen Onboard-Schnittstelle Du verwendest -ich tippe auf 14. > Ich interpretiere das jetz mal einfach so, das das Abarbeiten der > Empfangenen Zeichen vom Controller erst ausgelöst wurde, wenn er 100 > Bytes Empfangen hatte. Wenn Du mit "Controller" den UART-Baustein in Deiner Karte meinst, ist das korrekt. > Ich war aber auch der Meinung, das ich das selbst > in meinem Code festlegen kann ab wieviel Byte das Empfangs Ereignis > ausgelöst wird. Nein, dazwischen sitzt noch ein Puffer, der von Windows verwaltet wird. Zugriff auf treiberspezifische Konfigurationsoptionen bietet die recht allgemein gehaltene API für serielle Schnittstellen nicht, das aber ist kein Fehler von Windows, sondern bei Betriebssystemen allgemein üblich. > Aber vermutlich vergleiche ich hier Äpfel mit Birnen, > kann das sein ? Ach, das wird so oft gemacht ...
Ich habe den Wert von WindowsXP übernommen, der stand in der tat auf 14, aber leider hatte ich dabei immernoch einen Überlauf. Zwar wesentlich langsamer, aber er war eben noch da. Denke aber das die Einstellungen in Ordnung , solange ich nicht wieder Schwierigkeiten bekomme. Ich bin ja schon voll zufrieden das es erstmal so funktioniert. Bin in Sachen Programmieren kein profi und was die Hardware angeht auch nicht :)
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.