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);
}
::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);
}
相关文章推荐
- MFC串口编程——使用标准SerialCom类
- 20120908-串口编程-MSComm使用2-接收Step by Step
- Qt之串口编程--使用事件驱动来触发接收数据
- 用MFC实现串口编程(zz赛迪网)
- 用MFC实现串口编程
- 串行通信的基本原理及用MFC实现串口通信编程
- 串行通信的基本原理及用MFC实现串口通信编程
- 使用MFC快速实现网络编程
- MFC使用GDI+编程基础
- 如何使用串口控件MSComm在dotNet下编程(转)
- 串口调试程序软件GraphdCommDebugger V1.0 与使用手册
- 使用MFC快速实现网络编程 CAsyncSocket
- 串行通信的基本原理及用MFC实现串口通信编程通信编程实现原理基本串口//数据操作线程
- 用MFC实现串口编程
- 用MFC实现串口编程
- 使用MFC开始openGL编程
- 用MFC实现串口编程
- 用MFC实现串口编程
- [转]如何使用串口控件MSComm在dotNet下编程
- 使用MFC快速实现网络编程 CAsyncSocket