PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : COM-Abfrage



surfer
05.09.2005, 14:20
Hallo

Ich habe meine bisherigen Projekte immer so realisiert, dass ich vom uC her alle ca. 10ms Daten an den PC sende.
Am PC habe ich dann auch immer ca. alle 10ms (mit Timer) den COM-Eingang abgefragt und so hat sich das ganze System irgendwie synchronisiert...
Da sehr viele Daten ankommen, war das kein Problem. Nun ist es bei meinem nächsten Projekt so, dass ich nur etwa alle 1s Daten vom uC schicke. Jetzt möchte ich mit dem Borland C++ Builder ein Programm realisieren, dass mir die Daten in eine Variable schreibt, wenn sie ankommen. Also so eine Art Interrupt für den Dateneingang am COM-Port...
Ich bin jetzt wirklich schon lange am versuchen, aber es will einfach nicht so recht!
Da ich kein spitzen-Progammierer bin, würde ich mich freuen, wenn ihr mir helfen könntet!!
Merci

PicNick
05.09.2005, 14:37
Ich arbeite mit Visual C++. Da mach ich sowas mit threads, is' am einfachsten: Einer wartet auf input , der andere kann inzwischen weiterbüffeln.
Geht auch anders, aber es funzt, und dann genügt es mir (mir hängt windows eigentlich bei den Ohren raus)

hl_angel
06.09.2005, 15:25
schau mal da: http://www.traverse.com/people/poinsett/bcbcomm.html
In einem thread auf die COM zu warten funktioniert auf betriebssystemebene ebenfalls mit interrupts, nur der programmierer merkt nichts davon (kapselung durch system treiber): der thread wird solange angehalten, bis der interrupt ausgelöst wird, dann wird vom COM-"File" das zeichen gelesen... manchaml sehn ich mich auch nach der alten DOS-Zeit, wo man das alles selber machen musste (pardon: durfte!)

PicNick
06.09.2005, 15:31
... manchaml sehn ich mich auch nach der alten DOS-Zeit, ...alles selber..
Au weia, Nostalgie-Attacken schon in deinem jugendlichen Alter sind bedenklich ! Aufpassen !

:mrgreen:

PasstScho
06.09.2005, 17:04
Hi surfer,
Dass es nicht mit TTimer geht, wird dir aufgefallen sein (nur weil Interval auf 1 ist, bedeutet das leider nicht, dass er jede ms aufgerufen wird).
Mir fallen jetzt 2 Möglichkeiten ein, dein Problem zu lösen.
1. Threads: wenn man sich damit auskennt, und sich im klaren ist was man tut ist das ne gute Lösung.
2. Eine Art eigenen Timer basteln, mit hilfe der "Application.OnIdle" Methode, indem du darin immer abfrägst, ob eine ms vergangen ist. (Application.OnIdle wird in einer endlosschleife immer aufgerufen, wenn dein Programm grad nix besseres zu tun hat). Wenn dein Programm mit den Daten keine zeitintensiven Dinge vor hat, ist die Möglichkeit wohl die Problemloseste und einfachste. Wenn man das einmal gemacht hat, ist es einfach(auch wenns kompliziert klingt), also frag wenns bei dir nicht gleich klappt, dann mache ich dir schnell den code, der dir helfen sollte...
MfG Alex

surfer
08.09.2005, 10:00
Also 1.Mal danke für eure Antworten...

Die ganze Abfrage habe ich nach der Anleitung von hl_angel's link gemacht.
Mir wäre die "Thread-Lösung" eigentlich am besten.
Wenn ich das richtig verstehe...:

Es gibt mein Hauptprogramm und einen Thread.
Der Thread läuft parallel zum Hauptprogramm und ruft immer und immer wieder die Daten am COM ab....
Das ganze beeinflusst sich nicht und ich kann einfach im Hauptprogramm die im anderen Thread abgeholten Daten auswerten.
Im Thread schreibe ich die Daten in ein char und lese sie im Hauptprogramm aus.

Könnte das so richtig sein?

Wenn ja. Hätte mir jemand für den Builder mal ein Beispiel für einen einfachen Thread? Danke.

Merci

PasstScho
08.09.2005, 13:24
Hi,
Hab mit BC++ nocht nix mit Threads gemacht, sondern bisher nur mit Delphi.
Aber mit File|New|Other|Thread kannst du deine Thread Klasse machen, die dann wie jede andere Thread Klasse auch benutzt werden kann.
Unter ::Execute schreibste deinen Code rein... für Delphi hab ich auf die schnelle http://www.dev-center.de/index.php?cat=tutorials&file=multithreading gefunden, das müsstest du nur schnell in C++ reintippen, was bei Delphi->BC++ ja kein problem darstellen sollte.
MfG Alex

surfer
08.09.2005, 13:54
Aaah. So einfach ist das....
Eigentlich funktioniert es. Nur weiss ich noch nicht, wie ich zwischen dem Hauptprogramm und dem Threads Variabeln übergeben kann...?
Muss ich mit include noch die beiden miteinander verknüpfen?

Danke schonmals...!

surfer
08.09.2005, 14:18
Suuper!! Danke vielmals!! Ist ja wirklich einfach!! Funktioniert jetzt super!!!!

DANKE!!!

surfer
08.09.2005, 17:57
Nun habe ich aber etwas anderes gemerkt....
Und zwar habe ich ja im Thread eine Endlosschlaufe, ohne Verzögerung, die mir einfach immer den Eingang abfragt. Dies jedoch verlangsamt alles ein bisschen... Wenn ich dann ein Zeichen mit der Tastatur senden möchte, hat es sicher einige 1/100s verzögerung. Sowieso läuft alles irgendwie instabil. Ist das ein bekanntes Problem?

PasstScho
08.09.2005, 18:54
Hi,
Naja, das ist so ne Sache mit Threads ;).
Mich haben die auch schon mal genervt weil ich mich damit auch nicht so gut auskenne.
Du müsstest die Priorität des Threads runterschrauben. Entweder mit thread->Priority oder mit Mitteln, wie bei meinem Link unten beschrieben.
Das sollte helfen - wenn nicht bin ich auch fast Ratlos...
MfG Alex

NumberFive
09.09.2005, 01:05
Ich hoffe das es hier um ein windows kiste geht.

Immer dran denk windows kann kein Multitasking. Sonder es ist TimeSlot
gesteuert. Das heist bei windows 2000 ist es so das alle 18 ms der Trhead gewechselt wird. Jedes program ist mindestens ein Thread wo bei ich keines
kenne was wirklich nur eine hat. Auch wenn den nicht selbst programmiert.

Auch deine Tastatur hängt in dieser Falle. wäre nur anders wenn du die tastatur per DireckX abfragst dann ist die Prioritäte etwas anders.

Zur Instabilität kenn ich ein Fhler den viel am anfang tun. du draf auf keine Fall auch bildschirm element aus dem Thread zugreien oder auf global varialen diese zugriffe muß du sycronnisieren oder anders machen.

Vielleicht hilft die das ja weiter.

Gruß

Blackbird
09.09.2005, 06:49
Der Thread im Link von @hl_angel ist offenbar unvollständig.
Pollen ist in Fall einer seriellen Kommunikation schlecht, da hilft auch die Herabsetzung der Priorität nicht viel. Besser ist es, im Thread auf das Empfangen eines(mehrer) Bytes zu warten mit WaitForSingleObjekt(...).

Im folgenden Beispiel wird im Empfangsthread (ComThread) mit WaitForSingleObjekt(...) auf Ereignisse an der seriellen Schnittstelle gewartet. Auf alle muß man natürlich nicht warten, EV_RXCHAR reicht schon. Die Priorität wird hier sogar noch erhöht, um ja auch alles sofort mitzubekommen (hier wird die Zeit gemessen), ohne daß das System damit ausgebremst wird! Und wie die Datenübergabe an den ComThread funktioniert, ist auch in diesem Beispiel zu sehen.
Der Monitorthread ist nicht nowendig, die Ereignisse und Daten vom seriellen Port könne auch anderwohin gesendet werden. ABER: die Verarbeitung der Daten sollte natürlich NICHT im ComThread (oder einer von ihm aufgerufenen Funktion/Klasse) erfolgen, sondern immer gleich (in eine Message-Queue) weggeschrieben und woanders verarbeitet werden.


/************************************************** **********
** CommThread : Öffnet, schließt und liest den Port,
** sendet die Zeiten per PostThreadMessage
** an den MonitorThread
************************************************** **********/

#include <windows.h>
#include <process.h>
#include <stdio.h>


// Prototypes:
DWORD WINAPI ComThread (LPVOID lpParam);
DWORD WINAPI MonitorThread (LPVOID lpParam);
HANDLE StartComThread (DWORD iPortNum, HWND hEdit);
long queryPrecisionTime (void);
long queryPrecisionTimeStamp (void);

// Globals:
HANDLE hCom = INVALID_HANDLE_VALUE;

// global struc contains parameter for threads
typedef struct
{
volatile BOOL ThreadStoppen;
volatile int iComPortNum;
volatile DWORD dwMonitorThreadId;
} PARAMS, *PPARAMS;

static HANDLE hEvent;

// Message types
#define MSG_MIN_RANGE 0
// Der Message-Type für PostThreadMessage setzt sich aus
// QS_ALLPOSTMESSAGE (=256) und dem eigenem Message-Type
// (siehe MSG_xxxxxxx) zusammen.
// Mit MSG_MIN_RANGE können verschiedene Gruppen bei
// Bedarf gebildet werden.
#define MSG_TIME MSG_MIN_RANGE + 1000 // vom ComThread
#define MSG_TRIG MSG_MIN_RANGE + 2000 // reserviert
#define MSG_COMOPEN MSG_TRIG + 4
#define MSG_COMCLOSE MSG_TRIG + 5

#define QEVENT "QueueEvent"


//--------------------------------------------------------------------
// COMThread
//
// erstellt eine Queue, setzt danach den Event ("Queue ist ready").
// Schließt eine geöffneten COM-Port und öffnet den neuen (Nummer ist
// in der Strukur, auf die lpParam zeigt).
// liest die queue aus.
//
// Thread Funktion
// Liest eventgesteuert den Status von CTS, DSR, ... ein und
// sendet in dwEvtMask alle zum Event gehörenden Ereignisse
// zum Monitor-Thread.
//
//--------------------------------------------------------------------
DWORD WINAPI ComThread (LPVOID lpParam)
{
long lTime;
volatile PPARAMS pparams; // struct-Instanz
pparams = (PPARAMS) lpParam; // Zuweisung zu lpParam
int iPortNum = pparams->iComPortNum; // ...
DWORD dwMonitorThreadId = pparams->dwMonitorThreadId; // ...
char szPort[15];
static OVERLAPPED o;
// Maske für SetCommMask, die bestimmt, welche Ereignisse auftreten können
DWORD dwEvtMaskIn = EV_CTS | EV_DSR | EV_BREAK | EV_RING | EV_RXCHAR |
EV_RLSD | EV_ERR | EV_RXFLAG | EV_TXEMPTY;
DWORD dwEvtMask = 0; // Maske, in die WaitCommEvent aktuelle Werte schreibt
BOOL bRet;

CloseHandle (hCom); // "alten" COM-Port schließen

// Com Port öffnen
wsprintf (szPort, "COM%d", iPortNum);
hCom = CreateFile (szPort,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attributes
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);

if (hCom == INVALID_HANDLE_VALUE)
{
LPVOID lpMsgBuf;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL);
MessageBox (NULL, (LPCTSTR)lpMsgBuf, TEXT("ComThread: error: CreateFile()"),
MB_OK | MB_ICONINFORMATION);
LocalFree (lpMsgBuf);
pparams->ThreadStoppen = TRUE;
}
else
{
if (!SetCommMask (hCom, dwEvtMaskIn))
MessageBox (NULL, "SetCommMask fehlgeschlagen", "COM Port:", MB_OK | MB_ICONSTOP);

// Create an event object for use in WaitCommEvent.
o.hEvent = CreateEvent (NULL, // no security attributes
FALSE, // auto reset event
FALSE, // not signaled
NULL); // no name
}

// Setzt die Priorität "RealTime" für das Programm
DWORD dwProcessId; // own process identifier
HANDLE hProcess; // handle to the own process
DWORD dwDesiredAccess = PROCESS_SET_INFORMATION; // access flag
BOOL bInheritHandle = TRUE; // handle inheritance flag
BOOL bReturn; // If the SetPriorityClass succeeds, then nonzero
DWORD dwPriorityClass = HIGH_PRIORITY_CLASS;

dwProcessId = GetCurrentProcessId ();
hProcess = OpenProcess (dwDesiredAccess, bInheritHandle, dwProcessId);
bReturn = SetPriorityClass (hProcess, dwPriorityClass);

printf ("\r\nComThread: %s geöffnet, warte auf Events ...", szPort);

// eine message zum Monitor-Thread senden:
bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMOPEN),
(WPARAM)iPortNum , (LPARAM)0);

// Auf Events warten:
while (!pparams->ThreadStoppen) // solange weitermachen bis TRUE
{
WaitCommEvent (hCom, &dwEvtMask, &o); // EventMask "scharf machen"
// kommt der Event, ist auch die dwEvtMask geladen und es kann weitergehen
if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
{
lTime = queryPrecisionTimeStamp (); // Zeit holen
// Message senden. In dwEvtMask können mehrere Ereignisse gesetzt sein
bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_TIME),
(WPARAM)dwEvtMask , (LPARAM)lTime);
} // end of: if (WAIT_OBJECT_0 == ...
} // end of: while (...

CloseHandle (o.hEvent);
CloseHandle (hCom); // COM-Port schließen

printf ("\r\nComThread: %s geschlossen", szPort);

bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMCLOSE),
(WPARAM)iPortNum , (LPARAM)0);

return (0);
}


//----------------------------------------------------------------------------
// MonitorThread
//
// erstellt eine Queue, setzt danach den Event und liest
// die queue aus
//----------------------------------------------------------------------------
DWORD WINAPI MonitorThread (LPVOID lpParam)
{
static char szMsg[255] = "";
static char szMsgTmp[30] = "";
int i = 0;
BOOL bRet;
MSG msg;
volatile PPARAMS pparams; // struct-Instanz
pparams = (PPARAMS) lpParam; // Zuweisung zu lpParam

DWORD COMStatus;


// create a queue for the thread
PeekMessage ((LPMSG)&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// sent event after queue creation back to the threads creator
bRet = SetEvent (hEvent);

printf ("\r\nMonitorThread: warte auf Events ...");

// get messages by message from threads local queue
while ((bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{ // handle the error and possibly exit
MessageBox (NULL, "MonitorThread: GetMessage error", "COM Port:", MB_OK | MB_ICONSTOP);
return NULL; // error!
}
else
{ // a valid message is received
switch (msg.message)
{
case (QS_ALLPOSTMESSAGE + MSG_COMOPEN):
printf ("\r\nMonitorThread: MSG_COMOPEN: lParam=0x%08x wParam=0x%08x",
msg.lParam, msg.wParam);
break;

case (QS_ALLPOSTMESSAGE + MSG_COMCLOSE):
printf ("\r\nMonitorThread: MSG_COMCLOSE: lParam=0x%08x wParam=0x%08x",
msg.lParam, msg.wParam);
break;

case (QS_ALLPOSTMESSAGE + MSG_TIME):
// Time stamp message: lParam=time, wParam=dwEvtMask
szMsg[0] = '\0';

if (DWORD(msg.wParam) & EV_CTS)
{
GetCommModemStatus (hCom, &COMStatus);
if (COMStatus & MS_CTS_ON)
{ // CTS (Pin8) activated
wsprintf (szMsgTmp, "\r\nCTS_ON : %lu µs", msg.lParam);
}
else
{ // CTS (Pin8) deactivated
wsprintf (szMsgTmp, "\r\nCTS_OFF: %lu µs", msg.lParam);
}
strcat (szMsg, szMsgTmp);
}

if (DWORD(msg.wParam) & EV_DSR)
{
GetCommModemStatus (hCom, &COMStatus);
if (COMStatus & MS_DSR_ON)
{ // DSR (Pin6) activated
wsprintf (szMsgTmp, "\r\nDSR_ON : %lu µs", msg.lParam);
}
else
{ // DSR (Pin6) deactivated
wsprintf (szMsgTmp, "\r\nDSR_OFF: %lu µs", msg.lParam);
}
strcat (szMsg, szMsgTmp);
}

if (DWORD(msg.wParam) & EV_RLSD)
{
GetCommModemStatus (hCom, &COMStatus);
if (COMStatus & MS_RLSD_ON)
{ // DCD (Pin1) activated
wsprintf (szMsgTmp, "\r\nRLSD_ON: %lu µs", msg.lParam);
}
else
{ // DCD (Pin1) deactivated
wsprintf (szMsgTmp, "\r\nRLSD_OFF: %lu µs ", msg.lParam);
}
strcat (szMsg, szMsgTmp);
}

if (DWORD(msg.wParam) & EV_RING)
{
GetCommModemStatus (hCom, &COMStatus);
if ((COMStatus & MS_RING_ON))
{ // RI (Pin9) activated
wsprintf (szMsgTmp, "\r\nRING_ON: %lu µs", msg.lParam);
}
else
{ // RI (Pin9) deactivated
wsprintf (szMsgTmp, "\r\nRING_OFF: %lu µs", msg.lParam);
}
strcat (szMsg, szMsgTmp);
}

printf (szMsg);
break;

default:
wsprintf (szMsg, "\r\nMonitorThread: default: lParam=0x%08x wParam=0x%08x message=0x%08x",
msg.lParam, msg.wParam, msg.message);
MessageBox (NULL, (LPCTSTR)szMsg, "COM Port:", MB_OK | MB_ICONSTOP);
break;
} // end of: switch (msg.message)
} // end of: if (bRet == -1) else ...
} // end of: while((bRet = GetMessage(...

printf ("\r\nMonitorThread: beendet");
return 0;
}


// Globale Variablen
// struct für Zeitmessung
union ut_LargeInteger
{
LARGE_INTEGER o_WinPart;
ULONGLONG l_MyPart;
};

int i_ResetPrecisionTime = 0;
ULONGLONG l_PerfFrequ;
ut_LargeInteger uo_PerfCount;

/************************************************** **********************
Die Funktion queryPrecisionTimeStamp () liefert die seit dem Start des PC
verstrichene Zeit in Mikrosekunden.
************************************************** **********************/
long queryPrecisionTimeStamp (void)
{
if (i_ResetPrecisionTime == 0)
{
i_ResetPrecisionTime = 1;
QueryPerformanceFrequency (&uo_PerfCount.o_WinPart);
l_PerfFrequ = uo_PerfCount.l_MyPart;
}

ut_LargeInteger uo_perfCount;
QueryPerformanceCounter (&uo_perfCount.o_WinPart);
return (long) (uo_perfCount.l_MyPart * 1000000 / l_PerfFrequ);
}

// ************************************************** *******************
int main (void)
{
DWORD dwMonThreadId;
DWORD dwComThreadId;
HANDLE hMonThread;
HANDLE hComThread;
DWORD dwState;
PARAMS p;

// MonitorThread erstellen:
// Erstellt den Event für die Thread Queue
hEvent = CreateEvent (NULL, false, true, QEVENT);
// Thread starten und uMonThreadID für ComThread merken
hMonThread = CreateThread ( // Handle des Threads
NULL, // no security attributes
0, // use default stack size
MonitorThread, // thread function
&p, // argument to thread function
0, // use default creation flags
&dwMonThreadId); // returns the thread identifier

if (hMonThread == NULL)
printf ("\r\nCreateThread (MonitorThread) fehlgeschlagen");

p.dwMonitorThreadId = dwMonThreadId; // merken, für ComThread

// wait for queue completition
dwState = WaitForSingleObject (hEvent, 100);
CloseHandle (hEvent);

// "alten" Thread stoppen
p.ThreadStoppen = TRUE;
CloseHandle (hComThread); // "alten" Thread stoppen
p.iComPortNum = 1;
// ComThread: Starten und Parameterstruct übergeben
p.ThreadStoppen = FALSE;
hComThread = CreateThread ( // Handle des Threads
NULL, // no security attributes
0, // use default stack size
ComThread, // thread function
&p, // argument to thread function
0, // use default creation flags
&dwComThreadId); // returns the thread identifier

if (hComThread == NULL)
printf ("\r\nCreateThread (ComThread) fehlgeschlagen");

Sleep (30000); // nur so zum Test

CloseHandle (hMonThread); // MonitorThread beenden
CloseHandle (hComThread); // ComThread beenden

return (0);
}

Anpassen an die Borland-Sytax/Notation sollte nicht schwer sein.

Blackbird

NumberFive
09.09.2005, 06:52
@Blackbrid

Ich hätte mir den link angucken sollen wer pollt der bei der serialen.
man dann verstehe ich das zu den verzögerungen kommt.

Gruß

Blackbird
09.09.2005, 07:02
Nicht nur beim Lesen der seriellen Schnittstelle sollte man nicht pollen, sondern auch beim Datei lesen. Geht genauso. Und beim Schreiben ebenfalls mit "overlapped" Funktionen arbeiten, damit nicht der Programmablauf in dieser Zeit blockiert ist. Ist besonders wichtig bei großen Datenmengen (seriell wie auch Datei) und vielen Schreib-Lese-Operationen. Das bringt richtig Speed!

Blackbird

NumberFive
09.09.2005, 07:06
Datei lesen tut ich selten schon garnicht im robi.
wenn ich daten holen dann meintesn eine DB.
Und für die logs schreibe ich eh per thread.

Gruß

Blackbird
09.09.2005, 07:20
Der Fragesteller hat das Prog ja auch auf einen PC laufen, nicht im Bot. Würde im Bot ein Mainbord mit Windows laufen, gelten die Ausführungen dann aber auch dort.
Dateien müssen nicht unbedingt auf einer HDD, CD oder Floppy liegen ;)

Blackbird

NumberFive
09.09.2005, 07:27
bei mir ist das so windows PC im bot *g*

surfer
14.09.2005, 07:32
OK. Ich hab vielleicht den Anfängerfehler gemacht und auf globale Variabeln, bzw. auf Elemente zugegriffen.
Wie funktioniert denn das mit dem Synchronisieren?

NumberFive
14.09.2005, 07:47
procedureTMyThread.PushTheButton;

begin
Button1.Click;
end;
...
procedure TMyThread.Execute;
begin
....
Synchronize(PushTheButton);
...
end;


ist zwar ein deplhi beispiel aber im Borland C++ gibt es den meines wissens auch.

Denke daber dran das den code auf hält bis sync erreicht.

welche daten will du den vom Thread an das fenster schicken
geht das nicht vielleicht besser mit PostMessage ?

Gruß

surfer
14.09.2005, 08:44
ich möchte das am COM-Port empfangene char im hauptprogramm weiterverarbeiten. Z.B. an einem Memo anzeigen lassen...

NumberFive
14.09.2005, 08:50
wenn es nur ein char ist mach es mit postmessage ist besser

PostMessage(<festerhandle>,WM_USER+X,NULL,CHAR);

im Form dann muß du die Funktion des Message handler über schreiben




procedure AppMessages(var Msg: Tmsg; var Handled: Boolean);
....
procedure TMainForm.AppMessages(var Msg: Tmsg; var Handled: Boolean);
// Eigener Messages Handler
begin
if not Handled then
begin
if Msg.message = WM_USER+X then
begin
HandleBuffer(Msg.lParam);
Handled := true;
end;
end;
end;


Gruß

ELECTRIC
14.09.2005, 09:56
Hast du es schon mal mit einem Trminel Programm versucht?
Schau mal auf www.emtec.com lade das Terminel Program zoc herunter.

gruß tobias

NumberFive
14.09.2005, 10:10
was nutzt mir ein Terminal programm wenn ich die Daten weiter verarbeiten will ?

Gruß

Blackbird
14.09.2005, 10:15
Und wenn das Hauptprogramm ein Windows-Fenster ist und Du sehr viele Bytes zu senden hast, kannst Du ein Editfeld (sichtbar oder auch nicht) erstellen und mit:


// Text an die Editbox anhängen:
// 1. an das Ende springen
SendMessage (hwndEdit, EM_SETSEL, (WPARAM)-2, (LPARAM)-2);
// 2. Text anhängen
SendMessage (hwndEdit, EM_REPLACESEL, (WPARAM)0 , (int)szText);

das Editfeld mit szText beschreiben, weil diese Messages in eine Queue gehen.
Geht natürlich nur bei ASCII-Zeichen.

Bei Binär-Daten kannst Du Dir einen eigene Linked List anlegen, in der jede Message eine neues Element ist (und nach dem Lesen wieder freigegeben wird) oder Du erstellst einen Socket und tauschst die Daten per UDP zwischen dem COM-Empfangs-Thread und dem Hauptprogramm aus.

Blackbird

ELECTRIC
14.09.2005, 10:16
Du kannst die die Daten die du über das Terminal program einlist sehr wohl weiterverarbeiten.
tobias

NumberFive
14.09.2005, 10:30
@Blackbird warum so kompliziert ?

kann doch einfach auch einer Pointer macher auf ein array of byte
und den per nachricht verschicken. Geht wunderbar mach ich den ganzen tag.

Also im thread:

buffer = new byte[3];
buffer[1] = 1;
buffer[2] = 2;
buffer[3] = 3;

PostMessage(<fensterhandle>,WM_USER,NULL,(long)buffer);

im Fenster

if Msg = WM_USER then
byte* buffer = (byte*) LPARAM;
// daten ver arbeiten
delete buffer
end if

gruß

surfer
14.09.2005, 10:43
Danke für die Antworten, jedoch müsst ihr wissen, dass ich bis jetzt immer am "Messagen" versuchen war, jedoch total nicht durchblicke...
Ich habe Blackbirds Code übernommen, jedoch reklamiert der Builder wegen dem hwindEdit1 (Bei mir heisst das Editfeld Edit1... darum habe ichs geändert... weiss nicht ob man das darf...)
Ich weisss eben lustigerweise auch nicht was ein Handler ist...

Hoffentlich könnt ihr mir trotzdem helfen... ;-)

Blackbird
14.09.2005, 11:52
@surfer,
hwndEdit ist das Handle des Editfeldes, das beim Erstellen des Editfeldes mit
HANDLE hwndEdit = CreateWindows(...);
zurückgeliefert wird.

@NumberFive,
machen kann man das, aber ich code um's Verrecken nicht mehr getrennte new-delete-Paare.

Blackbird

surfer
14.09.2005, 12:02
Bei mir gibt es aber wegen dem hwndEdit1 ein Fehler...???

NumberFive
14.09.2005, 13:08
@Blackbird warum nicht ?

Das Sendmessage hält aber den Thread auf.

@surfer

ein handle ist die Fenterszugriffszahl und es mal ganz einfach aus zu drücken.

Wenn du eine edit box auch den Dialog mal's müsste er eingebdlich eine einegendschaft Handle haben das ist dann der wert für hwndEdit1

die Variable kannst du dann bei thread start zu weisen.

Gruß

surfer
14.09.2005, 13:29
Ich kann zwar auf die Eigenschaft "Handle" zugreifen, jedoch was ich auch reinschreibe (z.B. Edit1->Handle=testhandle) gibt es Fehler....

Ich weiss, dass ich das total falsch mache, jedoch kenne ich mit diesem Zeugs halt total nicht aus :-)

NumberFive
14.09.2005, 13:35
anders rumist richtig das handle raus lesen und dem thread geben.
testhandle = Edit1->Handle;


SendMessage (testhandle, EM_SETSEL, (WPARAM)-2, (LPARAM)-2);

Gruß

surfer
14.09.2005, 13:51
OK. Ich habe jetzt mal ein Testprogramm erstellt, ohne Threads...
Meiner Meinung nach sollte jetzt bei Tastendruck der Buchstabe f ins Textfeld geschrieben werden, was es aber nicht macht...?



HANDLE testhandle;
char test;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
testhandle=Edit1->Handle;
test='f' ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
SendMessage (testhandle, EM_SETSEL, (WPARAM)-2, (LPARAM)-2);
SendMessage (testhandle, EM_REPLACESEL, (WPARAM)0 , (int)test);
}
//---------------------------------------------------------------------------

NumberFive
14.09.2005, 14:00
ja beim button drücken sollte was rein geschrieben werden.

Setzt mal die eigendschaft test so das im edit feld was drin steht wenn
der dialog auf geht dann soll das tun.

den EM_REPLACESEL ersetzt den markierten text aber wenn da nix markiert ist kann er auch nicht ersetzen.

Gruß

surfer
14.09.2005, 14:16
Aha... Ein einzelnes Char geht nicht... muss ein String sein, der geschickt wird...
Und was muss ich jetzt dabei ändern, dass ich ein PostMessage habe. Eben dass der Thread nicht unterbrochen wird?
Ich finde nämlich BlackBirds Idee nicht schlecht es im Edit anzeigen zu lassen... Werde dann eher ein Memo nehmen, aber egal...
Habe einfach mal aus dem SendMessage das PostMessage drausgemacht, aber dann geht es nicht mer :-(

Ach ja... Danke vielmals für deine schnelle Hilfe!!! (Ist auch nicht das erste Mal) =D> :Weihnacht

NumberFive
14.09.2005, 14:55
PostMessage geht nicht mit Steuerelement ist halt so in windows.

Da hast du keine Chance da geht nur mein Lösung.

Probier doch mal ob der zeit verlust so tragisch ist. SendMessage ist ein kern Funktion und so mit sehr schnell.

Gruß

surfer
14.09.2005, 14:57
OK... werds versuchen...

surfer
14.09.2005, 15:26
Aaalllssooooo!!
Jetzt läufts eigentlich wirklich ganz schön dank all euren Tipps!!!

Ich brauche für die Wertübergabe ans Memo das SendMessage...
Jedoch hatte ich dann immer noch erhebliche Verzögerungen auch mit der Priorität tpLowest.... Dann habe ich noch gesehen, dass es ja auch noch die Priorität tpIdle gibt... Mit dieser funktioniert jetzt alles TipTop ohne Verzögerung!!!
Senden&Empfangen---Einfach tolll!!!!

DANKE vielmals an alle!!!
Merci

NumberFive
14.09.2005, 15:35
na den gutes gelingen für den rest

NumberFive
15.09.2005, 14:29
mir ist da noch was auf gefallen warum muß du den thread von der prio so weit runter setzen ?

eingendlich draf der thread nur laufen wenn auf der com was kommt.

Poste doch mal den Teil von source

schon mal mit SetCommMask und WaitCommEvent probiert ?

Gruß