// SeriesCommDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SeriesComm.h"
#include
"SeriesCommDlg.h"
#include "Shlwapi.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char
THIS_FILE[] = __FILE__;
#endif
#define FILE_BLOCK_SIZE 1024 //16
//
/////////////////////////////////////////////////////////////////////////////
//
CSeriesCommDlg dialog
CSeriesCommDlg::CSeriesCommDlg(CWnd* pParent /*=NULL*/)
:
CDialog(CSeriesCommDlg::IDD,
pParent)
{
//{{AFX_DATA_INIT(CSeriesCommDlg)
m_strRecv =
_T("");
m_strSend = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon
does not require a subsequent DestroyIcon in Win32
m_hIcon =
AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSeriesCommDlg::DoDataExchange(CDataExchange*
pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSeriesCommDlg)
DDX_Control(pDX,
IDC_EDIT_RECV, m_EditMsg);
DDX_Control(pDX, IDC_EDIT_COM_STATE,
m_ComState);
DDX_Control(pDX, IDC_COMBO_BAUD,
m_CBoxBaud);
DDX_Control(pDX, IDC_COMBO_COM,
m_CBoxSetCom);
DDX_Control(pDX, IDC_MSCOMM1, m_ctrlComm);
DDX_Text(pDX,
IDC_EDIT_RECV, m_strRecv);
//}}AFX_DATA_MAP
DDX_Control(pDX,
IDC_BTN_SEND, m_btnSend);
}
BEGIN_MESSAGE_MAP(CSeriesCommDlg,
CDialog)
//{{AFX_MSG_MAP(CSeriesCommDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_EXIT,
OnBtnExit)
ON_BN_CLICKED(IDC_BTN_SEND,
OnBtnSend)
ON_CBN_SELCHANGE(IDC_COMBO_BAUD,
OnSelchangeComboBaud)
ON_CBN_SELCHANGE(IDC_COMBO_COM,
OnSelchangeComboCom)
//}}AFX_MSG_MAP
ON_WM_CLOSE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
CSeriesCommDlg message handlers
BOOL CSeriesCommDlg::OnInitDialog()
{
BOOL
ret;
CDialog::OnInitDialog();
// Set the icon for this dialog. The
framework does this automatically
// when the application‘s main window is
not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon,
FALSE); // Set small icon
// TODO: Add extra initialization
here
CString strCmdLine;
//取命令行参数 "D:\test.bin 1" //命令行参数为1则是下载图片数据
为2则表示下载用户程序
//参数1:源文件路径; 参数2:选择下载用户程序或图片
strCmdLine =
AfxGetApp()->m_lpCmdLine;
m_strPath = strCmdLine.Left(strCmdLine.GetLength()-2);
if (m_strPath.GetLength()-4 !=
m_strPath.Find(".bin"))
{
MessageBox("参数传递不正确,请与厂家联系.", "程序异常",
MB_OK);
}
else
{
m_flag =
strCmdLine[strCmdLine.GetLength()-1];
}
m_strBaud
="115200";
m_CBoxSetCom.SetCurSel(0);
m_CBoxBaud.SetCurSel(5);
ret
= SetComPort(1); //初始化串口
if (ret)
{
m_nMsgFlag =
0;
m_nRxLen = 0;
m_nFileSize = 0;
m_hEvent = CreateEvent(NULL,
FALSE, FALSE, NULL);
m_ComState.SetWindowText("COM1 已打开.
115200,N,8,1");
}
else
{
m_bComStatus =
FALSE;
m_ComState.SetWindowText("COM1
没有发现此串口或被占用,请重新选择串口");
}
return TRUE; // return TRUE unless you
set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code
below
// to draw the icon. For MFC applications using the document/view
model,
// this is automatically done for you by the framework.
void CSeriesCommDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC
dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND,
(WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client
rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon =
GetSystemMetrics(SM_CYICON);
CRect
rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) /
2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the
icon
dc.DrawIcon(x, y,
m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user
drags
// the minimized window.
HCURSOR
CSeriesCommDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CSeriesCommDlg::OnBtnExit()
{
// TODO: Add your control
notification handler code here
if
(m_bComStatus)
{
m_ctrlComm.SetPortOpen(0);
CloseHandle(m_hThread);
CloseHandle(m_hEvent);
}
CDialog::OnCancel();
}
void CSeriesCommDlg::SendString(BYTE *Buf, int len)
{
CByteArray
array;
int i=0;
if(Buf)
{
array.RemoveAll(); //清空数组
array.SetSize(len); //设置数组大小为帧长度
for(i=0; i<len; i++)
//把待发送数据存入数组
array.SetAt(i,Buf[i]);
m_ctrlComm.SetOutput(COleVariant(array));
}
}
BYTE
ucCurrBlock=0; //当前段号
DWORD WINAPI ThreadFunc(LPVOID
lpParameter)
{
int i=0;
CSeriesCommDlg * pThis
=(CSeriesCommDlg*)lpParameter;
BYTE
cHandDate[5]={0xA1,0xB2,0xC3,0xD4,0x00};
BYTE
cNum[6]={0xAA,0xBB,0x01,0x00,0x00,0x00};
BYTE
cFileInfo[6]={0xAA,0xCC,0x00,0x00,0x20,0x00};
BYTE
cEnd[3]={0xAA,0xDD,0x00};
BYTE ucFileBlcok=0; //文件段数
WORD
wSendSize=0; //当前段长
int nFileSize = 0; //文件大小
if(pThis->m_flag == ‘1‘) //1 表示下载图片数据
{
cNum[3] =
0x01;
}
else if(pThis->m_flag == ‘2‘) //2 表示下载用户程序
{
cNum[3] =
0x02;
}
nFileSize = pThis->m_nFileSize;
if(nFileSize < FILE_BLOCK_SIZE)
{
ucFileBlcok =
1;
}
else
{
if( (nFileSize % FILE_BLOCK_SIZE) == 0
)
ucFileBlcok = nFileSize / FILE_BLOCK_SIZE;
else
ucFileBlcok =
nFileSize / FILE_BLOCK_SIZE + 1;
}
cNum[4] = ucFileBlcok;
pThis->SendString(cHandDate, 4); //发握手包 send
1
pThis->m_EditMsg.SetWindowText("发握手包");
pThis->m_btnSend.EnableWindow(false);
for(;;)
{
WaitForSingleObject(pThis->m_hEvent, INFINITE); //1500
//INFINITE
switch(pThis->m_nMsgFlag)
{
case
0:
pThis->m_EditMsg.SetWindowText("接收超时,系统重发。");
pThis->MessageBox("控制器没有返回,请确认连接是否正常,点确认后系统重发。",
"提示", MB_OK);
pThis->SendString(cHandDate, 4); //发握手包
send 1
pThis->m_EditMsg.SetWindowText("发握手包");
break;
case
1:
ucCurrBlock=0;
pThis->m_nRxLen = 2;
pThis->SendString(cNum, 5); // send
2
pThis->m_EditMsg.SetWindowText("发文件接收扇区");
break;
case 2:
if (ucFileBlcok == ucCurrBlock)
{
pThis->SendString(cEnd,
2);
pThis->m_EditMsg.SetWindowText("发完成命令");
break;
}
if (ucFileBlcok > (ucCurrBlock+1)) // send
3
{
wSendSize =
FILE_BLOCK_SIZE;
}
else
{
wSendSize = nFileSize -
ucCurrBlock*FILE_BLOCK_SIZE;
}
cFileInfo[2] =
ucCurrBlock;
cFileInfo[3] = (BYTE)(wSendSize>>8);
cFileInfo[4]
= (BYTE)(wSendSize&0x00FF);
pThis->SendString(cFileInfo, 5);
if(pThis->pFileBuf)
{
pThis->SendString(pThis->pFileBuf+(ucCurrBlock*FILE_BLOCK_SIZE),
wSendSize);
}
else
{
::MessageBox(pThis->GetSafeHwnd(),_T("pThis->Buf为空"),NULL,0);
}
pThis->m_EditMsg.SetWindowText("发送数据");
ucCurrBlock++;
break;
case
5:
pThis->m_EditMsg.SetWindowText("下载完成");
pThis->m_btnSend.EnableWindow(true);
pThis->m_nRxLen
= 2;
if(pThis->pFileBuf)
{
int flag =
::ResetEvent(pThis->m_hEvent);
delete
pThis->pFileBuf;
pThis->pFileBuf =
NULL;
CloseHandle(pThis->m_hThread);
}
if(IDOK ==
MessageBox(pThis->GetSafeHwnd(),_T("下载完成!"),NULL,0))
{
pThis->Destroy()
;
}
break;
default:
pThis->m_nRxLen = 0;
break;
}
i++;
}
return 0x00;
}
BEGIN_EVENTSINK_MAP(CSeriesCommDlg,
CDialog)
//{{AFX_EVENTSINK_MAP(CSeriesCommDlg)
ON_EVENT(CSeriesCommDlg,
IDC_MSCOMM1, 1 /* OnComm */, OnOnCommMscomm1,
VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
void CSeriesCommDlg::Destroy()
{
CSeriesCommApp * pApp =
(CSeriesCommApp*)::AfxGetApp();
CSeriesCommDlg * pDlg =
(CSeriesCommDlg*)pApp->m_pMainWnd;
pDlg->SendMessage(WM_CLOSE);
}
void
CSeriesCommDlg::OnOnCommMscomm1()
{
// TODO: Add your control
notification handler code here
VARIANT variant_inp;
COleSafeArray
safearray_inp;
LONG len,k;
CString strtemp;
BYTE
cFileFlag[4]={0xAA,0xBB,0x01,0x00};
BYTE rxData[2048]={0};
//设置BYTE数组
//static LONG lSize=0;
m_nRxLen = 2;
if(m_ctrlComm.GetCommEvent()==2)
//事件值为2表示接收缓冲区内有字符
{
variant_inp=m_ctrlComm.GetInput();
//读缓冲区
safearray_inp=variant_inp;
//VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize();
//得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxData+k);
//转换为BYTE型数组
//lSize += len;
if (len >=
m_nRxLen)
{
if (rxData[0]==0x55 && rxData[1]==0x55)
//握手包
{
m_nMsgFlag = 1;
memset(rxData, 0,
sizeof(rxData));
::SetEvent(m_hEvent);
}
else if
(rxData[0]==0xBB && rxData[1]==0xAA) //写flash扇区号 0 or
1
{
m_nMsgFlag = 2;
memset(rxData, 0,
sizeof(rxData));
::SetEvent(m_hEvent);
}
else if
(rxData[0]==0xCC && rxData[1]==0xAA) //继续发下一块数据
{
m_nMsgFlag =
2;
memset(rxData, 0,
sizeof(rxData));
::SetEvent(m_hEvent);
}
else if
(rxData[0]==0xDD && rxData[1]==0xAA) //数据完成
{
m_nMsgFlag =
5;
memset(rxData, 0,
sizeof(rxData));
::SetEvent(m_hEvent);
}
else
{
m_nMsgFlag
= -1;
memset(rxData, 0,
sizeof(rxData));
}
}
/*
for(k=0;k<len;k++)
//将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxData+k);
//字符型
strtemp.Format("%c",bt);
//将字符送入临时变量strtemp存放
m_strRecv+=strtemp; //加入接收编辑框对应字符串
}*/
}
UpdateData(FALSE);
}
void CSeriesCommDlg::OnBtnSend()
{
CFile
fp;
UpdateData(TRUE);
int err =
0;
//fp.Open(m_strPath, CFile::modeRead);
fp.Open("D:\\ceshi.bin",
CFile::modeRead); //不读命令行参数时,用绝对路径
m_nFileSize = fp.GetLength();
if
(m_nFileSize > 0)
{
pFileBuf = new
BYTE[m_nFileSize+1];
memset(pFileBuf,0,m_nFileSize);
if( (err =
fp.Read(pFileBuf, m_nFileSize)) == 0 || !pFileBuf)
{
MessageBox(_T("文件读取失败"));
}
pFileBuf[m_nFileSize] =
‘\0‘;
fp.Close();
m_hThread =
::CreateThread(NULL,
0,
ThreadFunc,
this,
0,//CREATE_SUSPENDED
挂起
&m_dwThreadId);
::SetThreadPriority(m_hThread,THREAD_PRIORITY_HIGHEST);
}
else
{
MessageBox("文件为空或不存在!",
"错误", MB_OK);
}
//BYTE
cHandDate[5]={0xA1,0x00,0xC3,0xD4,0x00};
//m_ctrlComm.SetOutput(COleVariant(m_strSend));
//发送数据
//CSeriesCommDlg::SendString(cHandDate,
4);
//UpdateData(TRUE);
}
void CSeriesCommDlg::OnSelchangeComboBaud()
{
// TODO: Add your
control notification handler code here
CString temp,str;
int
i=m_CBoxBaud.GetCurSel();
switch(i)
{
case
0:
m_strBaud="9600";
break;
case
1:
m_strBaud="19200";
break;
case
2:
m_strBaud="38400";
break;
case
3:
m_strBaud="56000";
break;
case
4:
m_strBaud="57600";
break;
case
5:
m_strBaud="115200";
break;
default:
break;
}
if
(!m_bComStatus)
{
m_ComState.SetWindowText("串口没有打开不能进行此操作!");
return;
}
temp
= m_strBaud + ",n,8,1";
m_ctrlComm.SetSettings(temp);
i=m_CBoxSetCom.GetCurSel();
m_CBoxSetCom.GetLBText(i,str);
str +=
"已打开. "+ temp;
m_ComState.SetWindowText(str);
}
void CSeriesCommDlg::OnSelchangeComboCom()
{
// TODO: Add your
control notification handler code here
int
index=m_CBoxSetCom.GetCurSel();
CString str;
CString
strTemp="COM";
CString strBaud;
BOOL
ret;
m_CBoxSetCom.GetLBText(index,str);
strTemp = str;
str += "
没有发现此串口或被占用,请重新选择串口";
if (!m_bComStatus)
{
m_hEvent =
CreateEvent(NULL, FALSE, FALSE, NULL);
}
ret = SetComPort(index+1);
//初始化串口
if (!ret)
{
m_bComStatus =
FALSE;
m_ComState.SetWindowText(str);
return;
}
strBaud =
m_strBaud+",n,8,1";
m_ctrlComm.SetSettings(strBaud);
strTemp +=
"已打开. "+
strBaud;
m_ComState.SetWindowText(strTemp);
//MessageBox(str, "错误",
MB_OK);
}
BOOL CSeriesCommDlg::SetComPort(int index)
{
HANDLE m_hCom;
CString strComPort="COM";
CString strError;
CString
strTemp;
strComPort.Format("COM%d",index);
//
这里的CreateFile函数起了很大的作用,可以用来创建系统设备文件,如果该设备不存在或者被占用,
// 则会返回一个错误,即下面的
INVALID_HANDLE_VALUE ,据此可以判断可使用性。详细参见MSDN中的介绍。
m_hCom =
CreateFile(strComPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, NULL);
if(m_hCom == INVALID_HANDLE_VALUE) // 如果没有该设备,或者被其他应用程序在用
{
CloseHandle(m_hCom); // 关闭文件句柄,后面我们采用控件,不用API
m_bComStatus =
FALSE;
strError = strComPort +"
没有发现此串口或被占用,请重新选择串口";
m_ComState.SetWindowText(strError);
AfxMessageBox(strError,MB_OK);
return
FALSE;
}
else
{
m_bComStatus = TRUE;
CloseHandle(m_hCom);
}
try
{
if(m_ctrlComm.GetPortOpen())
//如果串口是打开的,则行关闭串口
{
m_ctrlComm.SetPortOpen(FALSE);
}
m_ctrlComm.SetCommPort(index);
//选择COM1
m_ctrlComm.SetInputMode(1);
//输入方式为二进制方式
m_ctrlComm.SetInBufferSize(1024);
//设置输入缓冲区大小
//设置输出缓冲区大小,波特率9600,无校验,8个数据位,1个停止位
m_ctrlComm.SetOutBufferSize(1024);
strTemp = m_strBaud +
",N,8,1";
m_ctrlComm.SetSettings(strTemp);
if(!m_ctrlComm.GetPortOpen())
{
m_ctrlComm.SetPortOpen(TRUE);
//打开串口
}
//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
m_ctrlComm.SetRThreshold(1);
m_ctrlComm.SetInputLen(0);
//设置当前接收区数据长度为0
m_ctrlComm.GetInput();
//先预读缓冲区以清除残留数据
return TRUE;
}
catch(CException * /*e*/)
{
m_bComStatus = FALSE;
MessageBox("没有发现此串口或被占用,请重新选择串口", "错误",
MB_OK);
return FALSE;
}
}
void CSeriesCommDlg::OnClose()
{
// TODO:
在此添加消息处理程序代码和/或调用默认值
if(pFileBuf)
{
delete pFileBuf;
pFileBuf
= NULL;
}
if(m_hThread)
{
CloseHandle(m_hThread);
m_hThread =
NULL;
}
/**/
if(m_ctrlComm.GetPortOpen())
//如果串口是打开的,则行关闭串口
{
m_ctrlComm.SetPortOpen(FALSE);
}
CDialog::OnClose();
}
原文:http://www.cnblogs.com/xiaoxiaocaicai/p/3548855.html