PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART-Synchronisation (like Interrupt) am PC



surfer
12.02.2005, 10:45
HalloHallo...

Ich habe mir in Borland C++ ein Programm zur RS232 Kommunikation geschrieben. Funktioniert eigentlich ganz gut...
Nur leider gibt es ein klitzekleines Problemchen :-)

Zum Vergleich: Auf dem uC wird bei UART Empfang ein Interrupt ausgelöst -- Beim PC gibt es meines Wissens nach keine Empfangsinterrupts (wenn ja, wäre mein Problem gelöst...), daher habe ich einfach einen Timer eingebaut, der jede 10ms den COMPort liest. Jetzt das Problem: wenn etwas vom uC genau dann gesendet wird, wenn der Timer halt eben nicht aktiv ist, dann werden einige Zeichen abgeschnitten... Das heisst, dass die Kommunikation nicht synchron ist...

Wie könnte ich dieses Problem lösen, ohnen den Timer extrem herunterzusetzen?

Danke

MfG Surfer

NumberFive
12.02.2005, 11:10
naja einen interrupt gibt es nicht ganz aber es gibt eine Wait funktion.

ich denke du programmierst unter windows sonst brauchst du nicht weiter lesen.




//init
m_hCOM = CreateFile(m_csCOM.operator LPCTSTR(),GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLA PPED,NULL);
if(m_hCOM == INVALID_HANDLE_VALUE)
{
return false;
}

// lesen
ReadFile(m_hCOM,Buffer,1,&readen,&o);
WaitForSingleObject(o.hEvent,INFINITE);
GetOverlappedResult(m_hCOM,&o,&Bytes,FALSE);




Das waitforsingeleObject kommt erst zurrück wenn ein zeichen geslesen wurde.

Gruß

surfer
12.02.2005, 12:12
Das tönt schon recht gut... aber ist das auch unabhängig von anderen Prozessen, so wie der Timer... also das es dann nicht an dieser Programmstelle wartet, bis das Signal kommt. Alle anderen Funktionen im Programm müssen normal weiterlaufen können...

NumberFive
12.02.2005, 16:05
dann mach halt eine thread draus so ist das eh üblich bei sollchen sachen.
jetzt serial komunikation ist gethreadet.

Gruß

surfer
18.02.2005, 07:56
Also... Ich hab jetzt mal das ganze Programm versucht zu schreiben.
Habe die Overlapped-Abfrage in einen Thread gesteckt...
Nun habe ich nur das Problem, dass sobald ich im CreateFile das Attribut "FILE_FLAG_OVERLAPPED" setze, funktioniert die ganze Kommunikation nicht mehr. Ich kann den Port auch nicht mehr richtig schliessen. Ich schicke mal den Code... vielleich siehst du einen Fehler...


//---------------------------------------------------------------------------
DWORD WINAPI Datenthread( LPVOID lpParam )
{
while(threading)
{
ReadFile(hComm, buffer, 10, &dwBytesRead, NULL);
WaitForSingleObject(hComm,INFINITE);
GetOverlappedResult(hComm,NULL,&dwBytesRead,FALSE);
Form2->Memo1->Text=dwBytesRead;
}

return 0;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(active==false&&ComboBox1->ItemIndex!=-1&&ComboBox2->ItemIndex!=-1)
{
DCB dcbCommPort;

hComm = CreateFile(com,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, //<-- Da will es nicht so ganz...
NULL);


if(hComm == INVALID_HANDLE_VALUE) Application->MessageBox(" !! Bitte anderen Port wählen !! \n\n Der gewählte Port wird schon\nvon einem anderem Programm\n benutzt oder existiert nicht."," .........::: Portfehler :::.........",MB_OK);
else
{
Form2->Visible=true;
threading=true;
hThread=CreateThread(NULL,0,Datenthread,&dwThrdParam,0,&dwThreadId);
active=true;
Button1->Enabled=false;
Button2->Enabled=true;

StatusBar1->Panels->Items[3]->Text="Status: geöffnet";
}
GetCommTimeouts(hComm,&ctmoOld);
ctmoNew.ReadTotalTimeoutConstant = 100;
ctmoNew.ReadTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &ctmoNew);

dcbCommPort.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcbCommPort);

switch(ComboBox2->ItemIndex)
{
case 0: BuildCommDCB("110,N,8,1", &dcbCommPort); break;
case 1: BuildCommDCB("300,N,8,1", &dcbCommPort); break;
case 2: BuildCommDCB("1200,N,8,1", &dcbCommPort); break;
case 3: BuildCommDCB("2400,N,8,1", &dcbCommPort); break;
case 4: BuildCommDCB("4800,N,8,1", &dcbCommPort); break;
case 5: BuildCommDCB("9600,N,8,1", &dcbCommPort); break;
case 6: BuildCommDCB("19200,N,8,1", &dcbCommPort); break;
case 7: BuildCommDCB("38400,N,8,1", &dcbCommPort); break;
case 8: BuildCommDCB("57600,N,8,1", &dcbCommPort); break;
case 9: BuildCommDCB("115200,N,8,1", &dcbCommPort); break;
case 10: BuildCommDCB("230400,N,8,1", &dcbCommPort); break;
case 11: BuildCommDCB("460800,N,8,1", &dcbCommPort); break;
case 12: BuildCommDCB("921600,N,8,1", &dcbCommPort); break;
default: Application->Terminate(); break;
}

SetCommState(hComm, &dcbCommPort);
}
}

engineer
18.02.2005, 09:12
Das darf eigentlich nicht sein. Bei korrektem Betrieb tauchst Du nur ein eine Leseroutone ein, welche den aktuellen seriellen Buffer solange ausliest, wie nichts mehr komt, also kein Zeichen ansteht. Ich time solche Zugriffe so, daß ich immer mindestens ein Zeichen vorfinde, aber der Buffer immer geleert werden kann, also nie mehr als z.B. 20 Zeichen reingeschrieben wurden. Das ist am effizientesten.

Eine Leseroutine samt Tinitialisierung findest Du auf meiner Hp, bzw kann ich Dir senden.

surfer
18.02.2005, 09:20
Wäre nett, wenn du sie mir schicken könntest! Danke

NumberFive
18.02.2005, 10:41
Hallo surfer,

in dem Read muß du auch die Overlapp strucktur mit übergeben.
und du drafs von ein thread nicht so auf obflächen element zu greifen
das gibt schutz verletzungen. es gibt bei Borland den sync befehlt für so was
aber ich persöhnlich mache es immer über nachrichten. da ich mit MS C++ arbeite da gibt es keine VCL.

zum beenden muß du dann das evnet aus lösen. und die variable setzen dann sollte sich der thread beenden und du kannst die com schliesen.

Gruß

surfer
18.02.2005, 10:44
Tja, NumberFive... Ich muss gestehen, irgendwie ist mir das ein bisschen zu viel... Ich bin halt nicht so ein C++ Genie...

Wie kann ich die Overlapp-Struktur übergeben?
Soll ich im Thread einfach ein Unterprogramm aufrufen lassen?

engineer
18.02.2005, 12:02
Hier ist der link:
http://home.arcor.de/juergen.schuhmacher/pdf/spmdwx.pdf

Ich hoffe, es ist das aktualisierte.

surfer
18.02.2005, 12:11
Sorry, aber bei Read und Write Operations steht nur "To follow..."

Hab sonst nichts gefunden???

NumberFive
22.02.2005, 00:11
hallo Surfer,

ohne overlapped:

ReadFile(hComm, buffer, 10, &dwBytesRead, NULL);

mit overlapped :

ReadFile(hComm, buffer, 10, &dwBytesRead, &Overlapped);

Es müsste bei dir einen Typ geben TOverlapped

jetzt muß du nur noch ein handle in die structure packen.




OVERLAPPED o;
....

m_hCOM = CreateFile(m_csCOM.operator LPCTSTR(),GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLA PPED,NULL);
if(m_hCOM == INVALID_HANDLE_VALUE)
{
return false;
}
....

o.hEvent = CreateEvent(
NULL, // default security attributes
FALSE, // auto reset event
FALSE, // not signaled
NULL // no name
);




ich hoffe es hilft dir

surfer
23.02.2005, 07:08
OK, Danke vielmals... läuft jetzt! ;-). Jetzt müsste ich nur noch wissen, wie ich den Buffer leeren kann...

NumberFive
25.02.2005, 17:31
welchen buffer willst du leeren ?

surfer
25.02.2005, 18:44
Den Eingangsbuffer (ReadFile(hcomm,buffer<--diesen Buffer...)
Wenn ich einmalig z.B. ein x vom uC her sende, wird das x immer und immer wieder geschrieben, da wenn kein Eingangssignal reinkommt der letzte Eingangsbuffer verwendet wird...

NumberFive
25.02.2005, 19:28
buffer ist was für ein daten typ ?
declaration ?

surfer
25.02.2005, 19:51
char.... das ist ja einfach dort wo die Daten reinrasseln...
aber einfach "" reinschreiben bringt nichts, da es bei jedem "ReadFile" Vorgang wieder vollgeschrieben wird...

NumberFive
25.02.2005, 19:58
wenn in dem buffer was drin steht und
WaitForSingleObject(o.hEvent,INFINITE);

zu rückkommt hat die seriale auch was emfangen
oder in dem code ist noch ein fehler