Avatar billede tje Nybegynder
31. juli 2003 - 16:12 Der er 8 kommentarer

WriteFile returnere false

Jeg er igang med at lære at bruge seriel porten.
Jeg har lavet et loopback-kabel, således at jeg kører hyperterminal på COM2, og mit test program på com1.

Mit program sender også fint nok, når strengene ikke er så lange, men den streng jeg bruger nu fylder 16 bytes, og
bliver kun sendt til og med 'e'.
Under min fejlsøgning, fandt jeg ud af at writefile og GetOverlappedResult returnere false. Når jeg kalder GetLastError, får jeg bare false.

Her er min rutine....
//-----------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
DCB dcb;
COMMTIMEOUTS TimeOuts;
COMMPROP CommProperties;
HANDLE hComport;
unsigned long Written;
OVERLAPPED OverLapped;
unsigned char Buffer[]={'1','2','3','4','5','6','7','8','9',
                        'a','b','c','d','e','f',0};


hComport = INVALID_HANDLE_VALUE;
hComport = CreateFile(
                "COM1",
                GENERIC_READ+GENERIC_WRITE,
                0, // must be opened with exclusive-access
                0, //no security
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);


if (hComport==INVALID_HANDLE_VALUE){
        Button1->Caption="handle error";
        }

else    {
        GetCommState(hComport,&dcb);
        GetCommProperties(hComport,&CommProperties);
        GetCommTimeouts(hComport,&TimeOuts);

        dcb.BaudRate = 9600;
        dcb.Parity = NOPARITY;
        dcb.StopBits = ONESTOPBIT;
        dcb.ByteSize = 8;

        SetCommState(hComport,&dcb);

        ZeroMemory(&TimeOuts,sizeof(TimeOuts));

        TimeOuts.ReadIntervalTimeout = DWORD(0xFFFFFFFF);
        TimeOuts.WriteTotalTimeoutMultiplier = 0;
        TimeOuts.WriteTotalTimeoutConstant = 0;

        SetCommTimeouts(hComport,&TimeOuts);

        ZeroMemory(&OverLapped,sizeof(OverLapped));

        Edit1->Text=WriteFile(
                hComport,
                &Buffer,
                (unsigned long) sizeof(Buffer),
                &Written,
                &OverLapped);

        Edit2->Text=GetLastError();

        Edit3->Text=GetOverlappedResult(hComport,&OverLapped,&Written,false);

        CloseHandle(hComport);
        }
}
Avatar billede bertelbrander Praktikant
01. august 2003 - 00:37 #1
Har du testet indholdet af Written efter kaldet til WriteFile?
Har du prøvet at gøre det uden FILE_FLAG_OVERLAPPED?

Jeg har ikke prøvet at bruge FILE_FLAG_OVERLAPPED men i min dokumentation (MSDN) står der:

"If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the write operation starts at the offset specified in the OVERLAPPED structure and WriteFile may return before the write operation has been completed. In this case, WriteFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING. This allows the calling process to continue processing while the write operation is being completed. The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the write operation."

Det betyder så vidt jeg kan læse at du skal kalde WriteFile igen for at få sendt resten, hvis den ikke sender det hele første gang.
Avatar billede segmose Nybegynder
01. august 2003 - 09:04 #2
Efter første kald er hele sende FIFO'en i seriel chippen (UART, sikkert en 16550 med 16 byte FIFO) nok fuld, det der defineres i OVERLAPPED er nok en callback der activeres når seriel chippen er færdig med at sende de førte 16 byte.
Kalder du igen omgående fil du sikkert kun få skrevet en eller nul byte extra da UART'en ikke har nået at få sendt så meget, ved 9600 baud tager det ca. 1ms at få sendt en byte.
Avatar billede tje Nybegynder
01. august 2003 - 11:52 #3
Her kommer mine C kundskaber til kort, hvordan laver man løkke, som tester osv.
Jeg har prøvet en while løkke, men det låser programmet, men til gengæld for jeg fyldt hele min hyperterminal med hele strengen også de før manglende bytes.
Avatar billede segmose Nybegynder
01. august 2003 - 12:46 #4
Du skal enten fjerne FILE_FLAG_OVERLAPPED så den blokkere indtil det hele er skrevet eller kikke noget mere på hvad

OVERLAPPED OverLapped;

gør for dig, jeg kunne forstå på Bertel's kommentar at det var muligt at få et svar tilbage når alt var sendt.

ps. Er Written 14 eller 16 efter kaldet? det er ikke i modtage enden den er gal?
Avatar billede tje Nybegynder
01. august 2003 - 13:55 #5
Jeg har løst problemet.

Når Handlen lukkes, inden alt er sendt går dataen tabt. Jeg har løst det ved at lave en while(!GetOverLappedResult). Når GetOverLappedResult returner en høj, er det fordi hele strengen er sendt.
Så slutningen af koden kom til at se ud som flg...
----------------------------------------
        Edit1->Text=WriteFile(
                hComport,
                &Buffer,
                (unsigned long) sizeof(Buffer),
                &Written,
                &OverLapped);

        Edit2->Text=GetLastError();

        while(!GetOverlappedResult(hComport,&OverLapped,&Written,false));

        Edit3->Text=GetOverlappedResult(hComport,&OverLapped,&Written,false);


        CloseHandle(hComport);
Avatar billede bertelbrander Praktikant
01. august 2003 - 17:00 #6
Der er så vidt jeg kan ikke se nogen grund til at bruge overlapped skrivning, når du alligevel blot venter på at den er færdig med en while loop.
Er pointen med overlapped ikke at man kan lave andet mens man venter på at den skriver?
Avatar billede tje Nybegynder
01. august 2003 - 17:27 #7
Jo. Programmet er kun lavet for at lære skidtet at kende.!
Avatar billede soepro Nybegynder
05. august 2003 - 10:10 #8
tje >> I fht. brugen af overlapped kommunikation, er det netop også sådan som du gør, det også anbefales at man skal gøre. På http://msdn.microsoft.com/library/en-us/dnwbgen/html/msdn_serial.asp?frame=true findes en længere, og god artikel om hvordan man laver seriel kommunikation, og særligt forskellen mellem Overlapped og non-overlapped kommunikation.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester