您的位置:首页 > 编程语言

MFC串口编程——使用WM_COMM_TXEMPTY_DETECTED来判断接收结束

2017-10-30 22:19 639 查看
最重要的写在最前面:

::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED,
(WPARAM) RXBuff, (LPARAM) port->m_nPortNr); 

在void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT
comstat)函数的  for循环结束之后  添上上面代码即可,就是添加  发送“串口数据发送完毕”消息!

void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff;

for (;;)
{
// Gain ownership of the comm port critical section.
// This process guarantees no other part of this program
// is using the port object.

EnterCriticalSection(&port->m_csCommunicationSync);

// ClearCommError() will update the COMSTAT structure and
// clear any other errors.

bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

LeaveCriticalSection(&port->m_csCommunicationSync);

// start forever loop. I use this type of loop because I
// do not know at runtime how many loops this will have to
// run. My solution is to start a forever
4000
loop and to
// break out of it when I have processed all of the
// data available. Be careful with this approach and
// be sure your loop will exit.
// My reasons for this are not as clear in this sample
// as it is in my production code, but I have found this
// solutiion to be the most efficient way to do this.

if (comstat.cbInQue == 0)
{
// break out when all bytes have been read
break;
}

EnterCriticalSection(&port->m_csCommunicationSync);

if (bRead)
{
bResult = ReadFile(port->m_hComm, // Handle to COMM port
&RXBuff, // RX Buffer Pointer
1, // Read one byte
&BytesRead, // Stores number of bytes read
&port->m_ov); // pointer to the m_ov structure
// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress
// Proceed on to GetOverlappedResults();
bRead = FALSE;
break;
}
default:
{
// Another error has occured. Process this error.
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)

if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag

// deal with the error code
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)

LeaveCriticalSection(&port->m_csCommunicationSync);

// notify parent that a byte was received
::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);

} // end forever loop
::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
}

//

“发送文件”按钮 IDC_BUTTON_SENDFILE添加单击响应函数OnButtonSendfile( )

[cpp] view
plain copy

//发送文件  

void CSCOMMDlg::OnButtonSendfile()   

{  

    // TODO: Add your control notification handler code here  

    CFile fp;  

    if(!(fp.Open((LPCSTR)m_strSendFilePathName,CFile::modeRead)))//文件以只读的方式打开  

    {  

        AfxMessageBox("Open file failed!");  

        return ;  

    }  

    fp.SeekToEnd(); //这里应该是设置光标到 文本的末尾,一遍统计字符文本字符数  

    unsigned long fplength=fp.GetLength();  

    m_nFileLength=fplength;  

    char* fpBuff;  

    fpBuff =new char[fplength];  

    fp.SeekToBegin();  

    if(fp.Read(fpBuff,fplength)<1)//读文件的数据到fpBuff中  

    {  

        fp.Close();//读文件失败 关闭文件  

        return ;  

    }  

    fp.Close();  

    CString strStatus;  

    if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,fplength))  

    {  

          

        m_Port.StartMonitoring();  

        strStatus.Format("STATUS: COM%d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  

        m_ctrlIconOpenoff.SetIcon(m_hIconRed);  

        m_bSendFile=TRUE;  

        //  m_strTempSendFilePathName=m_strSendFilePathName;  

        m_ctrlEditSendFile.SetWindowText("正在发送......");  

          

        //发送文件时,一下功能不能使用  

        m_ctrlManualSend.EnableWindow(FALSE);  

        m_ctrlAutoSend.EnableWindow(FALSE);  

        m_ctrlSendFile.EnableWindow(FALSE);  

        m_Port.WriteToPort((LPCSTR)fpBuff,fplength);  

    }  

    else  

    {  

        AfxMessageBox("Failed to send file!");  

        m_ctrlIconOpenoff.SetIcon(m_hIconOff);  

    }  

    delete fpBuff;//释放内存,一定得记得  

}  

怎样才知道文件的内容发送完了呢???还用串口类CSerialPort中有WM_COMM_TXEMPTY_DETECTED消息来告诉我们

添加串口字符发送完毕消息WM_COMM_TXEMPTY_DETECTED,并添加响应函数

函数的声明:

[cpp] view
plain copy

//{{AFX_MSG(CSCOMMDlg)    

       afx_msg LONG OnFileSendingEnded(WPARAM wParam,LPARAM port);  

//}}AFX_MSG  

DECLARE_MESSAGE_MAP()  

添加消息映射:

[cpp] view
plain copy

//消息映射  

BEGIN_MESSAGE_MAP(CSCOMMDlg, CDialog)  

    //{{AFX_MSG_MAP(CSCOMMDlg)  

    ON_MESSAGE(WM_COMM_RXCHAR,OnCommunication)  

    //}}AFX_MSG_MAP  

END_MESSAGE_MAP()  

添加消息响应函数:

[cpp] view
plain copy

LONG CSCOMMDlg::OnFileSendingEnded(WPARAM wParam,LPARAM port)  

{  

    if(m_bSendFile)  

    {  

        m_ctrlEditSendFile.SetWindowText("发送完毕!");//  

        TX_count+=m_nFileLength;  

        SetTimer(3,3000,NULL);  

        CString strTemp;  

        strTemp.Format("TX: %d ",TX_count);  

        m_ctrlTXCount.SetWindowText(strTemp);  

    }  

    return 0;  

}  

看到上面的函数中发送数据结束后启动 SetTimer(3,3000,NULL);以恢复状态。看来还要在定时函数中添加代码:

[cpp] view
plain copy

void CSCOMMDlg::OnTimer(UINT nIDEvent)   

{  

    // TODO: Add your message handler code here and/or call default  

    switch (nIDEvent)  

    {  

    case 1: //定时器ID==1为自动发送时间  

        OnButtonManualsend();   //周期到后自动发送  

        break;  

    case 2:  

        m_ctrlSavePath.SetWindowText(m_StrCurPath);//重新显示路径  

        KillTimer(2);//关闭定时器  

        break;  

    case 3:  

        m_ctrlManualSend.EnableWindow(TRUE);  

        m_ctrlAutoSend.EnableWindow(TRUE);  

        m_ctrlSendFile.EnableWindow(TRUE);  

        m_strSendFilePathName=m_strTempSendFilePathName;          

        KillTimer(3);  

        if(!(m_ctrlAutoSend.GetCheck()))  

        {  

            CString strStatus;  

            if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))  

            {  

                m_Port.StartMonitoring();  

                strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  

                m_ctrlIconOpenoff.SetIcon(m_hIconRed );  

  

            }  

            else  

            {  

                AfxMessageBox("Failed to reset send buffer size!");  

                m_ctrlIconOpenoff.SetIcon(m_hIconOff);  

            }  

            m_ctrlPortStatus.SetWindowText(strStatus);  

        }  

        break;  

    default:  

        break;  

    }  

    CDialog::OnTimer(nIDEvent);  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: