mikrocontroller.net

Forum: PC-Programmierung UART PC Interrupt Empfang VC++


Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

sorry für das ewig gleiche Thema. Meine selbst geschriebene Klassen für
das Senden und Empfangen über UART funktionieren einwandfrei.

Das Empfangen möchte jetzt aber optimieren. Bisher sieht das
Empfangsprotokoll in etwa so aus:

PC --> uC: Anfrage auf Informationen
uC --> PC: uC sendet genaue Anzahl von BYTES. (Empfang)

Ich möchte nun aber gerne, das meine PC-Software Daten empfängt die
irgenwann auf den Bus gelegt werden. In einer while(1)-Schleife in
meiner PC-Software möchte und kann ich nicht ewig auf einen Empfang
warten.

Wie kann ich ohne dieser while-Schleife das machen??????????????

Bin dankbar für jeden Vorschlag,
Michael

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entweder per Thread, da ist eine while-Schleife kein Problem, oder mit
dem Overlapped-Modus, der blockiert das programm nicht, so dass man
regelmässig nachfragen kann, ob was da ist. Zu guter letzt wäre da noch
readfileex, das eine Callback-Routine aufruft, wenn es fertig ist, aber
damit habe ich noch nichts gemacht vondaher keine Ahnung, wie das genau
funktioniert

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Tobi,

was ist Deiner Meinung nach leichter zu programmieren. Die Thread- oder
die Overlappedvariante.

Und vielleicht hast Du noch ein paar gute Infolinks. Bei der
MSN-Library verstehe ich meistens nur Bahnhof. Bin halt doch mehr der
uC-Programmierer.

Michael

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist eine sehr gute Beschreibung aus der MSDN:
http://msdn.microsoft.com/library/default.asp?url=...

Ich denke, wenn du noch wie was mit Threads gemacht hast ist die
Overlapped-Version einfacher. Aber schau dir den Link mal an, dann
solltest du das selbst einschätzen können

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Tobi,

danke für die Quelle ich komme damit ziemlich gut zurecht. Ich habe
noch eine brauchbare Info gefunden, vorallem für die Einsteiger auf
Multi-Thread.

http://msdn.microsoft.com/library/default.asp?url=...

MfG,
Michael

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin ein gutes Stück weiter mit dem Multithreading. In C ist das ja
relativ einfach. Ich habe allerdings echte Probleme wenn ich das ganze
im VC++ Code versuche zu implementieren.

Ich möchte eine Memberfunktion von CTestboxDlg als BackgroundTread
laufen lassen. Diese Memberfunktion soll mir in ein Ausgabefeld die
asynchron empfangenen Zeichen (vom UART-Port) schreiben.

Meine Fragen:
Kann ich überhaupt eine Memberfunktion einer Klasse separat in einem
Thread laufen lassen?

Wenn ja wie?

_beginthread( CTestboxDlg.MyMultiThread, 0, NULL );

funktioniert nicht... Ich hab' auch schon ein paar ander Funktionen
auspropiert. Aber ich habe immer Ärger mit dem ersten Parameter. Der
wird nie akzeptiert.

Danke,
Michael

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.
   Kann ich überhaupt eine Memberfunktion einer Klasse
   separat in einem Thread laufen lassen?

Das geht schon, nur muss diese Funktion eine statische Memberfunktion
sein.
Das bedeutet, daß es in der Funktion keinen this-Pointer gibt, sondern
der, wenn benötig, als getrennter Parameter an
_beginthread/CreateThread zu übergeben ist und der Funktion bei Aufruf
entsprechend übergeben wird.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Rufus
Danke für Deine schnelle Antwort. Ich bin leider nicht so sattelfest in
C++. Kannst Du vielleicht mal einen Code Snippet von der statischen
Funktion und der anschließenden Parameterüberger für _beginthread
posten.
Damit könntest Du mir wirklich weiterhelfen.

Michael

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Eine statische Member-Funktion ist im Grunde wie
eine einzelne, freistehende Funktion. Nur dass sie
halt aus welchen Gruenden auch immer, im Namensraum
einer Klasse definiert wird.
D.h. Du kannst genauso gut auch eine freistehende
Funktion machen, die Du in den beginthread hineinstopfts.

Schau Dir mal das angehaengte Beispiel an.
Die ThreadFunktion bekommt eine globale Variable,
die als Window-Handle zum Dialog fungiert. Die Thread-
Funktion selbst kommuniziert mit dem Dialog Objekt
indem es ihm Messages schickt. Dadurch vermeide ich, daß
ich Funktionen des Dialog-Objektes aufrufe, wenn dieses
in einem falschen Zustand ist.

Die entscheidende Source ist in ThreadDlg.cpp / ThreadDlg.h

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun, das ist schon noch ein Unterschied.
Eine statische Memberfunktion kann über einen ihr übergebenen
this-Pointer auf private und protected-Membervariablen ihrer Klasse
zugreifen und über den this-Pointer auch nichtstatische
Memberfunktionen ihrer Klasse aufrufen; eine alleinstehende
nicht-Memberfunktion kann das nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sag ich ja: sie ist im Namensraum der Klasse definiert.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Danke für Eure Untersützung. Ich bin jetzt ein gutes Stück weiter.Mein
Thread (globale Funktion) läuft. Jetzt muss ich nur noch an ein
"Ein-Ausbgabe"-Feld meines Hauptfensters die Daten schicken, die über
 die UART empfangen wurden .

Ich habe es mir so gedacht.

static BYTE hMemberVar; // Handle zu meiner AusgabeVariable global
static HWND hDlg;       // ...

void CTestboxDlg::OnStartCatch()
{
  ...
  hMemberVar = this->m_bCatchResult;
  hDlg = this->GetSafeHwnd();
}

void NewMultiThread(void *pvParam)
{
     BYTE bCatchUART = 34;      // Hier empfang über UART
     *hMemberVar = bCatchUART;  // ????????? Funktioniert nicht
     UpdateData(FALSE);         // ????????? Hier hDlg Updaten
     while(1);
}

Nochmals Danke für Euren Support...
Michael

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry muss natürlich ein Zeiger sein.

static BYTE *hMemberVar; // Handle zu meiner AusgabeVariable global

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmals Sorry,
manchmal steht man auf dem Schlauch. Lösung...

static BYTE * hMemberVar;

hMemberVar = & m_bCatchResult;

*hMemberVar = bCatchUART;

Allerdings habe ich noch immer das UpdateData(FALSE) Problem.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UpdateData solltest Du auf gar keinen Fall aus einem anderen Thread
heraus aufrufen.

Besser ist es in diesem Fall mit PostThreadMessage dem GUI-Thread der
Applikation eine Nachricht zu senden, die vom Nachrichtenhandler Deines
Dialoges ausgewertet wird und an dieser Stelle UpdateData aufruft.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:-)

Genau so, wie ich es ihm in der Demo gezeigt habe.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, Danke Leute. Ich hab's kapiert und zum laufen gebracht :-)

:-)  :-)  :-)  :-)  :-)  :-)  :-)  :-)  :-)

Michael

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie schon gesagt alles funktioniert so wie ich es mir vorstelle.
Allerdings möchte ich jetzt noch meinen erzeugten Background-Thread:

while (1){ USART Dauerempfang; SendMessage zu Main;}

aus dem Bedienfenster wieder beenden. Ich kann das mit Hilfe ein
globalen Variable "EndThreadFlg".

while (EndThreadFlg == 0){ USART Dauerempfang; SendMessage zu Main;}

Es würde mir aber viel besser gefallen, wenn ich eine Message an meinen
Background-Thread schicken könnte und dann auf diese Message gezielt
reagieren. Mein Backgroundprozess ist aber eine primitive globale
Funktion.

long WINAPI AsynUsartThread (long *pvParam)
{
  Öffne Port;
  while (EndThreadFlg == 0){ USART Dauerempfang; SendMessage zu Main;}
  return 0;
}

Ist es sehr aufwendig meine AsynUsartThread-Funktion über Messages zu
steuern???
Und wie kann man es ungefähr bewerkstelligen. Muss ich für meinen
Thread einen großen Overhead anlegen zum Message-Empfang?????

Danke für Eure Antworten,
Michael

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Statt ein Flag auszuwerten kannst Du auch ein Event verwenden.
So etwas wird mit CreateEvent erzeugt und mit SetEvent signalisiert.

Deine "Dauerempfangsfunktion" wird, sofern sie overlapped I/O
verwendet, bereits irgendwo ein WaitForSingleObject verwenden.
Wird das durch ein WaitForMultipleObjects ersetzt, kann die
Wartefunktion im Thread sowohl eintreffende Zeichen als auch die
Signalisierung des Events mitbekommen.

Windows-Nachrichten sind für die Kommunikation mit Background-Threads
ein eher ungeeignetes Mittel.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das mit den CEvent dingern ist nicht inbedingt notwendig.. wenns nur 1
thread ist geht das mit nem flag auch problemlos..

im übrigen solltest du möglichst NICHTS was einem CWnd gehört in einen
thread reintun.. mach dir einen struct mit den daten die du drinnen
haben willst, hol dir speicher dafür und gibt den pointer drauf in den
thread.. der muss dann am schluss den speicher selbst wieder frei
geben... alles andere ist schrott..

also im prinzip sowas...

SMeineDaten *MeineDaten=new SMeineDate;
MeineDate->m_hWindowToUpdate=<der handle auf das fenster was daten tun
soll ;)
MeineDate->wasauchimmer

dann machst ein AfxBeginThread(....); oder wie auch immer du das
erledigen willst...

im thread schickst du dann einfach eine window-message and das fenster,
von dem du den handle hast und schon rutschen die daten dort hin... (z.b
SetWindowText-message)

wie gesagt MESSAGE schicken.. nicht funktion aufrufen !!! das ist sonst
alles NICHT Threadsafe!!!

immer wenn dein fenster nachrichten verarbeitet(also sich neu zeichnet
beim verschieben,...) dann wirds auch die box updaten...

es gibt aber noch eine variante die ein grober hack ist.. du kannst in
einem thread eine eigene message-queue aufbaun und dann das gesamt
fenster im thread handlen... aber das ist böse.. tu lieber nachrichten
schicken.. das ist unkompliziert und funktioniert gut ;)

73

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.