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

最重要的写在最前面:

::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 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
  1. //发送文件  
  2. void CSCOMMDlg::OnButtonSendfile()   
  3. {  
  4.     // TODO: Add your control notification handler code here  
  5.     CFile fp;  
  6.     if(!(fp.Open((LPCSTR)m_strSendFilePathName,CFile::modeRead)))//文件以只读的方式打开  
  7.     {  
  8.         AfxMessageBox("Open file failed!");  
  9.         return ;  
  10.     }  
  11.     fp.SeekToEnd(); //这里应该是设置光标到 文本的末尾,一遍统计字符文本字符数  
  12.     unsigned long fplength=fp.GetLength();  
  13.     m_nFileLength=fplength;  
  14.     char* fpBuff;  
  15.     fpBuff =new char[fplength];  
  16.     fp.SeekToBegin();  
  17.     if(fp.Read(fpBuff,fplength)<1)//读文件的数据到fpBuff中  
  18.     {  
  19.         fp.Close();//读文件失败 关闭文件  
  20.         return ;  
  21.     }  
  22.     fp.Close();  
  23.     CString strStatus;  
  24.     if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,fplength))  
  25.     {  
  26.           
  27.         m_Port.StartMonitoring();  
  28.         strStatus.Format("STATUS: COM%d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  
  29.         m_ctrlIconOpenoff.SetIcon(m_hIconRed);  
  30.         m_bSendFile=TRUE;  
  31.         //  m_strTempSendFilePathName=m_strSendFilePathName;  
  32.         m_ctrlEditSendFile.SetWindowText("正在发送......");  
  33.           
  34.         //发送文件时,一下功能不能使用  
  35.         m_ctrlManualSend.EnableWindow(FALSE);  
  36.         m_ctrlAutoSend.EnableWindow(FALSE);  
  37.         m_ctrlSendFile.EnableWindow(FALSE);  
  38.         m_Port.WriteToPort((LPCSTR)fpBuff,fplength);  
  39.     }  
  40.     else  
  41.     {  
  42.         AfxMessageBox("Failed to send file!");  
  43.         m_ctrlIconOpenoff.SetIcon(m_hIconOff);  
  44.     }  
  45.     delete fpBuff;//释放内存,一定得记得  
  46. }  
怎样才知道文件的内容发送完了呢???还用串口类CSerialPort中有WM_COMM_TXEMPTY_DETECTED消息来告诉我们

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

函数的声明:

[cpp]  view plain  copy
  1. //{{AFX_MSG(CSCOMMDlg)    
  2.        afx_msg LONG OnFileSendingEnded(WPARAM wParam,LPARAM port);  
  3. //}}AFX_MSG  
  4. DECLARE_MESSAGE_MAP()  
添加消息映射:

[cpp]  view plain  copy
  1. //消息映射  
  2. BEGIN_MESSAGE_MAP(CSCOMMDlg, CDialog)  
  3.     //{{AFX_MSG_MAP(CSCOMMDlg)  
  4.     ON_MESSAGE(WM_COMM_RXCHAR,OnCommunication)  
  5.     //}}AFX_MSG_MAP  
  6. END_MESSAGE_MAP()  

添加消息响应函数:

[cpp]  view plain  copy
  1. LONG CSCOMMDlg::OnFileSendingEnded(WPARAM wParam,LPARAM port)  
  2. {  
  3.     if(m_bSendFile)  
  4.     {  
  5.         m_ctrlEditSendFile.SetWindowText("发送完毕!");//  
  6.         TX_count+=m_nFileLength;  
  7.         SetTimer(3,3000,NULL);  
  8.         CString strTemp;  
  9.         strTemp.Format("TX: %d ",TX_count);  
  10.         m_ctrlTXCount.SetWindowText(strTemp);  
  11.     }  
  12.     return 0;  
  13. }  
看到上面的函数中发送数据结束后启动  SetTimer(3,3000,NULL);以恢复状态。看来还要在定时函数中添加代码:

[cpp]  view plain  copy
  1. void CSCOMMDlg::OnTimer(UINT nIDEvent)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default  
  4.     switch (nIDEvent)  
  5.     {  
  6.     case 1: //定时器ID==1为自动发送时间  
  7.         OnButtonManualsend();   //周期到后自动发送  
  8.         break;  
  9.     case 2:  
  10.         m_ctrlSavePath.SetWindowText(m_StrCurPath);//重新显示路径  
  11.         KillTimer(2);//关闭定时器  
  12.         break;  
  13.     case 3:  
  14.         m_ctrlManualSend.EnableWindow(TRUE);  
  15.         m_ctrlAutoSend.EnableWindow(TRUE);  
  16.         m_ctrlSendFile.EnableWindow(TRUE);  
  17.         m_strSendFilePathName=m_strTempSendFilePathName;          
  18.         KillTimer(3);  
  19.         if(!(m_ctrlAutoSend.GetCheck()))  
  20.         {  
  21.             CString strStatus;  
  22.             if(m_Port.InitPort(this,m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))  
  23.             {  
  24.                 m_Port.StartMonitoring();  
  25.                 strStatus.Format("STATUS: COM %d OPENED, %d, %c, %d, %d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);  
  26.                 m_ctrlIconOpenoff.SetIcon(m_hIconRed );  
  27.   
  28.             }  
  29.             else  
  30.             {  
  31.                 AfxMessageBox("Failed to reset send buffer size!");  
  32.                 m_ctrlIconOpenoff.SetIcon(m_hIconOff);  
  33.             }  
  34.             m_ctrlPortStatus.SetWindowText(strStatus);  
  35.         }  
  36.         break;  
  37.     default:  
  38.         break;  
  39.     }  
  40.     CDialog::OnTimer(nIDEvent);  
  41. }  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值