📄 pc2pcview.cpp
字号:
// PC2PCView.cpp : implementation of the CPC2PCView class
//
#include "stdafx.h"
#include "PC2PC.h"
#include "PC2PCDoc.h"
#include "PC2PCView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
HANDLE hCom; //串口的句柄
HANDLE hThreadEvent; //事件线程句柄
DWORD ThreadProcEvent(LPVOID pParam); //事件响应函数
bool fEventRun; //事件线程函数执行标志
HWND hWnd; //窗口句柄
DWORD dwThreadID; //事件线程ID
OVERLAPPED Eol={0}; //事件线程使用的OVERLAPPED结构Eol
OVERLAPPED Wol={0}; //写操作使用的OVERLAPPED结构Wol
OVERLAPPED Rol={0}; //读操作使用的OVERLAPPED结构Rol
DWORD dwTimeoutValue; //定义接收超时时间,ms为单位,在事件线程中使用
/////////////////////////////////////////////////////////////////////////////
// CPC2PCView
IMPLEMENT_DYNCREATE(CPC2PCView, CEditView)
BEGIN_MESSAGE_MAP(CPC2PCView, CEditView)
//{{AFX_MSG_MAP(CPC2PCView)
ON_COMMAND(ID_SETUPCOM, OnSetupcom)
ON_COMMAND(ID_SENDFILE, OnSendfile)
ON_COMMAND(ID_OPENCOM, OnOpencom)
ON_COMMAND(ID_CLOSECOM, OnClosecom)
ON_UPDATE_COMMAND_UI(ID_SENDFILE, OnUpdateSendfile)
ON_UPDATE_COMMAND_UI(ID_SETUPCOM, OnUpdateSetupcom)
ON_UPDATE_COMMAND_UI(ID_OPENCOM, OnUpdateOpencom)
ON_UPDATE_COMMAND_UI(ID_CLOSECOM, OnUpdateClosecom)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateAppExit)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_MYMSG,OnReceiveEvent)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPC2PCView construction/destruction
CPC2PCView::CPC2PCView()
{
// TODO: add construction code here
myCom="COM4"; //默认设置
myBaudRate=CBR_4800;
myfParity=false;
myParity=NOPARITY;
}
CPC2PCView::~CPC2PCView()
{
}
BOOL CPC2PCView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
BOOL bPreCreated = CEditView::PreCreateWindow(cs);
cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL); // Enable word-wrapping
return bPreCreated;
}
/////////////////////////////////////////////////////////////////////////////
// CPC2PCView drawing
void CPC2PCView::OnDraw(CDC* pDC)
{
CPC2PCDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CPC2PCView diagnostics
#ifdef _DEBUG
void CPC2PCView::AssertValid() const
{
CEditView::AssertValid();
}
void CPC2PCView::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
CPC2PCDoc* CPC2PCView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPC2PCDoc)));
return (CPC2PCDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPC2PCView message handlers
void CPC2PCView::OnSetupcom()
{
// TODO: Add your command handler code here
CString strStatus;
if(mySetupDlg.DoModal()==IDOK)
{
switch (mySetupDlg.m_Com)
{
case 0:
{
strStatus="COM1";
strStatus+=" ";
myCom="COM1";
break;
}
case 1:
{
strStatus="COM2";
strStatus+=" ";
myCom="COM2";
break;
}
case 2:
{
strStatus="COM3";
strStatus+=" ";
myCom="COM3";
break;
}
case 3:
{
strStatus="COM4";
strStatus+=" ";
myCom="COM4";
break;
}
case 4:
{
strStatus="COM5";
strStatus+=" ";
myCom="COM5";
}
break;
case 5:
{
strStatus="COM6";
strStatus+=" ";
myCom="COM6";
}
break;
}
switch(mySetupDlg.m_BaudRate)
{
case 0:
{
strStatus+="19200";
strStatus+=" ";
myBaudRate=CBR_19200;
break;
}
case 1:
{
strStatus+="9600";
strStatus+=" ";
myBaudRate=CBR_9600;
break;
}
case 2:
{
strStatus+="4800";
strStatus+=" ";
myBaudRate=CBR_4800;
break;
}
case 3:
{
strStatus+="2400";
strStatus+=" ";
myBaudRate=CBR_2400;
break;
}
}
switch(mySetupDlg.m_Parity)
{
case 0:
{
myfParity=false;
myParity=NOPARITY;
strStatus+="N";
strStatus+="-8-1";
break;
}
case 1:
{
myfParity=TRUE;
myParity=ODDPARITY;
strStatus+="O";
strStatus+="-8-1";
break;
}
case 2:
{
myfParity=true;
myParity=EVENPARITY;
strStatus+="E";
strStatus+="-8-1";
break;
}
}
CMainFrame* m_pGetFrame=(CMainFrame*) AfxGetApp()->m_pMainWnd ;
CStatusBar* m_pStatus=&m_pGetFrame->m_wndStatusBar;
m_pStatus->SetPaneText(1,strStatus); //将通信参数显示在状态条上
blnSeted=true;
}
}
void CPC2PCView::OnSendfile()
{
// TODO: Add your command handler code here
CFileDialog myFileDlg(true); //打开文件对话框
CEdit& myEdit=this->GetEditCtrl();
BYTE bytFileNameLen; //文件名字符串的长度
BYTE bytTemp;
DWORD dwTemp1,dwTemp2;
int i;
CString myStr,myFileName,myPathName;
CFileException e; //文件异常变量
bytActStatus=1; //置为发送态
if(myFileDlg.DoModal()==IDOK) //调出文件选择对话框,选择传送的文件
{
myPathName=myFileDlg.GetPathName();
myFileName=myFileDlg.GetFileName();
if(myFileName.GetLength()>100)
{
AfxMessageBox("文件名长度应小于100!");
bytActStatus=10; //恢复为接收态
return;
}
else
{
bytFileNameLen=(BYTE)myFileName.GetLength();
}
}
else
{
bytActStatus=10; //恢复为接收态
return;
}
myPathName.Replace("\\","\\\\"); //将文件名中的单“\”替换成双“\\”
//打开选定的文件
if(!myFile.Open(myPathName,CFile::modeRead|CFile::typeBinary|CFile::shareDenyWrite,&e))
{
myStr.Format("%02X",e.m_cause);//文件打开错误处理,错误代码为m_cause
myStr+="error";
AfxMessageBox(myStr);
bytActStatus=10; //恢复为接收态
return;
}
dwFileLen=myFile.GetLength();
if(dwFileLen>=67108864)
{
AfxMessageBox("文件必须小于64MB!");//检查文件尺寸<64MB
bytActStatus=10; //恢复为接收态
return;
}
arrSendData[0]=05; //ENQ
arrSendData[4]=(BYTE)(dwFileLen/16777216);
dwTemp1=dwFileLen%16777216;
arrSendData[3]=(BYTE)(dwTemp1/65536);
dwTemp2=dwTemp1%65536;
arrSendData[2]=(BYTE)(dwTemp2/256);
arrSendData[1]=(BYTE)(dwTemp2%256);
arrSendData[5]=bytFileNameLen;
for(i=6;i<=bytFileNameLen+5;i++) //保存文件名称
{
arrSendData[i]=myFileName.GetAt(i-6);
}
bytTemp=0;
for(i=0;i<=bytFileNameLen+5;i++)
{
bytTemp^=arrSendData[i];
}
arrSendData[bytFileNameLen+6]=bytTemp;//计算出校验位
bytSendStatus=1;
bytResendCount=0;
Write(arrSendData,bytFileNameLen+7);
myEdit.SetSel(1000000,1000000);
myEdit.ReplaceSel("发出传输请求。\15\12");
blnNoTimeout=false;
}
void CPC2PCView::OnOpencom()
{
// TODO: Add your command handler code here
//打开串口操作
hCom=CreateFile(myCom, //打开串口COM2
GENERIC_READ | GENERIC_WRITE, //使用读写方式
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //使用重叠方式
NULL);
if( hCom !=INVALID_HANDLE_VALUE)
{
SetupComm(hCom,1500,1500); //设置发送缓冲1500,接收缓冲区1500
DCB myDCB;
GetCommState( hCom, &myDCB ); //获取当前串口参数
myDCB.BaudRate=myBaudRate;
myDCB.fBinary=TRUE;
myDCB.fParity=myfParity;
myDCB.ByteSize=8;
myDCB.Parity=myParity;
myDCB.StopBits=ONESTOPBIT;
SetCommState(hCom,&myDCB); //设置串口通信参数
blnOpened=true;
//创建并立即执行线程函数
DWORD dwParam;
if (!SetCommMask(hCom,EV_RXCHAR))// | EV_TXEMPTY))//设置允许的事件类型
{
AfxMessageBox("建立事件掩码失败!");
}
hThreadEvent=CreateThread(NULL, //创建事件线程
0,
(LPTHREAD_START_ROUTINE )ThreadProcEvent, //指定线程函数名称
&dwParam,
0, //创建线程函数后,立即执行
&dwThreadID);
if (hThreadEvent==INVALID_HANDLE_VALUE)
{
AfxMessageBox("事件线程创建失败!");
}
fEventRun=true; //允许事件函数执行循环体
bytActStatus=10;
bytSendStatus=0;
bytRcvStatus=0;
bytResendCount=0;
uintStxCurNo=0;
}
else
{
AfxMessageBox("创建串口失败!");
}
}
void CPC2PCView::OnClosecom()
{
// TODO: Add your command handler code here
fEventRun=false; //停止事件线程循环体的操作
WaitForSingleObject(hThreadEvent, //等待事件线程函数退出
INFINITE); //无限时地等待,直到事件线程函数退出
CloseHandle(hThreadEvent); //关闭事件线程句柄
CloseHandle(hCom); //关闭串口句柄
blnOpened=false;
}
//事件线程函数
DWORD ThreadProcEvent(LPVOID pParam)
{
DWORD dwErrors;
COMSTAT Rcs;
DWORD dwEvtMask,dwRes;
Eol.hEvent=CreateEvent(NULL, //设置Eol.hEvent成员为无信号状态
TRUE,
FALSE,
NULL);
while(fEventRun)
{
WaitCommEvent(hCom, //监视串口事件
&dwEvtMask, //存放事件掩码组合值
&Eol); //OVERLAPPED结构
dwRes=WaitForSingleObject(Eol.hEvent, //等待的事件对象句柄
dwTimeoutValue); //超时时间(ms)
switch (dwRes)
{
case WAIT_OBJECT_0: //成功得到事件监视结果
{
switch (dwEvtMask)
{
case EV_RXCHAR: //接收到数据
{
//向主线程发送消息,接收到数据
ClearCommError(hCom, //串口句柄
&dwErrors, //存放出错信息的掩码组合
&Rcs); //COMSTAT类型结构变量
if(Rcs.cbInQue!=0)
{
::PostMessage(hWnd, //目的窗口句柄
WM_MYMSG, //消息名称
0, //传递的参数1
(LPARAM)EV_RXCHAR ); //传递的参数2
}
break;
}
case EV_TXEMPTY: //发送缓冲区已空
{
//这里可加入发送缓冲区空的处理代码,或向主线程发送消息
break;
}
}
break;
}
case WAIT_TIMEOUT:
{
//传递超时消息给主线程
::PostMessage(hWnd, //目的窗口句柄
WM_MYMSG, //消息名称
0, //传递的参数1
(LPARAM)100 ); //传递的参数100
break;
}
}
}
return true;
}
//消息响应函数
LONG CPC2PCView::OnReceiveEvent(WPARAM wParam,LPARAM lParam)
{
CFileDialog myFileDlg(false); //保存文件对话框
BYTE myByte[1100];
BYTE bytTemp;
CString strDis,strDis1;
char *myChar; //获取文件名时使用
char myName[300];
char myExt[5];
int i;
CEdit& myEdit=this->GetEditCtrl();
CMainFrame* m_pGetFrame=(CMainFrame*) AfxGetApp()->m_pMainWnd ;
CStatusBar* m_pStatus=&m_pGetFrame->m_wndStatusBar;
CFileException e;
switch(bytActStatus)
{
case 1://发送操作
{
switch(bytSendStatus)//发送的不同状态
{
case 1://发送操作的1态
{
switch(lParam)
{
case EV_RXCHAR://lParam=EV_RXCHAR即1,说明读线程收到数据
{
blnNoTimeout=true;
bytTimeoutCounter=0;
switch(Detect(1))
{
case 0://收到指定数量的字符
{
break;
}
case 4://超时错误
{
DisSend(4);
blnNoTimeout=false;
return -1;
break;
}
case 8://无效,输入缓冲区中字符数量为0
{
blnNoTimeout=false;
return 0;
break;
}
}
switch(Read(myByte,1))
{
case 0:
{
//继续后面的操作
break;
}
case 4://超时错误
{
DisSend(4);
return -1;
break;
}
case 16://读操作失败
{
DisSend(16);
return -1;
break;
}
}
switch(myByte[0])
{
case 6://响应是ACK
{
//发送当前序号的数据
uintStxCurNo=1;
myEdit.SetSel(1000000,1000000);
myEdit.ReplaceSel("正在传送数据……\15\12");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -