Avatar billede henning-a Nybegynder
13. oktober 2005 - 14:35 Der er 6 kommentarer og
1 løsning

Com port: virker ikke 1. gang, men derefter ingen problem

Jeg har et problem med et program der skal udføre nogle tests på en Mikroprocessor.

Programmet virker egentlig fint nok, bare ikke første gang det bliver kørt.
Når den kører de tests, starter den med at bede om en acknowledge(?) fra MP'eren men den modtager ikke noget ack. Trykker du så på test igen, vil programmet fint afvikle testen uden problemer.

Her er koden der åbner COM porten:

/******************************************************/
HANDLE CPWTestDlg::GetComportHandle()
{

    OSVERSIONINFO OSversion;   

    OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
    ::GetVersionEx(&OSversion);   

    //char ComportString[5];
    CString ComportString;

    CComboBox* p_Combobox = (CComboBox*) GetDlgItem(IDC_COMBO1);
   
    if (p_Combobox->GetCurSel() == 1)
        //strcpy(ComportString, "COM2");
        ComportString="COM2";

    else if (p_Combobox->GetCurSel() == 0)
        //strcpy(ComportString, "COM1");
        ComportString="COM1";
   
    HANDLE hPort = CreateFile(ComportString,
                                GENERIC_READ | GENERIC_WRITE,
                                0,
                                0,
                                OPEN_EXISTING,
                                0,
                                0);

    if (hPort == INVALID_HANDLE_VALUE)
        MessageBox("Initializing comport failure!", "PW-Test Error Message", NULL);

    else
    {
        switch(OSversion.dwPlatformId)
        {
            case VER_PLATFORM_WIN32_NT: //If windows NT(2K/Xp) is deteceted
            {
                // Set DCB
                // DCB dcb;
                GetCommState(hPort, &dcb);

                dcb.BaudRate = CBR_19200;
                dcb.ByteSize = 8;
                dcb.fRtsControl = RTS_CONTROL_ENABLE;
                dcb.fOutxCtsFlow = 0;
                SetCommState(hPort, &dcb);
                dcb.Parity = NOPARITY;
                dcb.StopBits = ONESTOPBIT;

/*                GetCommState(hPort, &dcb);
                dcb.Parity = NOPARITY;
                dcb.StopBits = ONESTOPBIT;
                dcb.ByteSize = 8;
                dcb.BaudRate = CBR_19200;
                SetCommState(hPort, &dcb);
*/
                COMMTIMEOUTS CommTimeOut;
               
                GetCommTimeouts(hPort, &CommTimeOut);
               
                CommTimeOut.ReadIntervalTimeout        = MAXDWORD;
                CommTimeOut.ReadTotalTimeoutMultiplier = 2;
                CommTimeOut.ReadTotalTimeoutConstant  = 2;
                CommTimeOut.WriteTotalTimeoutMultiplier = 0;
                CommTimeOut.WriteTotalTimeoutConstant = 0;   
               
                if (!SetCommTimeouts(hPort, &CommTimeOut))
                    MessageBox("Setting CommTimeOut error!", "PW-Test Error Message", NULL);

                break;
           
            }

            //If older versions of windows is detected(windows98)
            case VER_PLATFORM_WIN32s || VER_PLATFORM_WIN32_WINDOWS:
            {
                // Set timeouts                
                COMMTIMEOUTS CommTimeOut;

                GetCommTimeouts(hPort, &CommTimeOut);

                CommTimeOut.ReadIntervalTimeout        = 0;
                CommTimeOut.ReadTotalTimeoutMultiplier = 2;
                CommTimeOut.ReadTotalTimeoutConstant  = 2;
               
                if (!SetCommTimeouts(hPort, &CommTimeOut))
                    MessageBox("Setting CommTimeOut error!", "PW-Test Error Message", NULL);

                // Set DCB
                DCB dcb;

                GetCommState(hPort, &dcb);
                BuildCommDCB("baud=19200 parity=N data=8 stop=1", &dcb);
                SetCommState(hPort, &dcb);               
               
                break;           
            }
           
            //If the windows version is unknown
            default:
            {
                AfxMessageBox("Unknown Windows version detected!", MB_ICONSTOP);
                break;

            }


        }
       
        EscapeCommFunction(hPort,CLRDTR);    // Turn off power to module
    }   
    return hPort;   
}

Det skal lige siges at det ikke er mig der har lavet programmet i sin tid, men er sat til at løse denne fejl :) Så bare with me, hvis jeg ikke lige kan svare på jeres spørgsmål, hvis i da har sådan nogle :D
Avatar billede driis Nybegynder
13. oktober 2005 - 15:24 #1
Hvis jeg skulle komme med et gæt, ville det være at man sender en besked til MP'en, og straks derefter forsøger at læse fra porten, uden at MP'en har haft tid til at svare.

Når du så kører programmet anden gang, er dataene løbet ind på porten og er klar til at blive læst.
Avatar billede henning-a Nybegynder
13. oktober 2005 - 16:29 #2
Har du nogen evt. løsning på det? Kan man sætte en wait ind i programmet?
Evt. Sleep(400) <-- jeg ved ikke helt om den kan bruges. måske?
Avatar billede driis Nybegynder
13. oktober 2005 - 18:34 #3
Ja, en Sleep vil typisk være det du bruger til at forsinke eksekvering i et Windows program. Det kan du så sætte ind lige efter der er blevet sendt data til enheden.
Avatar billede henning-a Nybegynder
14. oktober 2005 - 08:35 #4
:( Jeg prøvede lige at smide nogle Sleeps ind i koden. Sådan ser det ud:

void CPWTestDlg::OnButtonTestStart()
{
    HANDLE hPort;

    hPort = GetComportHandle();

    MessageBox("Sleeping 1 second after GetComporthandle", "Sleep message", NULL);
    Sleep(1000);

    if (hPort != INVALID_HANDLE_VALUE)
    {
        GetReceiveTime(set_time, receive);

        MessageBox("Sleeping 1 second before Test Start", "Sleep message", NULL);
        Sleep(1000);

        StartTest(hPort);
    }

    MessageBox("Sleeping 1 second before CloseHandle", "Sleep message", NULL);
    Sleep(1000);

    CloseHandle(hPort);
}


Jeg ved ikke helt om koden til opsætning af COM porten er helt rigtigt lavet :S
Den er her:

{
    OSVERSIONINFO OSversion;   

    OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
    ::GetVersionEx(&OSversion);   

    CString ComportString;

    CComboBox* p_Combobox = (CComboBox*) GetDlgItem(IDC_COMBO1);
   
    if (p_Combobox->GetCurSel() == 1)
        //strcpy(ComportString, "COM2");
        ComportString="COM2";

    else if (p_Combobox->GetCurSel() == 0)
        //strcpy(ComportString, "COM1");
        ComportString="COM1";
   
    HANDLE hPort = CreateFile(ComportString,
                                GENERIC_READ | GENERIC_WRITE,
                                0,
                                0,
                                OPEN_EXISTING,
                                0,
                                0);

    if (hPort == INVALID_HANDLE_VALUE)
        MessageBox("Initializing comport failure!", "PW-Test Error Message", NULL);

    else
    {
        switch(OSversion.dwPlatformId)
        {
            case VER_PLATFORM_WIN32_NT: //If windows NT(2K/Xp) is deteceted
            {
                // Set DCB
                // DCB dcb;
                GetCommState(hPort, &dcb);

                dcb.BaudRate = CBR_19200;
                dcb.ByteSize = 8;
                dcb.fRtsControl = RTS_CONTROL_ENABLE;
                dcb.fOutxCtsFlow = 0;
                dcb.Parity = NOPARITY;
                dcb.StopBits = ONESTOPBIT;
               
                COMMTIMEOUTS CommTimeOut;
               
                GetCommTimeouts(hPort, &CommTimeOut);
               
                CommTimeOut.ReadIntervalTimeout        = MAXDWORD;
                CommTimeOut.ReadTotalTimeoutMultiplier = 2;
                CommTimeOut.ReadTotalTimeoutConstant  = 2;
                CommTimeOut.WriteTotalTimeoutMultiplier = 0;
                CommTimeOut.WriteTotalTimeoutConstant = 0;   
                SetCommState(hPort, &dcb);
                if (!SetCommTimeouts(hPort, &CommTimeOut))
                    MessageBox("Setting CommTimeOut error!", "PW-Test Error Message", NULL);

                break;
           
            }

            //If older versions of windows is detected(windows98)
            case VER_PLATFORM_WIN32s || VER_PLATFORM_WIN32_WINDOWS:
            {
                // Set timeouts                
                COMMTIMEOUTS CommTimeOut;

                GetCommTimeouts(hPort, &CommTimeOut);

                CommTimeOut.ReadIntervalTimeout        = 0;
                CommTimeOut.ReadTotalTimeoutMultiplier = 2;
                CommTimeOut.ReadTotalTimeoutConstant  = 2;
               
                if (!SetCommTimeouts(hPort, &CommTimeOut))
                    MessageBox("Setting CommTimeOut error!", "PW-Test Error Message", NULL);

                // Set DCB
                DCB dcb;

                GetCommState(hPort, &dcb);
                BuildCommDCB("baud=19200 parity=N data=8 stop=1", &dcb);
                SetCommState(hPort, &dcb);               
               
                break;           
            }
           
            //If the windows version is unknown
            default:
            {
                AfxMessageBox("Unknown Windows version detected!", MB_ICONSTOP);
                break;

            }


        }
       
        EscapeCommFunction(hPort,CLRDTR);    // Turn off power to module
    }   
    return hPort;   
}

Grunden til at den ekstra kode er, at jeg tjekker på hvilket OS programmet kører på, og så bliver COMporten sat op som den skal, eller det urde den i hvert fald :)
Avatar billede driis Nybegynder
14. oktober 2005 - 16:42 #5
Jeg tror det er i metoden:
StartTest(hPort);
at selve kommunikationen foregår. Prøv at se efter kald til ReadFile og WriteFile med hPort som parameter.
Avatar billede henning-a Nybegynder
17. oktober 2005 - 14:15 #6
Der er en funktion der bliver kaldt med parametren hPort, den er her:

BYTE* CPWTestDlg::ReceiveBytes(HANDLE hPort, DWORD nInQue)
{
    DWORD BytesRead = 0;   
   
    static BYTE ReceiveBuf[40] = "";   

    ReadFile(hPort, &ReceiveBuf, nInQue, &BytesRead, NULL);   
   
    return ReceiveBuf;
   
}

Deri bliver ReadFile kaldt, det er det eneste sted jeg lige kan se der bliver brugt ReadFile.
Den der nInQue bliver sat sådan her, i en tidligere del af koden.

nInQue = comstat.cbInQue;
Avatar billede henning-a Nybegynder
11. juni 2007 - 13:30 #7
Nevermind.. jeg fik det til at virke.. Kørte bare en funktion 2 gange i stedet.. det løste problemet..
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