串行程序问题! [英] Serial Program Problem!

查看:70
本文介绍了串行程序问题!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hello Everybody!

我是串口编程的新手,我必须制作一个从微控制器接收数据的程序。问题是它收到的数字与我发送的数字有点不同。例如,我每0.1发送1,它接收并打印1 .. 10 ... 1 ... 10 ...我该如何解决这个问题?

任何提示都会有所帮助! />


我使用计时器来接收事件;



代码:



[...]



  int  WINAPI WinMain(HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd; / * 这是我们窗口的句柄* /
MSG消息; / * 此处保存到应用程序的消息* /
WNDCLASSEX wincl; / * 窗口类的数据结构* /

// 创建窗口!


/ * 运行消息循环。它将一直运行,直到GetMessage()返回0 * /
(GetMessage(& messages,NULL, 0 0 ))
{
/ * 将虚拟密钥消息转换为字符消息* /
TranslateMessage(& messages);
/ * 发送消息给WindowProcedure * /
DispatchMessage(& messages) ;
}

/
}



LRESULT CALLBACK WindowProcedure(HWND hwnd,UINT消息,WPARAM wParam,LPARAM lParam )
{
// Caso o botao1 seja apertado; //
int gwtstat = 0 ;
int I;
char * t =& textSaved [ 0 ];
char pcCommPort [ 50 ] = COM4;
char SuceText [] = { 已连接};
char stopedcon [] = { 连接采空};
char ErrorText [] = { 错误连接};
char ConnectionError [] = { 端口未连接};
int x [ 300 ] = { 0 },y [ 300 ] = { 0 },z [ 300 ] = { 0 },v [ 300 ] = { 0 };
int vetor1 [ 500 ],vetor2 [ 500 ];

/ * --- Estrutura para quando pintar a tela --- * /
PAINTSTRUCT ps;
HDC hdc;
TEXTMETRIC tm; // 决定o tamanho das letras
TCHAR teste [] = { Exame:};
/ * -------------- SERIAL ----- ------------- * /
int tx;
DWORD num;
字节 [ 2 ] = { 0 };
/ * -------------------- ----------------------- * /


开关(消息) / * 处理消息* /
{
case WM_CREATE:

AddMenus(hwnd); // < span class =code-comment> Adiciona Menus a janela


TextBox = CreateWindow( 编辑

WS_BORDER | WS_CHILD | WS_VISIBLE,
10 40 400 20
HWND,NULL,NULL,NULL);

CreateWindow( BUTTON
SAVE
WS_VISIBLE | WS_CHILD | WS_BORDER,
420 40 70 20
hwnd,(HMENU) 1 ,NULL,NULL);

CreateWindow( BUTTON
START
WS_VISIBLE | WS_CHILD | WS_BORDER,
420 80 70 20
hwnd,(HMENU) 2 ,NULL,NULL);

CreateWindow( BUTTON
STOP
WS_VISIBLE | WS_CHILD | WS_BORDER,
300 80 70 20
hwnd,(HMENU) 6 ,NULL,NULL);
break ;


case WM_PAINT:
hdc = BeginPaint(hwnd,& ps);
FillRect(hdc,& ps.rcPaint,(HBRUSH)(COLOR_WINDOW + 1));
矩形(hdc, 10 110 500 300 );
for (I = 0 ; I< 50; I ++){
SetPixel (hdc,I,I,RGB( 255 0 0 ));
}
TextOut(hdc, 1 1 ,teste,strlen(teste) ));
EndPaint(hwnd,& ps);
break ;

case WM_TIMER:
// 待办事项:invalidar apenas uma pequena regiao
tx = ReadFile(hCom,& in, 1 ,& num ,空值);
printf( %x \ t,( in [ 0 ]));
hdc = GetDC(hwnd);
SetPixel(hdc,i, in [ 0 ],RGB( 255 0 0 ));
ReleaseDC(hwnd,hdc);
i ++;




// InvalidateRect(hwnd, NULL,FALSE);
/ * for(i = 0; i< 1000; i ){
hdc = GetDC(hwnd);
SetPixel(hdc,i,in [i],RGB(255,0,0));
ReleaseDC(hwnd,hdc); * /

// }


break ;
case WM_COMMAND:
switch (LOWORD(wParam)){
case BUTTON1:
gwtstat = GetWindowText(TextBox,t, 20 );
:: MessageBox(hwnd,textSaved,textSaved,MB_OK);
fopen( info.txt a +);
fwrite(teste, 1 sizeof (teste),fp);
break ;

case BUTTON2:
hCom = CreateFile(pcCommPort,
GENERIC_READ | GENERIC_WRITE,
0 // 必须以独占访问方式打开
NULL, // 无安全属性
OPEN_EXISTING, // 必须使用OPEN_EXISTING
0 // 不重叠I / O
NULL // 对于通讯设备,hTemplate必须为NULL
);


if (hCom == INVALID_HANDLE_VALUE)
{
:: MessageBox(hwnd,ConnectionError, ConnectionError,MB_OK);
return 1 );
}


fSuccess = GetCommState(hCom,& dcb);

if (!fSuccess)
{
return 2 );
}

dcb.BaudRate = CBR_9600; // 设置波特率
dcb.ByteSize = 8 ; // 数据大小,xmit和rcv
dcb.Parity = ODDPARITY; // 无奇偶校验位
dcb.StopBits = ONESTOPBIT; // 一站式

fSuccess = SetCommState(hCom,& dcb );

if (!fSuccess)
{
:: MessageBox(hwnd,ConnectionError,ConnectionError,MB_OK);
return 3 );
}
:: MessageBox(hwnd,SuceText,SuceText,MB_OK);

SetTimer(hwnd, 1 ,0x1,NULL);
/ *
if(tx == TRUE){
printf(% d,在[0]);
}
else {
:: MessageBox(hwnd,ConnectionError,ConnectionError,MB_OK);
} * /


break ;
case IDM_FILE_NEW:
Beep( 100 100 );
break ;
case IDM_FILE_OPEN:
Beep( 50 100 );
break ;
case IDM_FILE_QUIT:
SendMessage(hwnd,WM_CLOSE, 0 0 );
break ;
case STOP:
KillTimer(hwnd, 1 );
if (CloseHandle(hCom)== 0 ){
:: MessageBox (HWND,ERRORTEXT,NULL,MB_OK);
}
else {
:: MessageBox(hwnd,stopedcon,stopedcon,MB_OK);
}
break ;
}

/ * case WM_DESTROY:
PostQuitMessage(0) ; //将WM_QUIT发送到消息队列
KillTimer(hwnd,1);
break; * /


默认 / * 我们不处理的消息* /
return DefWindowProc(hwnd, message,wParam,lParam);
}

return 0 ;
}

解决方案

看看这一行:



 tx = ReadFile(hCom,& in, 1 ,& num,NULL); 





tx声明为int但ReadFile返回BOOL。您的代码应检查成功/失败的调用。



num将具有读取的字符数(例如0或1)。在尝试从in缓冲区中打印字符之前,您的代码应该检查这个。



您的代码为每个WM_TIMER读取一个字符。您对SetTimer的调用指定延迟为1 ms,但SetTimer的最小延迟为10 ms,因此您将每秒轮询100次字符。如果微控制器发送的字符比这快(9600波特每秒可发送960个字符) - 你将丢失数据。



https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906% 28v = vs.85%29.aspx [ ^ ]



使用SetCommTimeouts控制程序在每次调用ReadFile时等待的时间。



https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437%28v=vs.85%29.aspx [ ^ ]



使用更大的缓冲区来读取多个字符以容忍来自微控制器的一连串数据。



您可能需要考虑创建一个单独的线程来调用CreateFile并在循环中调用ReadFile以避免阻塞UI。


Hello Everybody!
I am new to Serial programming, And I have to make a programm that receives data from a microcontroler. The problem is that the number that it receives are a little diferent from the ones I sent. For example, i send 1 every 0.1, it receives and prints 1.. 10... 1... 10... How do I solve this?
Any hint would be helpful!

I used a timer to sincronize receiving events;

CODE:

[...]

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

//    CREATES WINDOW!


    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /
}



LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//Caso o botao1 seja apertado;//
int     gwtstat = 0;
int I;
char *  t = &textSaved[0];
char pcCommPort[50] = "COM4";
char SuceText[] = {"Connected"};
char stopedcon[]= {"Connection Stoped"};
char ErrorText[] = {"Error Connecting"};
char ConnectionError[] = {"Port Not Connected"};
int x[300]={0},y[300]={0},z[300]={0},v[300]={0};
int vetor1[500],vetor2[500];

/*--- Estrutura para quando pintar a tela ---*/
PAINTSTRUCT ps;
HDC         hdc;
TEXTMETRIC  tm;     //Decide o tamanho das letras
TCHAR       teste[]={"Exame:"};
/*--------------SERIAL------------------*/
int tx;
DWORD num;
byte in[2]={0};
/*-------------------------------------------*/


    switch (message)                  /* handle the messages */
    {
    case WM_CREATE:

        AddMenus(hwnd);//Adiciona Menus a janela

        TextBox = CreateWindow("EDIT",
                              "",
                              WS_BORDER | WS_CHILD | WS_VISIBLE,
                              10, 40,400,20,
                              hwnd,NULL,NULL,NULL);

        CreateWindow("BUTTON",
                     "SAVE",
                     WS_VISIBLE | WS_CHILD | WS_BORDER,
                     420, 40, 70, 20,
                     hwnd, (HMENU) 1, NULL, NULL);

        CreateWindow("BUTTON",
                     "START",
                     WS_VISIBLE | WS_CHILD | WS_BORDER,
                     420, 80, 70, 20,
                     hwnd, (HMENU) 2, NULL, NULL);

        CreateWindow("BUTTON",
                     "STOP",
                     WS_VISIBLE | WS_CHILD | WS_BORDER,
                     300, 80, 70, 20,
                     hwnd, (HMENU) 6, NULL, NULL);
                break;


    case WM_PAINT:
                hdc = BeginPaint(hwnd,&ps);
                FillRect(hdc,&ps.rcPaint,(HBRUSH)(COLOR_WINDOW+1)); 
                Rectangle(hdc,10,110,500,300);
                for (I=0;I<50;I++){
                    SetPixel(hdc,I,I,RGB(255,0,0));
                }
                TextOut(hdc,1,1,teste,strlen(teste));    
                EndPaint(hwnd,&ps);
                break;

    case WM_TIMER:
                // To do: invalidar apenas uma pequena regiao
                tx = ReadFile(hCom,&in,1,&num,NULL);
                printf("%x\t",(in[0]));
                 hdc = GetDC(hwnd);
                       SetPixel(hdc,i,in[0],RGB(255,0,0));
                       ReleaseDC(hwnd,hdc);
                i++;




                //InvalidateRect (hwnd, NULL, FALSE) ;
               /* for(i=0;i<1000;i){
                       hdc = GetDC(hwnd);
                       SetPixel(hdc,i,in[i],RGB(255,0,0));
                       ReleaseDC(hwnd,hdc);*/
                //}


                break;
    case WM_COMMAND:
        switch (LOWORD(wParam)){
            case BUTTON1:
                gwtstat = GetWindowText(TextBox,t, 20);
                ::MessageBox(hwnd,textSaved,textSaved,MB_OK);
                fopen("info.txt","a+");
                fwrite(teste,1,sizeof(teste),fp);
                break;

            case BUTTON2:
                hCom = CreateFile( pcCommPort,
                                GENERIC_READ | GENERIC_WRITE,
                                0,    // must be opened with exclusive-access
                                NULL, // no security attributes
                                OPEN_EXISTING, // must use OPEN_EXISTING
                                0,    // not overlapped I/O
                                NULL  // hTemplate must be NULL for comm devices
                    );


                if (hCom == INVALID_HANDLE_VALUE)
                {
                    ::MessageBox(hwnd,ConnectionError,ConnectionError,MB_OK);
                   return (1);
                }


               fSuccess = GetCommState(hCom, &dcb);

               if (!fSuccess)
               {
                    return (2);
               }

                dcb.BaudRate = CBR_9600;     // set the baud rate
                dcb.ByteSize = 8;             // data size, xmit, and rcv
                dcb.Parity = ODDPARITY;        // no parity bit
                dcb.StopBits = ONESTOPBIT;    // one stop bit

                fSuccess = SetCommState(hCom, &dcb);

                if (!fSuccess)
                {
                ::MessageBox(hwnd,ConnectionError,ConnectionError,MB_OK);
                  return (3);
                }
                ::MessageBox(hwnd,SuceText,SuceText,MB_OK);

                SetTimer(hwnd,1,0x1,NULL);
                /*
                if (tx == TRUE) {
                    printf("%d",in[0]);
                }
                else{
                    ::MessageBox(hwnd,ConnectionError,ConnectionError,MB_OK);
                }*/

                break;
            case IDM_FILE_NEW:
                Beep(100, 100);
                break;
            case IDM_FILE_OPEN:
                Beep(50, 100);
                break;
            case IDM_FILE_QUIT:
                SendMessage(hwnd,WM_CLOSE,0,0);
                break;
            case STOP:
                KillTimer(hwnd,1);
                if (CloseHandle(hCom)==0){
                ::MessageBox(hwnd,ErrorText,NULL,MB_OK);
                }
                else{
                ::MessageBox(hwnd,stopedcon,stopedcon,MB_OK);
                }
                break;
        }

    /*case WM_DESTROY:
            PostQuitMessage (0);       //send a WM_QUIT to the message queue
            KillTimer (hwnd, 1) ;
            break;*/

            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
            }

    return 0;
}

解决方案

Take a look at this line:

tx = ReadFile(hCom,&in,1,&num,NULL);



tx is declared as int but ReadFile returns BOOL. Your code should check the call for success / failure.

num will have the number of characters read (eg. 0 or 1). Your code should check this before attempting to print characters from the "in" buffer.

Your code reads one character for each WM_TIMER. Your call to SetTimer specifies a delay of 1 ms but SetTimer's smallest delay is 10 ms so you will poll for characters 100 times per second. If the microcontroller sends characters faster than that (9600 baud can send 960 characters per second) - you will loose data.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx[^]

Use SetCommTimeouts to control how long your program waits on each call to ReadFile.

https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437%28v=vs.85%29.aspx[^]

Use a larger buffer to read multiple characters to tolerate a burst of data from the microcontroller.

You may want to consider creating a separate thread to call CreateFile and call ReadFile in a loop to avoid blocking the UI.


这篇关于串行程序问题!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆