标签:
当我们在用VS进行串口编程时,在打开串口前,经常想知道当前PC上存在多少个串口,哪些串口可用?哪些串口已经打开了,最好是在一个Combo Box中列表系统当前所有可用的串口以供选择,然而如何获取系统当前可用的串口有哪些呢?
这里介绍的方法也是最简单也是最笨的一种方法,即一个一个去试,试完了就知道了。至于还有没有其它更好的方法,暂不在本文所讨论的范围之内。
一个在对话框的OnInitDialog函数内做如下操作:
1 初始化时检测串口
- BOOL Ctbox_debug_viewDlg::OnInitDialog()
- {
- CDialogEx::OnInitDialog();
-
-
-
-
- ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
- ASSERT(IDM_ABOUTBOX < 0xF000);
-
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- BOOL bNameValid;
- CString strAboutMenu;
- bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
- ASSERT(bNameValid);
- if (!strAboutMenu.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
- }
- }
-
-
-
- SetIcon(m_hIcon, TRUE);
- SetIcon(m_hIcon, FALSE);
-
-
-
- AddCom();
- m_CombolPort.SetCurSel(0);
-
- }
AddCom函数如下定义:
- void Ctbox_debug_viewDlg::AddCom(void)
- {
- EnumerateSerialPorts(ports,portse,portsu);
- unsigned short uicounter;
- unsigned short uisetcom;
- CString str;
-
-
- uicounter = portse.GetSize();
-
- if(uicounter > 0)
- {
-
- for(int i=0; i<uicounter; i++)
- {
- uisetcom = portse.ElementAt(i);
- str.Format(_T("COM%d "),uisetcom);
- m_CombolPort.AddString(str);
- }
- }
- }
EnumerateSerialPorts函数如下:
- void Ctbox_debug_viewDlg::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu)
- {
-
- ports.RemoveAll();
- portse.RemoveAll();
- portsu.RemoveAll();
-
-
-
-
- for (int i=1; i<256; i++)
- {
-
- CString sPort;
- sPort.Format(_T("\\\\.\\COM%d"), i);
-
-
- BOOL bSuccess = FALSE;
- HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- DWORD dwError = GetLastError();
-
- if (dwError == ERROR_ACCESS_DENIED)
- {
- bSuccess = TRUE;
- portsu.Add(i);
- }
- }
- else
- {
-
- bSuccess = TRUE;
- portse.Add(i);
-
- CloseHandle(hPort);
- }
-
-
- if (bSuccess)
- ports.Add(i);
- }
- }
如上操作即可将系统当前可用的所有串口添加到CombolPort所对应的Combol Box中了。
2 打开串口
代码如下:
- void Ctbox_debug_viewDlg::OnBnClickedBtOpen()
- {
-
-
- if(m_mscomm.get_PortOpen())
- {
- m_mscomm.put_PortOpen(FALSE);
- GetDlgItem(IDC_BT_OPEN)->SetWindowText(_T("打开"));
- ShowInfo(_T("关闭串口成功!"));
- m_OpenStatus =false;
- return;
- }
- UpdateData(TRUE);
- m_OpenStatus =true;
-
- int curPort =portse.ElementAt(m_CombolPort.GetCurSel());
- m_mscomm.put_CommPort(curPort);
- m_mscomm.put_InBufferSize(1024);
- m_mscomm.put_OutBufferSize(1024);
-
- m_mscomm.put_InputLen(0);
- m_mscomm.put_InputMode(1);
- m_mscomm.put_RThreshold(1);
-
-
-
-
- DWORD baudrate;
- switch(m_CombolBaudrate.GetCurSel())
- {
- case 0:
- baudrate =115200;
- break;
- case 1:
- baudrate =9600;
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- CString setting;
- setting.Format(_T("%d,n,8,1"),baudrate);
- m_mscomm.put_Settings(setting
-
- m_mscomm.put_PortOpen(TRUE);
- GetDlgItem(IDC_BT_OPEN)->SetWindowText(_T("关闭"));
- ShowInfo(_T("打开串口成功!"));
-
- }
3 串口热拔插时检测串口
这里主要利用Cwnd的ON_WM_DEVICECHANGE消息来处理。
ON_WM_DEVICECHANGE消息在VS2010中好像只能通过手动来添加,反正我没找到可以通过对话的形式来添加的,后续有知道的兄台麻烦告知我一下。
因此,首先得手动添加ON_WM_DEVICECHANGE消息:
第一步:在消息映射BEGIN_MESSAGE_MAP(Ctbox_debug_viewDlg, CDialogEx)中添加:
第二步:在头文件类的定义中添加函数声明:
- afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);
第三步:实现函数
- BOOL Ctbox_debug_viewDlg::OnDeviceChange(UINT nEventType,DWORD dwData)
- {
-
- switch (nEventType)
- {
- case DBT_DEVICEREMOVECOMPLETE:
- case DBT_DEVICEARRIVAL:
- RefreshCom();
- break;
-
- default:
- break;
- }
-
- return TRUE;
-
- }
RefreshCom函数如下:
- void Ctbox_debug_viewDlg::RefreshCom(void)
- {
- int count =m_CombolPort.GetCount();
-
- for(int i=0;i<count;i++)
- {
- m_CombolPort.DeleteString(count -1 -i);
- }
- AddCom();
- m_CombolPort.SetCurSel(0);
- }
第四步:在.cpp文件中包含头文件
这是因为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下检测当前存在的串口及串口热拔插
标签:
原文地址:http://www.cnblogs.com/zhanjxcom/p/4477976.html