一个串口程序示例

以下是我初学串口写的一个串口程序示例,内有详细注释

BOOL CMyTestCommDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    
// TODO: Add extra initialization here
    DCB dcb;
    DWORD dwError;
    COMMTIMEOUTS CommTimeOuts;
    hCom
=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);//打开串口
    if(hCom==(HANDLE)0xFFFFFFFF)//INVALID_HANDLE_VALUE==0xFFFFFFFF
    {
        dwError
=GetLastError();
        ATLTRACE(
"打开串口:dwError=%d ",dwError);
        
return FALSE;
    }

    SetupComm(hCom,
1024,512);//设置输入、输出缓冲区大小
    PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR );//中止后台读写操作,清空发送、接收缓冲区
    CommTimeOuts.ReadIntervalTimeout=20;//设置超时参数
    CommTimeOuts.ReadTotalTimeoutMultiplier=10;
    CommTimeOuts.ReadTotalTimeoutConstant
=100;
    CommTimeOuts.WriteTotalTimeoutMultiplier
=10;
    CommTimeOuts.WriteTotalTimeoutConstant
=100;
    
if(!SetCommTimeouts(hCom,&CommTimeOuts))
    
{
        dwError
=GetLastError();
        ATLTRACE(
"超时:dwError=%d ",dwError);
    }


    GetCommState(hCom,
&dcb);//获取串口参数
    dcb.BaudRate=9600;
    dcb.Parity
=NOPARITY;
    dcb.ByteSize
=8;
    dcb.StopBits
=1;
    SetCommMask(hCom,EV_ERR
|EV_RXCHAR);//设置事件掩码
    SetCommState(hCom,&dcb);//设置串口参数
    
    memset(
&osRead,0,sizeof(OVERLAPPED));
    osRead.Offset
=0;
    osRead.OffsetHigh
=0;
    osRead.hEvent
=CreateEvent(NULL,TRUE,FALSE,NULL);

    AfxBeginThread((AFX_THREADPROC)CommWatchProc,(LPVOID)
this);//创建事件监控线程
    return TRUE;  // return TRUE  unless you set the focus to a control
}


void  CMyTestCommDlg::OnBnClickedButtonSend()
{
    
// TODO: 在此添加控件通知处理程序代码
    UpdateData(true);
    DWORD wCount 
= 0;
    PurgeComm(hCom,PURGE_TXABORT
|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
    BOOL bwritestate
=WriteFile(hCom, m_sendstr.GetBuffer(0), m_sendstr.GetLength(), &wCount, NULL);//&overlapped);//发送数据
    if(!bwritestate||m_sendstr.GetLength()!=wCount)
    
{
        MessageBox(
"error:数据发送失败!");
        
return;
    }

    MessageBox(
"数据发送成功!");
}


UINT CommWatchProc(LPVOID pParam) 
{
    ATLTRACE(
"thread start ");
    DWORD dwEventMask;
//=0;
    CMyTestCommDlg* tempcom=(CMyTestCommDlg*)pParam;
    SetCommMask(hCom,EV_ERR
|EV_RXCHAR|EV_TXEMPTY|EV_RXFLAG);//设置事件掩码
    PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR );
    LPOVERLAPPED os
=&osRead;
    OVERLAPPED olRead
=osRead;//注意:等待事件和读写时的异步标志参数标志都是返回的,不要混用,因为可能不同值
    
    
int count1=0;//限制循环次数
    DWORD count;
    
    
while(count1<5000)
    
{
        count1
++;
        ATLTRACE(
"***%d***: ",count1);
        BOOL statetem
=0;
        
//SetCommMask(hCom,EV_ERR|EV_RXCHAR|EV_TXEMPTY|EV_RXFLAG);
        if(!(statetem=WaitCommEvent(hCom,&dwEventMask,os)))
        
{
            DWORD error
=GetLastError();
            ATLTRACE(
"error1=%d ",error);
            
if(error==ERROR_IO_PENDING)//异步I/O操作进行中
            {
                GetOverlappedResult(hCom,os,
&count,TRUE);//参数4为true表示等待标志,异步操作完成才返回
                ATLTRACE("GetOverlappedResult:123456  count=%d ",count);
            }

            
else 
                
continue;
        }

        
if(dwEventMask == 0)
            
continue;
        
{
            
if ((dwEventMask&EV_RXCHAR)==EV_RXCHAR)//接收事件
            {
                COMSTAT comstat;
                DWORD dwLength;
                DWORD dwErrorFlags;
                ClearCommError(hCom,
&dwErrorFlags,&comstat);//获取缓冲区字符长度
                dwLength=comstat.cbInQue;
                
if(dwLength>0)
                
{
                    BOOL fReadStat;
                    
char str[512]="";
                    DWORD count;
                    DWORD dwBytesRead,dwBytetoRead
=100;
                    dwBytesRead
=(dwLength<dwBytetoRead)?dwLength:dwBytetoRead;//比较缓冲区字符长度与可以读的字符长度,得到要求读字符长度
                    ATLTRACE("比较:dwLength=%d  dwBytetoRead=%d => dwBytesRead=%d ",dwLength,dwBytetoRead,dwBytesRead);
                    fReadStat 
= ReadFile(hCom,&str,dwBytesRead,&count,&olRead);//读缓冲区数据
                    if(fReadStat==FALSE)//读写失败则
                    {
                        
if(GetLastError() != ERROR_IO_PENDING)
                        
{
                            
continue;
                        }

                        
if(GetOverlappedResult(hCom,&olRead,&count,TRUE) == FALSE)//??
                        {
                            str[count]
=0;
                        }

                        
if(count == 0)
                        
{
                            
continue;
                        }

                    }

                        
                    str[count]
=0;//置字符串以结束字符标志
                    ATLTRACE("str=%s, count=%d, fReadStat=%d, ",str,count,fReadStat);
                    
if(count>0)
                        ::PostMessage(tempcom
->m_hWnd,COM_RECVDATA,(WPARAM) str,count);//接收到字符事件后,可以将此消息登记到由pParam指定的窗口类中进行处理 
                }

            }

            
if((dwEventMask&EV_ERR)==EV_ERR)//出错事件
            {
                DWORD error
=GetLastError();
                
//ATLTRACE("EV_ERR:error=%d ",error);//发生错误时的处理 
            }

        }

        ATLTRACE(
"***一次事件结束*** ");
    }

    
return 0;
}


LRESULT CMyTestCommDlg::OnRecvData(WPARAM wParam, LPARAM lParam)
{
    
char str[201];
    CString recvStr((
char *)wParam);
    m_receivestr
+=recvStr+"-- ";//+"-- ";
ATLTRACE("m_receivestr=%s ",m_receivestr);
    SetDlgItemText(IDC_RECE,m_receivestr);
    
return TRUE;

}

void  CMyTestCommDlg::OnClose()
{
    
// TODO: 在此添加消息处理程序代码和/或调用默认值
    CloseComm();
    CDialog::OnClose();
}


void  CMyTestCommDlg::CloseComm()
{
    SetCommMask(hCom,
0);//结束WaitCommEvent的等待,即停止事件监控
 PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);//中止后台读写操作,清空发送、接收缓冲区
    CloseHandle(hCom);//关闭句柄
}

你可能感兴趣的:(一个串口程序示例)