标题:VC API串口编程问题 附加详细注释的源码和图片
只看楼主
heavystorm
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2011-2-12
结帖率:0
 问题点数:0 回复次数:3 
VC API串口编程问题 附加详细注释的源码和图片
       各位高手,我初学VC串口编程,遇到我不能解决的问题,已经阻碍我还几天了,无助之下到此论坛发求助贴,我现在技术有限,以后技术提高了我想尽量帮助别人。但现在需要被高手帮助。
      以下是我在VC++2005上用纯API编程,不涉及MFC,不涉及串口控件,无对话框,仅有一个按钮和一些监控文字输出,程序尽量简化了,通过COM1口发送任意RS232数据都成功了,就是接收不到数据。我用单片机发出各种数据都可被串口助手(选COM1口,设置正确)正确显示,但我编这个程序就是接收不到数据,调用ReadFile(hComm,&receive,10,&BytesRead,&m_ov)后开单片机连续发送串口数据,发现receive中数据无变化。
以下是源程序,只需在完全空白的VC++工程的源文件下新建一个空白的C文件,然后复制以下代码到上面,直接编译即可。
#include<windows.h>//包含基本数据类型定义
#include<stdlib.h> //数学函数库
#include<string.h> //数学函数库
#include<stdio.h>//输入输出库
#define ID_MYBUT 50//定义按钮事件标识
HWND hwnd;//主窗口句柄
HDC hdc;//设备环境句柄
int number0=2,number=0,number2=0,number3=0,number4=0,number5=0,number6=0,number7=0;//监控标志数,多无用处
int times=0;//记录了WM_PAINT被执行的次数
char dialogue1='m';//无用监控标志
char m_szWriteBuffer='a';//写串口的写入字符
bool open;
char receive;//读串口是数据放到这里

HANDLE hComm;
OVERLAPPED m_ov;
COMSTAT comstat;
DWORD m_dwCommEvents;

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//窗口函数说明
void ReceiveChar();//读串口的函数
BOOL Openport();//开串口的函数
BOOL setupdcb(int);//设置串口参数的函数
BOOL setuptimeout(DWORD,DWORD,DWORD,DWORD,DWORD);//设置超时的函数
BOOL WriteChar(DWORD);//写串口的函数

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) // 入口函数
{
    MSG Msg; //MSG为消息结构体变量类型  Message为变量名,可为Msg
    WNDCLASS wndclass;
    char lpszClassName[]="位图";
    char lpszTitle[]="LTL Programe";
    wndclass.style=0;
    wndclass.lpfnWndProc=WndProc;
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hInstance=hInstance;
    wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName=NULL;
    wndclass.lpszClassName=lpszClassName;
    if(!RegisterClass(&wndclass))
    {
        MessageBeep(0);
        return FALSE;
    }
    hwnd=CreateWindow
        (
        lpszClassName,//窗口实例的标题名
        lpszTitle,//窗口的风格
        WS_OVERLAPPEDWINDOW,//
        0,//窗口左上角坐标为默认值
        0,//
        800,//窗口的高和宽为默认值
        400,
        NULL,//此窗口无父窗口
        NULL,//此窗口无主菜单
        hInstance,//创建此窗口应用程序的当前句柄
        NULL//不使用该值
        );
    ShowWindow(hwnd,nCmdShow);//显示窗口
    UpdateWindow(hwnd);//绘制用户区
        while(GetMessage(&Msg,0,0,0))//消息循环
                                 //后两个参数为0不过滤消息
        {//GetMessage是从消息队列中提取一条消息,并将消息放到MSG结构体
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)//窗口函数说明
{
    PAINTSTRUCT ps;
    char str[30]="";
    switch(message)//处理消息
    {
    case WM_CREATE:
        hdc=GetDC(hwnd);//获取设备环境句柄
        SetTimer(hwnd,1,200,NULL);
        //创建按钮////////////////////////////////////////////////
        HWND butt;
        butt=CreateWindow(
            "BUTTON",   // predefined class
            "OK",       // button text
            WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // styles
            20,         // starting x position
            10,         // starting y position
            100,        // button width
            30,        // button height
            hwnd,       // parent window
            (HMENU) ID_MYBUT,       // No menu
            (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
            NULL);      // pointer not needed
        //////////////////////////////////////////////////////////
        break;
    case WM_TIMER:
        InvalidateRect(hwnd,NULL,FALSE);//刷新用户区,并序发送WM_PAINT消息
        break;
    case WM_COMMAND://处理按钮消息
        switch(LOWORD(wParam))
        {
        case ID_MYBUT://点击按钮后打开串口并初始化
            open=Openport();//打开串口COM1
            if(open) number=999;//如果打开成功显示999
            else  number=111;
            if(setupdcb(9600))
            {
                number2=1;
            }
            if(setuptimeout(10,0,20,0,0))
            {
                number3=1;
            }
            SetupComm(hComm,1024,1024);
            SetCommMask(hComm,EV_RXCHAR);//当有字符串在inbuf中时产生这个事件
            PurgeComm(hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);//清空串口缓冲区
            InvalidateRect(hwnd,NULL,TRUE);//刷新用户区,并序发送WM_PAINT消息
            break;
        }
    case WM_PAINT://处理绘图消息
        hdc=BeginPaint(hwnd,&ps);
        if(number==999) {
        ReceiveChar();
        PurgeComm(hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);//清空串口缓冲区
        times++;
        //WriteChar(1);
        }
/////////监控字符输出////////////////////////
        hdc=GetDC(hwnd);
        SetTextColor(hdc,RGB(0,0,0));
        sprintf(str,"num=%d",number);
        TextOut(hdc,166,11,str,strlen(str));

        sprintf(str,"times=%d",times);
        TextOut(hdc,166,61,str,strlen(str));

        sprintf(str,"setupDCB= %d",number2);
        TextOut(hdc,250,11,str,strlen(str));
        sprintf(str,"setupTIMEout= %d",number3);
        TextOut(hdc,400,11,str,strlen(str));

        sprintf(str,"Receive=%c",receive);
        TextOut(hdc,400,51,str,strlen(str));
        ReleaseDC(hwnd,hdc);
////////////////////////////////////////////
        EndPaint(hwnd,&ps);//释放设备环境句柄
        break;
    case WM_DESTROY://消除窗口时由DestroyWindow函数发出此消息
        KillTimer(hwnd,1);//删除定时器
        CloseHandle(hComm);//关闭串口
        PostQuitMessage(0);//向应用程序发出WM_QUIT消息,请求退出
        break;
    default://对未定义的消息提供默认处理
        return(DefWindowProc(hwnd,message,wParam,lParam));
    }return 0;
}
BOOL Openport()
{
    hComm=CreateFile("COM1",//串口号
        GENERIC_READ|GENERIC_WRITE,//允许读写
        0,//通讯设备必须以独占方式打开
        0,//无安全属性
        OPEN_EXISTING,//通讯设备已存在
        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//异步IO        
        NULL);//通讯设备不能用模板打开
    if(hComm==INVALID_HANDLE_VALUE)
    {
        CloseHandle(hComm);//关闭串口
        return FALSE;
    }
    else
        return true;
}
BOOL setupdcb(int rate_arg)
{
    DCB dcb;
    memset(&dcb,0,sizeof(dcb));
    if(!GetCommState(hComm,&dcb))
        return FALSE;
    dcb.DCBlength=sizeof(dcb);//DCB结构体大小
    //*---------SERIAL Port Config-----------*/
    dcb.BaudRate=9600;//波特率
    dcb.Parity=NOPARITY;//奇偶校验
    dcb.fParity=0;//是否进行奇偶校验
    dcb.ByteSize=8;//数据宽度
    dcb.fOutxCtsFlow=0;//CTX线上硬件握手
    dcb.fOutxDsrFlow=0;//DSR线上硬件握手
    dcb.fDtrControl=DTR_CONTROL_DISABLE;//DTR控制
    dcb.fDsrSensitivity=0;
    dcb.fRtsControl=RTS_CONTROL_DISABLE;
    dcb.fOutX=0;//是否使用XON/XOFF协议
    dcb.fInX=0;//是否使用XON/XOFF协议
    //*---------misc parameters-----------*/
    dcb.fErrorChar=0;
    dcb.fBinary=1;//是否是二进制
    dcb.fNull=0;
    dcb.fAbortOnError=0;
    dcb.wReserved=0;
    dcb.XonLim=0;//设置XON字符发送前inbuf中允许的最小字节数
    dcb.XonChar=0x13;//设置表示XON字符的字符,一般是采用0x11
    dcb.XoffChar=0x19;//设置表示XOFF字符的字符,一般采用0x13
    dcb.EvtChar=0;
    dcb.StopBits=TWOSTOPBITS;//设定停止位为2位
    SetCommState(hComm,&dcb);
    return true;
}
BOOL setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)
{
    COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout=ReadInterval;//以毫秒为单位指定通信线上两个字符到达之间的最大时间
    timeouts.ReadTotalTimeoutConstant=ReadTotalconstant;//以毫秒为单位指定一个常数,用于计算读操作的总限时时间
    timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier;//为0则读操作立即返回已接受到的字符
    timeouts.WriteTotalTimeoutConstant=WriteTotalconstant;//与ReadTotalTimeoutConstant相似
    timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier;//与ReadTotalTimeoutMultiplier相似
    if(!SetCommTimeouts(hComm,&timeouts))//如果设置超时成功
        return false;
    else
        return true;
}
//不好使得读函数
void ReceiveChar()
{
    DWORD dwError=0;
    DWORD BytesRead=0;
    BOOL dataread;
    ClearCommError(hComm,&dwError,&comstat);//清除以前的错误并读串口现在的状态
    ReadFile(hComm,&receive,1,&BytesRead,&m_ov);//单片机连续发送数据,理应受到数据送至字符串变量receive,然后通过主程序输出到窗口上。
                                                //单片机发送的数据波特率为9600,无奇偶校验,停止位2位,串口助手能显示接收到的数据。

    if(GetLastError()==ERROR_IO_PENDING)//查询读写FALSE的详细结果
        WaitForSingleObject(m_ov.hEvent,100);
}

//以下为写串口函数,该函数没问题,只是读函数有问题,我在主程序中注释掉写函数了。

BOOL WriteChar(DWORD m_nToSend)
{
    BOOL bWrite=TRUE;
    BOOL bResult=TRUE;
    DWORD BytesSent=0;
    HANDLE m_hWriteEvent;
    ResetEvent(m_hWriteEvent);
    if(bWrite)
    {
        m_ov.Offset=0;//OVERLAPPED结构体
        m_ov.OffsetHigh=0;
        //Clean buffer
        bResult=WriteFile(hComm,//串口句柄
            &m_szWriteBuffer,//待写入数据的首地址
            m_nToSend,//待写入数据的字节长度
            &BytesSent,//函数返回的实际写入串口的数据数量的地址
            &m_ov);//m_ov重叠I/O结构的指针
        if(!bResult)//如果写串口不成功
        {
            number7=2;
            DWORD dwError=GetLastError();//获取不成功的详细信息
            switch(dwError)
            {
            case ERROR_IO_PENDING://写串口未完成函数就返回
                {
                    number7=3;
                    BytesSent=0;//
                    bWrite=FALSE;
                    break;
                }
            default:
                {//all other error codes
                    number7=4;
                    break;
                }
            }
        }
        else number7=1;
    }//end if(bWrite)
    if(!bWrite)//写串口未完时的操作
    {
        bWrite=TRUE;
        bResult=GetOverlappedResult(hComm,////调用GetOv..函数等待写串口完成
            &m_ov,//
            &BytesSent,//
            TRUE);
        number7=5;
        //等待OVERLAPPED结构的hEvent事件,若规定了读写超时,超时则自动结束等待,否则一直等待
        if(!bResult)
        {
            number7=6;
            number5=1;
        }
    }//end if(!bWrite)
    if(BytesSent!=m_nToSend)//如果实际写入串口字节数不等于要写入的字节数,则报错
    {
        number6=1;
    }
    return true;
}
希望高人能解答!
搜索更多相关主题的帖子: receive 单片机 对话框 图片 
2011-02-22 21:48
heavystorm
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2011-2-12
得分:0 
等待回复!
2011-02-23 15:00
heavystorm
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2011-2-12
得分:0 
已经搞明白了,结题!
2011-02-23 18:28
oneyear_zjzd
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2011-5-7
得分:0 
以下是引用heavystorm在2011-2-23 18:28:03的发言:

已经搞明白了,结题!
我也碰到了类似的问题,敢问楼主是如何解决的
2011-05-07 15:35



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-332622-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.793131 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved