VS2015串口通信编程(MFC)笔记

原创 2016年04月10日 00:00:59

前言:

一直很喜欢CSDN这个平台,这是第一次在这里写博客,内容若有不当之处还请多多指教,谢谢!

本笔记主要是记录一些开发过程中可能会遇到的一些注意事项,以加强记忆和提醒。

一、 开发目的:

  开发一个简单的上位机界面程序,实现上位机与下位机串口通信,从而对下位机进行程序升级。

二、 开发环境:

  win7系统; VS2015社区版(免费);USB转TTL模块*2(用于调试);

三、内容:

1.创建MFC项目工程,界面设计直接使用VS2015提供的控件,无非也就是一些按钮、编辑框、下拉框、文本、进度条。

这写可视化操作还是比较简单的。

2.语言细节:

(1). 移位运算: 使用 >> 时高位补1, 使用 << 时低位补0;

(2). int转CString: str.Format(_T("%d"), k); // int k; CString str;

(3) CString转int:k = _ttoi(str); //int k; CString str;

(4).取字符串中的某一部分:str.Mid(s, n); //str的第s个字符开始的n个字符(包括s在内)

(5).将unicode 转换为 char:

   iLength = WideCharToMultiByte(CP_ACP,0, FilePath, -1,NULL,0,NULL,NULL);//先取得长度

   WideCharToMultiByte(CP_ACP,0, FilePath, -1, FPchar, iLength,NULL, NULL);//转换后存入FPchar数组中


3. 选用MSCOMM控件方式进行串口通信

(1). 只能打开不大于COM16的串口;该控件不能在其他线程中直接被调用,但可以将其操作封装到函数中被间接使用。

(2). 接收:MSCOMM控件中断事件,用于接收下位机消息。

(3). 发送:另外创建一个子线程用于控制发送流程。

m_pThread = AfxBeginThread(UpgradeThread, (LPVOID)(this), THREAD_PRIORITY_BELOW_NORMAL, 256 * 1024);//stack size = 256*1024


4. 选用API函数方式进行串口通信

(1). 使用API函数CreateFile打开串口时传入的串口号参数前面需加“\\\\.\\”,否则无法打开大于COM9的串口。(例如打开COM10: "\\\\.\\COM10");

主要有四个函数:

CreateFile //打开

CloseHandle //关闭

ReadFile  //读取

WriteFile  //写入

主要三个变量: 

HANDLE m_HdlSerial = INVALID_HANDLE_VALUE;  //串口句柄

OVERLAPPED m_osRead; //用于读取控制

OVERLAPPED m_osWrite; //用于发送控制

(2). 打开串口(异步重叠方式)

//异步重叠,8个数据位,无校验,1个停止位

HANDLE KSerialOpen(LPCTSTR COMx, DWORD baudrate)

{

HANDLE hCom;

BOOL state;

DCB SerialDCB;


//打开

hCom = CreateFile(

COMx,

GENERIC_READ | GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,

NULL

);

if (hCom == INVALID_HANDLE_VALUE) {//打开失败

return INVALID_HANDLE_VALUE;

}

state = GetCommState(hCom, &SerialDCB);

SerialDCB.BaudRate = baudrate; /* Baudrate at which running, CBR_115200 */

SerialDCB.ByteSize = 8;        /* Number of bits/byte, 4-8 */

SerialDCB.Parity = NOPARITY;    /* 0-4=None,Odd,Even,Mark,Space */

SerialDCB.StopBits = ONESTOPBIT; /* 0,1,2 = 1, 1.5, 2 */

state = SetCommState(hCom, &SerialDCB);

if (!state) { 

CloseHandle(hCom);

return INVALID_HANDLE_VALUE; 

}

//设置缓冲区大小

state = SetupComm(hCom, SERIAL_RECV_BUFFER, SERIAL_SEND_BUFFER);//扱˙, ‰»Îª∫≥Â¥Û–°£¨ ‰≥ˆª∫≥Â¥Û–°

if (!state) {

CloseHandle(hCom);

return INVALID_HANDLE_VALUE;

}

PurgeComm(hCom,  PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);

return hCom;

}


(3). 接收:创建一个线程用于接收下位机消息。

//接收线程

UINT ComRxThread(LPVOID pParam)

{

CmyFileMissionDlg *pMainDlg = (CmyFileMissionDlg *)pParam;


DWORD dwBytes;

int iReadBytes, res;

DWORD dwError = 0;

DWORD dwEvtMask = 0;

unsigned char RxBuffer[1024];


//设置接收时间掩码

if (SetCommMask(m_HdlSerial, EV_RXCHAR) == 0) {

AfxMessageBox(_T("…Ë÷√ ¬º˛—¬Î ß∞‹!"));

return 1;

}

while (TRUE

        {

    if (m_HdlSerial == INVALID_HANDLE_VALUE) {

        return 0;

    }

    if (WaitCommEvent(m_HdlSerial, &dwEvtMask, &m_osRead)) {

        if (dwEvtMask & EV_RXCHAR) { //接收事件

    //TODO

    res = WaitForSingleObject(m_osRead.hEvent, INFINITE);//一直等到异步处理完成

    if (WAIT_OBJECT_0 == res) {

//TODO:进行读取及其他应用操作 (ReadFile)

    }

    PurgeComm(m_HdlSerial, PURGE_RXABORT | PURGE_RXCLEAR);

        }

    }

        }

return 0;

}


(4). 发送:创建一个线程用于控制发送流程。

//发送函数

int KSerialWrite(HANDLE hCom, LPOVERLAPPED lpOverlTx, unsigned char *Buffer, int cnt)

{

BOOL bStatus;

DWORD dwErrorFlags;

DWORD dwBytes = 0;

COMSTAT ComStat;

ClearCommError(hCom, &dwErrorFlags, &ComStat);

bStatus = WriteFile(hCom, Buffer, cnt, &dwBytes, lpOverlTx);

if (!bStatus) {

if (GetLastError() == ERROR_IO_PENDING) {//

GetOverlappedResult(hCom, lpOverlTx, &dwBytes, TRUE);

} else {

dwBytes = 0;

}

}

return dwBytes;

}


5. 关于实现文件选择  

//选择文件,并将文件名显示在编辑框中

void CmyFileMissionDlg::OnBnClickedButton2()

{

    CString fileName = _T("");//

    CString filter = _T("Œƒº˛ (*.bin; *.hex; *.txt)|*.bin;*.hex;*.txt||");//默认文件类型

    CString defaultDir;

    TCHAR exeDirectory[MAX_PATH];

    GetCurrentDirectory(MAX_PATH, exeDirectory);//获取当前路径作为默认路径

    defaultDir.Format(_T("%s"),exeDirectory);

    /* 打开方式打开 */

    CFileDialog openFileDlg(TRUE, defaultDir, fileName, OFN_HIDEREADONLY|OFN_READONLY, filter,NULL);

    openFileDlg.GetOFN().lpstrInitialDir = defaultDir;

    INT_PTR result = openFileDlg.DoModal();//选择文件

    if(result == IDOK) {//选择确定后,将文件名显示到 m_edit1 编辑框中

       m_edit1.SetWindowTextW(openFileDlg.GetPathName());

    }

}


6.后话:

由于本人主要是作嵌入式程序开发,对于上位机程序一般是作为辅助工具,主要用于开发一些简单调试工具。

对于VC++编程还只是接触皮毛,所以本文难免会有见解有误的地方,但是本着相互交流学习的态度还是毅然拙笔狂飞。

结尾之处,应该有:谢谢!






Visio studio 2015 使用串口

Windows下编程使用串口:这里使用VS2015编程。 其中串口相关的头文件如下: /*"Serial_Vs.h"*/ #include #include   #include HA...

VS2015编写的MFC上位机,波特率可调,可动态显示曲线,可显示三维

近期做一个项目正好涉及MFC编写串口上位机,主要用于动态显示曲线和陀螺仪三维信息,想做飞思卡尔或者四旋翼的小伙伴可以借鉴一下,首先贴个结果图: 下面来简单讲解一下这个上位机的核心步骤: 1、首先新...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

VS2017+CnComm串口通讯

CnComm开发库是一位国产的大牛做的,封装得很不错,使用很简单。大牛的博客地址:点击打开链接  最新的库:点击打开链接         其实也没啥必要说怎么开发,因为里面有个很好的demo,其实就...

VS 串口通信SerialPort,官方demo

网上有很多解决方案: 主流大概三种: 1、使用mscomm控件,是微软以前提供的控件,现在已经放弃了。当然在vs中可以手动集成这个控件,也能使用,但是需要注册。 2、自己编程实现串口通信(这个以...

VC2012/VS2012 MFC串口通讯上位机程序教程笔记

使用MFC来编写串口程序,需要有一定的c++语言功底,要清楚MFC代码的组织方式。 鉴于绝大多数的教程还停留在vc6.0这个骨灰级的环境,特在此说明一下VC2012下的代码组织方式,和大家一起交流下~...

VS2015中配置MSComm通讯控件和注意事项

1.MSCommon通讯控件前文回顾 MSComm 作为一个串行通讯控件。在为程序员串口通讯编程节省了很多时间,基于对话框的应用中加入一个MSComm控件非常简单。 MSComm控件提供了两种处...

VS2013 Windows API 串口通信编程--多线程异步方式

转载自:blog.csdn.net/mingojiang 1.串口通信基础 提到串口让人想起并口,它们是计算机中两个比较重要的通信方式. 串口:也叫COM口,把字节的二进制位按位列队进行传输,每个字...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

VS2013开发上位机并调用MSCcommm控件的方式

此文章适合VC++串口通信入门 一、页面布局及添加控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目comm 注意:点击ok,然...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VS2015串口通信编程(MFC)笔记
举报原因:
原因补充:

(最多只允许输入30个字)