串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口。串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是由于串口通信是异步的,串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。串口通信最重要的参数是[波特](http://baike.baidu.com/view/543280.htm)率、数据位、停止位和奇偶校验。
而在VC++中实现串口通信也是一名VC程序员必须要掌握的技能。下面结合实例详细介绍在VC++中实现串口通信的过程(完整的实例可在我的CSDN资源中下载:[http://download.csdn.net/detail/margin1988/6408513](http://download.csdn.net/detail/margin1988/6408513))。
在这个实例中,实现了系统中可用串口的自动检测(通过注册表信息)、打开、发送、接收、关闭等基本的操作,若将串口线的TX(发送)和RX(接收)引脚连起来,便采用了“一根线发送数据的同时用另一根线接收数据”的方式测试了发送和接收功能的可用性和正确性。该实例对于初学者学习和掌握基于VC的串口通信将会有非常大的帮助。
(1)实例中所要用的主要控件及其属性、事件设置情况:
<table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top"><p align="center">控件</p></td><td valign="top"><p align="center">ID</p></td><td valign="top"><p align="center">caption</p></td><td valign="top"><p align="center">绑定变量</p></td><td valign="top"><p align="center">绑定事件</p></td></tr><tr><td valign="top"><p align="center">组合框</p></td><td valign="top"><p align="center">IDC_COMBO1</p></td><td valign="top"><p align="center">-</p></td><td valign="top"><p align="center">CComboBox m_com;</p></td><td valign="top"><p align="center">-</p></td></tr><tr><td valign="top"><p align="center">按钮</p></td><td valign="top"><p align="center">IDC_BUTTON1</p></td><td valign="top"><p align="center">打开</p></td><td valign="top"><p align="center">CButton m_open;</p></td><td valign="top"><p align="center">OnBnClickedButton1()</p></td></tr><tr><td valign="top"><p align="center">按钮</p></td><td valign="top"><p align="center">IDC_BUTTON2</p></td><td valign="top"><p align="center">发送</p></td><td valign="top"><p align="center">CButton m_send;</p></td><td valign="top"><p align="center">OnBnClickedButton2()</p></td></tr><tr><td valign="top"><p align="center">按钮</p></td><td valign="top"><p align="center">IDC_BUTTON3</p></td><td valign="top"><p align="center">关闭</p></td><td valign="top"><p align="center">CButton m_close;</p></td><td valign="top"><p align="center">OnBnClickedButton3()</p></td></tr><tr><td valign="top"><p align="center">编辑框</p></td><td valign="top"><p align="center">IDC_EDIT1</p></td><td valign="top"><p align="center">发送输入</p></td><td valign="top"><p align="center">CString m_sendstr;</p></td><td valign="top"><p align="center">-</p></td></tr><tr><td valign="top"><p align="center">编辑框</p></td><td valign="top"><p align="center">IDC_EDIT2</p></td><td valign="top"><p align="center">接收显示</p></td><td valign="top"><p align="center">CString m_receivestr;</p></td><td valign="top"><p align="center">-</p></td></tr><tr><td valign="top"><p align="center">MSComm</p></td><td valign="top"><p align="center">IDC_MSCOMM1</p></td><td valign="top"><p align="center">-</p></td><td valign="top"><p align="center">CMSComm m_ctrlComm;</p></td><td valign="top"><p align="center">OnComm()</p></td></tr></tbody></table>
(2)需要的硬件条件及情况说明:
需要一根串口线,一端接在PC的某个串口上,另一端的TX引脚和RX引脚用铜线连接起来,这样便形成了一个回路,数据发送通过TX引脚出去后,又从RX引脚进来,程序中便可以得到接收到的数据了,接收到的数据应该和发送的数据一致,说明串口的发送、接收操作成功了。
(3)COM组件(MSComm控件)消息响应宏定义的**重要注意点**:
~~~
BEGIN_EVENTSINK_MAP (CPoint20Dlg, CDialog)
ON_EVENT (CPoint20Dlg, IDC_MSCOMM1, 1, OnComm, VTS_NONE)
END_EVENTSINK_MAP ()
~~~
(4)从注册表中检测系统中可用串口并添加到界面组合框中:
~~~
HKEY hKey;
int rtn;
rtn = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Hardware\\DeviceMap\\SerialComm", NULL, KEY_READ, &hKey);
if( rtn == ERROR_SUCCESS) // 打开串口注册表
{
int i=0;
char portName[256], commName[256];
DWORD dwLong,dwSize;
while (1)
{
dwSize = sizeof(portName);
dwLong = dwSize;
rtn = RegEnumValue ( hKey, i, portName, &dwLong, NULL, NULL, (PUCHAR)commName, &dwSize ); // 枚举串口
if( rtn == ERROR_NO_MORE_ITEMS )
break; // commName就是串口名字
m_com.AddString(commName);// 将可用串口添加到界面组合框
i++;
}
RegCloseKey(hKey);
}
m_com.SetCurSel(0);
~~~
(5)打开并设置串口参数:
~~~
if (!m_ctrlComm.GetPortOpen())
{
char commName[256];//串口名
m_com.GetWindowText (commName, 256);
m_ctrlComm.SetCommPort(_ttoi(&commName[3]));//从串口名中得到串口号
m_ctrlComm.SetInputMode (1);
m_ctrlComm.SetSettings ("9600, n, 8, 1");
m_ctrlComm.SetPortOpen (TRUE);
m_ctrlComm.SetRThreshold (1);
m_ctrlComm.SetInputLen (0);
m_ctrlComm.GetInput ();
MessageBox(" 串口已打开 ");
}
else
MessageBox("没有发现此串口或被占用");
~~~
(6)发送数据:
~~~
if (m_ctrlComm.GetPortOpen())
{
UpdateData();
CByteArray sendArr;//欲发送的数据,需从CString转化为CByteArray型
WORD wLen;
wLen=m_sendstr.GetLength();
sendArr.SetSize(wLen);
for (int i=0;i<wLen;i++){
sendArr.SetAt(i,m_sendstr.GetAt(i));
}
m_ctrlComm.SetOutput (COleVariant (sendArr));//发送数据
}
else
MessageBox("串口未打开");
~~~
(7)接收数据(onComm()函数):
~~~
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[6000];
CString strtemp;
if (m_ctrlComm.GetCommEvent()==2)
{
variant_inp=m_ctrlComm.GetInput ();
safearray_inp=variant_inp;
len=safearray_inp.GetOneDimSize();
for (k=0;k<len;k++)
{
safearray_inp.GetElement(&k,rxdata+k);
BYTE bt=*(char*)(rxdata+k);
//strtemp.Format(_T("%02X"),bt);//十六进制格式接收
strtemp.Format(_T("%c"),bt);//字符格式接收
m_receivestr+=strtemp;
}
UpdateData(FALSE);
}
~~~
(8)关闭串口:
~~~
if(m_ctrlComm.GetPortOpen())
{
m_ctrlComm.SetPortOpen (FALSE);
MessageBox("串口已关闭");
}
~~~
(9)实例效果图:
![](https://box.kancloud.cn/2016-08-31_57c6b4a826750.jpg)
- 前言
- VC++中自定义热键及响应
- CFileDialog文件对话框
- VC++中客户区保存为BMP图片
- VC++读、写注册表
- VC++播放音频文件和音频数据的方法
- VC++调用Matlab编写的DLL(混合编程)
- VC++中文件读、写和其他相关操作汇总
- VC++获取系统当前时间
- VC++按钮控件字体设置
- VC++软件界面风格简单美化
- VC++中一些常用的数据类型之间的相互转化
- VC++中截取字符串的方法
- VC++中vector矢量的使用方法及随机相关
- VC++中结构体的定义及使用
- VC++中List Control控件的使用方法介绍
- VC++中窗口过程函数及其消息发送、响应机制介绍
- VC++中Ribbon编程架构及SDI架构多视图切换介绍
- 串口通信基础知识及VC++实现
- VC++中单个键盘按键的响应
- VC++中的计时器及多媒体高精度计时器
- VC++编写DLL导出函数及其调用方法
- VC++对话框(CDialog)的全屏显示及控件居中显示
- VC++对话框(CDialog)添加背景图片
- VC++图片控件(Picture Control)显示资源位图(BMP)、文件位图(BMP)、其它格式文件图片(JPG\PNG\BMP)的方法
- VC++对Access数据库的操作(查询、插入、更新、删除等)