当我们在用VS进行串口编程时,在打开串口前,经常想知道当前PC上存在多少个串口,哪些串口可用?哪些串口已经打开了,最好是在一个Combo Box中列表系统当前所有可用的串口以供选择,然而如何获取系统当前可用的串口有哪些呢?

这里介绍的方法也是最简单也是最笨的一种方法,即一个一个去试,试完了就知道了。至于还有没有其它更好的方法,暂不在本文所讨论的范围之内。

一个在对话框的OnInitDialog函数内做如下操作:

1 初始化时检测串口

  1. BOOL Ctbox_debug_viewDlg::OnInitDialog()
  2. {
  3. CDialogEx::OnInitDialog();
  4. // Add "About..." menu item to system menu.
  5. // IDM_ABOUTBOX must be in the system command range.
  6. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  7. ASSERT(IDM_ABOUTBOX < 0xF000);
  8. CMenu* pSysMenu = GetSystemMenu(FALSE);
  9. if (pSysMenu != NULL)
  10. {
  11. BOOL bNameValid;
  12. CString strAboutMenu;
  13. bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
  14. ASSERT(bNameValid);
  15. if (!strAboutMenu.IsEmpty())
  16. {
  17. pSysMenu->AppendMenu(MF_SEPARATOR);
  18. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  19. }
  20. }
  21. // Set the icon for this dialog.  The framework does this automatically
  22. //  when the application's main window is not a dialog
  23. SetIcon(m_hIcon, TRUE);         // Set big icon
  24. SetIcon(m_hIcon, FALSE);        // Set small icon
  25. // TODO: Add extra initialization here
  26. AddCom();//向组合框中添加串口设备
  27. m_CombolPort.SetCurSel(0);
  28. //...
  29. }

AddCom函数如下定义:

  1. void Ctbox_debug_viewDlg::AddCom(void)
  2. {
  3. EnumerateSerialPorts(ports,portse,portsu);
  4. unsigned short uicounter;
  5. unsigned short uisetcom;
  6. CString str;
  7. //获取可用串口个数
  8. uicounter = portse.GetSize();
  9. //如果个数大于0
  10. if(uicounter > 0)
  11. {
  12. //初始化串口列表框
  13. for(int i=0; i<uicounter; i++)
  14. {
  15. uisetcom = portse.ElementAt(i);
  16. str.Format(_T("COM%d "),uisetcom);
  17. m_CombolPort.AddString(str);
  18. }
  19. }
  20. }

EnumerateSerialPorts函数如下:

  1. void Ctbox_debug_viewDlg::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu)
  2. {
  3. //清除串口数组内容
  4. ports.RemoveAll();
  5. portse.RemoveAll();
  6. portsu.RemoveAll();
  7. //因为至多有255个串口,所以依次检查各串口是否存在
  8. //如果能打开某一串口,或打开串口不成功,但返回的是 ERROR_ACCESS_DENIED错误信息,
  9. //都认为串口存在,只不过后者表明串口已经被占用
  10. //否则串口不存在
  11. for (int i=1; i<256; i++)
  12. {
  13. //Form the Raw device name
  14. CString sPort;
  15. sPort.Format(_T("\\\\.\\COM%d"), i);
  16. //Try to open the port
  17. BOOL bSuccess = FALSE;
  18. HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  19. if (hPort == INVALID_HANDLE_VALUE)
  20. {
  21. DWORD dwError = GetLastError();
  22. if (dwError == ERROR_ACCESS_DENIED)
  23. {
  24. bSuccess = TRUE;
  25. portsu.Add(i);       //已占用的串口
  26. }
  27. }
  28. else
  29. {
  30. //The port was opened successfully
  31. bSuccess = TRUE;
  32. portse.Add(i);      ////可用的串口
  33. //Don't forget to close the port, since we are going to do nothing with it anyway
  34. CloseHandle(hPort);
  35. }
  36. //Add the port number to the array which will be returned
  37. if (bSuccess)
  38. ports.Add(i);   //所有存在的串口
  39. }
  40. }

如上操作即可将系统当前可用的所有串口添加到CombolPort所对应的Combol Box中了。

2 打开串口

代码如下:

  1. void Ctbox_debug_viewDlg::OnBnClickedBtOpen()
  2. {
  3. // TODO: Add your control notification handler code here
  4. if(m_mscomm.get_PortOpen())
  5. {
  6. m_mscomm.put_PortOpen(FALSE);
  7. GetDlgItem(IDC_BT_OPEN)->SetWindowText(_T("打开"));
  8. ShowInfo(_T("关闭串口成功!"));
  9. m_OpenStatus =false;
  10. return;
  11. }
  12. UpdateData(TRUE);
  13. m_OpenStatus =true;
  14. //当前端口号
  15. int curPort =portse.ElementAt(m_CombolPort.GetCurSel());
  16. m_mscomm.put_CommPort(curPort);//端口号
  17. m_mscomm.put_InBufferSize(1024);//接收缓冲区
  18. m_mscomm.put_OutBufferSize(1024);//发送缓冲区
  19. m_mscomm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取
  20. m_mscomm.put_InputMode(1);//以二进制方式读写数据
  21. m_mscomm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
  22. //波特率
  23. DWORD baudrate;
  24. switch(m_CombolBaudrate.GetCurSel())
  25. {
  26. case 0:
  27. baudrate =115200;
  28. break;
  29. case 1:
  30. baudrate =9600;
  31. break;
  32. default:
  33. ASSERT(FALSE);
  34. break;
  35. }
  36. CString setting;
  37. setting.Format(_T("%d,n,8,1"),baudrate);
  38. m_mscomm.put_Settings(setting/*_T("115200,n,8,1")*/);//波特率,无校验,8个数据位,1个停止1位
  39. m_mscomm.put_PortOpen(TRUE);//打开串口
  40. GetDlgItem(IDC_BT_OPEN)->SetWindowText(_T("关闭"));
  41. ShowInfo(_T("打开串口成功!"));
  42. }

3 串口热拔插时检测串口

这里主要利用Cwnd的ON_WM_DEVICECHANGE消息来处理。

ON_WM_DEVICECHANGE消息在VS2010中好像只能通过手动来添加,反正我没找到可以通过对话的形式来添加的,后续有知道的兄台麻烦告知我一下。

因此,首先得手动添加ON_WM_DEVICECHANGE消息:

第一步:在消息映射BEGIN_MESSAGE_MAP(Ctbox_debug_viewDlg, CDialogEx)中添加:

  1. ON_WM_DEVICECHANGE()

第二步:在头文件类的定义中添加函数声明:

  1. afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);

第三步:实现函数

  1. BOOL Ctbox_debug_viewDlg::OnDeviceChange(UINT nEventType,DWORD dwData)
  2. {
  3. //DEV_BROADCAST_DEVICEINTERFACE* dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;
  4. switch (nEventType)
  5. {
  6. case DBT_DEVICEREMOVECOMPLETE://移除设备
  7. case DBT_DEVICEARRIVAL://添加设备
  8. RefreshCom();//刷新组合框的内容
  9. break;
  10. default:
  11. break;
  12. }
  13. return TRUE;
  14. }

RefreshCom函数如下:

  1. void Ctbox_debug_viewDlg::RefreshCom(void)
  2. {
  3. int count =m_CombolPort.GetCount();
  4. for(int i=0;i<count;i++)
  5. {
  6. m_CombolPort.DeleteString(count -1 -i);
  7. }
  8. AddCom();
  9. m_CombolPort.SetCurSel(0);
  10. }

第四步:在.cpp文件中包含头文件

  1. #include <Dbt.h>

这是因为DEV_BROADCAST_DEVICEINTERFACE,DBT_DEVICEREMOVECOMPLETE,DBT_DEVICEARRIVAL这几个东东在头文件Dbt.h中定义的,这样才能编译通过。

而AddCom函数已经在之前讲到过,回过头去看看。

这里的思想是通过检测到设备的插入和拔出时刷新组合框的内容,是通过重新测试串口的方式来实现的。

另:需要注意的是,当插入和拔出设备时,系统会检测到两次"设备改变事件",因此会两次调用OnDeviceChange函数,第一次调用时传入的函数nEventType的值固定为0x07,第二次调用时nEventType才是上述代码switch中所定义的事件,这与网上所说的需要注册是相悖的,不知道为什么网上有些文章会说一定需要注册什么的才能检测到设备改变的事件,反正我这里不需要,我用的是VS2010.

完!

见:http://blog.csdn.net/flydream0/article/details/8086976

【转】如何在VC下检测当前存在的串口及串口热拔插的更多相关文章

  1. 如何在linux下检测内存泄漏

    之前的文章应用 Valgrind 发现 Linux 程序的内存问题中介绍了利用Linux系统工具valgrind检测内存泄露的简单用法,本文实现了一个检测内存泄露的工具,包括了原理说明以及实现细节. ...

  2. 如何在linux下检测内存泄漏(转)

    本文转自:http://www.ibm.com/developerworks/cn/linux/l-mleak/ 本文针对 linux 下的 C++ 程序的内存泄漏的检测方法及其实现进行探讨.其中包括 ...

  3. 如何在linux下检测(自身)IP冲突

    最近遇到一个需求,或者说是一个用户现场问题. 我们设备先安装,设置dhcp模式获取ip进行联网,后来又安装了其他设备,但该设备是手动设置的静态ip地址,正好与我们设备冲突,造成网络故障. 那我们就需要 ...

  4. 如何在WINDOWS下编译BOOST C++库 .

    如何在WINDOWS下编译BOOST C++库 cheungmine 2008-6-25   写出来,怕自己以后忘记了,也为初学者参考.使用VC8.0和boost1.35.0.   1)下载boost ...

  5. 教你如何在Drcom下使用路由器上校园网(以广东工业大学、极路由1S HC5661A为例)

    免责声明: 在根据本教程进行实际操作时,如因您操作失误导致出现的一切意外,包括但不限于路由器变砖.故障.数据丢失等情况,概不负责: 该技术仅供学习交流,请勿将此技术应用于任何商业行为,所产生的法律责任 ...

  6. 如何在Linux下使用Rsync

    如何在Linux下使用Rsync 吐槽 昨天对scp进行总结之后看到最后有说到Rsync,俗语有云:好奇心害死猫.抱着学习的态度将Rsync给找了出来,然后进行了一些简单的学习.下面介绍一些个常用的命 ...

  7. Chrome出了个小bug:论如何在Chrome下劫持原生只读对象

    Chrome出了个小bug:论如何在Chrome下劫持原生只读对象 概述 众所周知,虽然JavaScript是个很灵活的语言,浏览器里很多原生的方法都可以随意覆盖或者重写,比如alert.但是为了保证 ...

  8. 在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。

    在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除. 作者:邵盛松 2009-09-05 前言 1关于的BLOB(Binary)数据的存储和读取功能主要参考了MSDN上的一篇& ...

  9. 如何在Chrome下Debug Mocha的测试

    简介 经过前两篇文章的介绍,相信读者对Mocha应该有一定的认知了,本文重点讲述如何在Chrome下Debug Mocha Test, 方便你在测试fail的时候troubleshooting. 关键 ...

随机推荐

  1. Node.js 内置模块crypto加密模块(3) HMAC

    HMAC:哈希消息认证码 ( Hash-based Message Authentication Code ) HMAC是密钥相关的哈希算法 使用 HMAC 进行加密的Node实现的一种方法: &qu ...

  2. 多媒体文件嵌入HTML中自动转码工具

    神器网址:https://iframely.com/embed 首先上传视频文件到服务器,视频管理网址平台 比如:   https://wistia.com/ 然后进入到 iframely 网址.复制 ...

  3. JS实现简单时钟效果

    老师上课需要我们做一个时钟的小作业 ,我把它放在上面记录一下啦 表盘和时针我都是用的背景图的形式,然后绝对定位,通过调整left和top确定时针.分针.秒针的位置,transform-origin设置 ...

  4. java CDI

    Scope声明周期 http://www.cnblogs.com/yjmyzz/p/javaee-cdi-bean-scope.html

  5. JDK自带反编译工具javap

    在JDK的bin文件夹下,有许多自带工具: javap就是其中的一个,对应为 javap.exe javap可反编译查看Java编译器编译生成的字节码文件, 语法: javap [ options ] ...

  6. 测试REST Web服务

    EST Web服务的测试计划 线程组 HTTP请求 与任何Jmeter测试一样,我们首先需要创建一个线程组以及一个HTTP请求采样器. 如果您现在运行测试,则可能会收到错误,响应代码为415,响应消息 ...

  7. 应用的入口——Startup

    应用的入口——Startup 一个ASP.NET Core应用被启动之后就具有了针对请求的处理能力,而这个能力是由管道赋予的,所以应用的启动同时意味着管道的成功构建.由于管道是由注册的服务器和若干中间 ...

  8. linux网卡软中断shell脚本

    LANG=C;export LANG;  service irqbalance stop >/dev/null 2>&1;chkconfig irqbalance off; bon ...

  9. 查询获取所有数据库名及数据库中表的集合、数据库连接字符串(类生成器,暂时支持mysql,sql server,后期有oracle再更新)

    现所在公司做项目开发时,经常会自己创建model类,网上的生成器也很多,完全满足自己的不太现实,所以感觉自己做一个更有底气,主要针对过程中的一些语句进行整理,也供其他人学习参考. 连接字符串: mys ...

  10. GitHub上优秀Android 开源项目

    GitHub在中国的火爆程度无需多言,越来越多的开源项目迁移到GitHub平台上.更何况,基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要.利用这些项目,有时能够让你 ...