• 串口


    // 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: est.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] = '';
    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();
    }

  • 相关阅读:
    js事件监听机制(事件捕获)
    js预解析
    前端工程师也要关注代码版本控制
    BOM跟DOM的区别和关联
    web开发,click,touch,tap事件浅析
    prototype
    CSS:haslayout
    canvas画图
    第一个json解析:ps:(内容待完善)
    json解析实例
  • 原文地址:https://www.cnblogs.com/xiaoxiaocaicai/p/3548855.html
Copyright © 2020-2023  润新知