【VC++开源代码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了VC++开源代码-串口调试助手源程序及编程详细过程 - 技术总结的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
串口调试助手源程序及编程详细过程1.建立项目2.在项目中插入 MSComm 控件3.利用 ClassWizard 定义 CMSComm 类控制变量4.在对话框中添加控件5.添加串口事件消息处理函数 OnComm6.打开和设置串口参数7.发送数据8.发送十六进制字符9.在接收框中以十六进制显示10.如何设置自动发送11.什么是 VARIANT 数据类型?如何使用 VARIANT 数据类型? 在众多网友的支持下,串口调试助手从 2001 年 5 月 21 日发布至今,短短一个月,在全国各地累计下载量近 5000 人次,在近 200 多个电子邮件中,20 多人提供了使用测试意见,更有 50 多位朋友提出要串口调试助手的源
代码,为了答谢谢朋友们的支持, 并写出详细的编程过程,公开推出我最初用
VC 控件 MSComm 编写串口通信程序的源
代码,姑且叫串口调试助手源程序 V1.0 或
VC 串口通讯源程序吧,我相信,如果你用
VC 编程,那么有了这个
代码,就可以轻而易举地完成串口编程任务了。
(也许本文过于详细,高手就不用看)开始吧:1.建立项目:打开
VC++6.0,建立一个基于对话框的 MFC 应用程序 SCommTest(与我源
代码一致,等会你会方便一点);2.在项目中插入 MSComm 控件 选择 Project 菜单下 Add To Project 子菜单中的Components and Controls…选项,在弹出的对话框中双击 Registered ActiveX Controls项(稍等一会,这个过程较慢),则所有注册过的 ActiveX 控件出现在列表框中。
选择 Microsoft Communications Control version 6.0,,单击 Insert 按钮将它插入到我们的 Project 中来,接受缺省的选项。
(如果你在控件列表中看不到 MicrosoftCommunications Control version 6.0,那可能是你在安装
VC6 时没有把 ActiveX 一项选上,重新安装
VC6,选上 ActiveX 就可以了),这时在 ClassView 视窗中就可以看到 CMSComm 类了,(注意:此类在 ClassWizard 中看不到,重构 clw 文件也一样),并且在控件工具栏 Controls 中出现了电话图标(如图 1所示),现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用 ClassWizard 定义 CMSComm 类控制对象 打开 ClassWizard-gtMemberViariables 选项卡, 为 m_ctrlComm, 选择 CSCommTestDlg 类, IDC_MSCOMM1 添加控制变量:这时你可以看一看,在对话框头文件中自动加入了//AFX_INCLUDES includequotmscomm.hquot //AFX_INCLUDES (这时运行程序,如果有错,那就再从头开始)。
4.在对话框中添加控件 向主对话框中添加两个编辑框,一个用于接收显示数据 ID 为IDC_EDIT_RXDATA,另一个用于输入发送数据,ID 为 IDC_EDIT_TXDATA,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其 ID 设为IDC_BUTTON_MANUALSEND。
别忘记了将接收编辑框的 Properties-gtStyles 中把Miltiline 和 Vertical Scroll 属性选上,发送编辑框若你想输入多行文字,也可选上Miltiline。
再打开 ClassWizard-gtMember Viariables 选项卡,选择 CSCommTestDlg 类, 为IDC_EDIT_RXDATA 添加 CString 变量 m_strRXData, 为 IDC_EDIT_TXDATA 添加 CString变量 m_strTXData。
说明: m_strRXData 和 m_strTXData 分别用来放入接收和发送的字符数据。
5.添加串口事件消息处理函数 OnComm 打开 ClassWizard-gtMessage Maps,选择类 CSCommTestDlg,选择 IDC_MSCOMM1,双击消息 OnComm,将弹出的对话框中将函数名改为 OnComm,(好记而已)OK。
这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在 OnComm函数加入相应的处理
代码就能实现自已想要的功能了。
请你在函数中加入如下
代码:void CSCommTestDlg::OnComm // TODO: Add your control notification handler code here VARIANT variant_inp COleSafeArray safearray_inp LONG lenk BYTE rxdata2048 //设置 BYTE 数组 An 8-bit integerthat is not signed. CString strtemp ifm_ctrlComm.GetCommEvent2 //事件值为 2 表示接收缓冲区内有字符 ////////以下你可以根据自己的通信协议加入处理
代码 variant_inpm_ctrlComm.GetInput //读缓冲区 safearray_inpvariant_inp //VARIANT 型变量转换为 ColeSafeArray 型变量 lensafearray_inp.GetOneDimSize //得到有效数据长度 fork0kltlenk safearray_inp.GetElementampkrxdatak//转换为 BYTE 型数组 fork0kltlenk //将数组转换为 Cstring 型变量 BYTE btcharrxdatak //字符型 strtemp.Formatquotcquotbt //将字符送入临时变量 strtemp 存放 m_strRXDatastrtemp //加入接收编辑框对应字符串 UpdateDataFALSE //更新编辑框内容到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行程序不应该有任何错误,不然,你肯定哪儿没看仔细,因为我是打开
VC6 对照着做一步写一行的,运行试试。
没错吧?那么做下一步:6.打开串口和设置串口参数 你可以在你需要的时候打开串口,例如在程序中做一个开始按钮,在该按钮的处理函数中打开串口。
现在我们在主对话框的CSCommTestDlg::OnInitDialog打开串口,加入如下
代码:// TODO: Add extra initialization hereifm_ctrlComm.GetPortOpenm_ctrlComm.SetPortOpenFALSEm_ctrlComm.SetCommPort1 //选择 com1if m_ctrlComm.GetPortOpenm_ctrlComm.SetPortOpenTRUE//打开串口elseAfxMessageBoxquotcannot open serial portquotm_ctrlComm.SetSettingsquot9600n81quot //波特率 9600,无校验,8 个数据位,1 个停止位m_ctrlComm.SetInputModel1 //1:表示以二进制方式检取数据m_ctrlComm.SetRThreshold1//参数 1 表示每当串口接收缓冲区中有多于或等于 1 个字符时将引发一个接收数据的OnComm 事件m_ctrlComm.SetInputLen0 //设置当前接收区数据长度为 0m_ctrlComm.GetInput//先预读缓冲区以清除残留数据现在你可以试试程序了,将串口线接好后(不会接?去看看我写的串口接线基本方法),打开串口调试助手,并将串口设在 com2,选上自动发送,也可以等会手动发送。
再执行你编写的程序,接收框里应该有数据显示了。
7.发送数据 先为发送按钮添加一个单击消息即 BN_CLICKED 处理函数,打开ClassWizard-gtMessage Maps,选择类 CSCommTestDlg,选择 IDC_BUTTON_MANUALSEND,双击 BN_CLICKED 添加 OnButtonManualsend函数,并在函数中添加如下
代码:void CSCommTestDlg::OnButtonManualsend// TODO: Add your control notification handler code hereUpdateDataTRUE //读取编辑框内容m_ctrlComm.SetOutputCOleVariantm_strTXData//发送数据运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一端的串口调试助手(或别的调试工具)接收框里出现了什么。
如果你真是初次涉猎串口编程,又一次成功,那该说声谢谢我了,因为我第一次做串口程序时可费劲了,那时网上的资料也不好找。
开开玩笑,谢谢你的支持,有什么好东西别忘了给我寄一份。
最后说明一下,由于用到
VC 控件,在没有安装
VC 的计算机上运行时要从
VC 中把mscomm32.ocx、msvcrt.dll、mfc42.dll 拷到 Windows 目录下的 System 子目录中(win2000为 System32)这是更新后适合本文的源程序(2001.8.25 制作),如果还没有下载源程序,又对本文有兴趣,请 立即下载 (当然,你看完本文也可以自己做出来,这个程序是接着上一个做的,如果你没下载前面程序,则没必要再下载了,本程序全部包含)。
8.发送十六进制字符 在主对话框中加入一个复选接钮,ID 为 IDC_CHECK_HEXSEND Caption: 十六进制发送,再利用 ClassWizard 为其添加控制变量:m_ctrlHexSend; 在 ClassView 中为 SCommTestDlg 类添加以下两个 PUBLIC 成员函数,并输入相应
代码//由于这个转换函数的格式限制,在发送框中的十六制字符应该每两个字符之间插入一个空隔//如:A1 23 45 0B 00 29//CByteArray 是一个动态字节数组,可参看 MSDN 帮助int CSCommTestDlg::String2HexCString str CByteArray ampsenddataint hexdatalowhexdataint hexdatalen0int lenstr.GetLengthsenddata.SetSizelen/2forint i0iltlenchar lstrhstrstriifhstr icontinueiifigtlenbreaklstrstrihexdataConvertHexCharhstrlowhexdataConvertHexCharlstrifhexdata16lowhexdata16breakelsehexdatahexdata16lowhexdataisenddatahexdatalencharhexdatahexdatalensenddata.SetSizehexdatalenreturn hexdatalen//这是一个将字符转换为相应的十六进制值的函数//好多 C 语言书上都可以找到//功能:若是在 0-F 之间的字符,则转换为相应的十六进制字符,否则返回-1char CSCommTestDlg::ConvertHexCharchar chifchgt0ampampchlt9return ch-0x30else ifchgtAampampchltFreturn ch-A10else ifchgtaampampchltfreturn ch-a10else return -1 再将 CSCommTestDlg::OnButtonManualsend修改成以下形式:void CSCommTestDlg::OnButtonManualsend// TODO: Add your control notification handler code hereUpdateDataTRUE //读取编辑框内容ifm_ctrlHexSend.GetCheckCByteArray hexdataint lenString2Hexm_strTXDatahexdata //此处返回的 len 可以用于计算发送了多少个十六进制数m_ctrlComm.SetOutputCOleVarianthexdata //发送十六进制数据elsem_ctrlComm.SetOutputCOleVariantm_strTXData//发送 ASCII 字符数据现在,你先将串口线接好并打开串口调试助手 V2.1,选上以十六制显示,设置好相应串口,然后运行我们这个程序,在发送框中输入 00 01 02 03 A1 CC 等十六进制字符,并选上以十六进制发送,单击手动发送,在串口调试助手的接收框中应该可以看到 00 01 0203 A1 CC 了。
9.在接收框中以十六进制显示 这就容易多了: 在主对话框中加入一个复选接钮,IDC_CHECK_HEXDISPLAY Caption:十六进制显示,再利用 ClassWizard 为其添加控制变量:m_ctrlHexDiaplay。
然后修改 CSCommTestDlg::OnComm函数:void CSCommTestDlg::OnComm// TODO: Add your control notification handler code hereVARIANT variant_inpCOleSafeArray safearray_inpLONG lenkBYTE rxdata2048 //设置 BYTE 数组 An 8-bit integerthat is not signed.CString strtempifm_ctrlComm.GetCommEvent2 //事件值为 2 表示接收缓冲区内有字符variant_inpm_ctrlComm.GetInput //读缓冲区safearray_inpvariant_inp //VARIANT 型变量转换为 ColeSafeArray 型变量lensafearray_inp.GetOneDimSize //得到有效数据长度fork0kltlenksafearray_inp.GetElementampkrxdatak//转换为 BYTE 型数组fork0kltlenk //将数组转换为 Cstring 型变量BYTE btcharrxdatak //字符型ifm_ctrlHexDisplay.GetCheckstrtemp.Formatquot02X quotbt //将字符以十六进制方式送入临时变量 strtemp 存放,注意这里加入一个空隔elsestrtemp.Formatquotcquotbt //将字符送入临时变量 strtemp 存放m_strRXDatastrtemp //加入接收编辑框对应字符串UpdateDataFALSE //更新编辑框内容测试:在串口调试助手发送框中输入 00 01 02 03 A1 CC 等十六进制字符,并选上以十六进制发送,单击手动发送,在本程序运行后选上以十六进制显示,在串口调试助手中单击手动发送或自动发送,则在本程序的接收框中应该可以看到 00 01 02 03 A1 CC 了。
10.如何设置自动发送 最简单的设定自动发送周期是用 SetTimer函数,这在数据采集中很有用,在控制中指令的传送也可能用到定时发送。
方法是:在 ClassWizard 中选上 MessageMap 卡,然后在 Objects IDs 选中CSCommTestDlg 类,再在 Messages 框中选上 WM_TIMER 消息,单击 ADD_FUNCTION 加入void CSCommTestDlg::OnTimerUINT nIDEvent 函数,这个函数是放入“时间到”后要处理的
代码:void CSCommTestDlg::OnTimerUINT nIDEvent// TODO: Add your message handler code here and/or call defaultOnButtonManualsend;CDialog::OnTimernIDEvent再在在主对话框中加入一个复选接钮,ID 为 IDC_CHECK_AUTOSEND Caption: 自动发送(周期 1 秒),再利用 ClassWizard 为其添加 BN_CLICK 消息处理函数 voidCSCommTestDlg::OnCheckAutosend:void CSCommTestDlg::OnCheckAutosend// TODO: Add your control notification handler code herem_bAutoSendm_bAutoSendifm_bAutoSendSetTimer11000NULL//时间为 1000 毫秒elseKillTimer1 //取消定时其中:m_bAutoSend 为 BOOL 型变量,在 CLASSVIEW 中为 CSCommTestDlg 类加入,并在构造函数中初始化: m_bAutoSenFALSE现在可以运行程序测试了。
11.什么是 VARIANT 数据类型?如何使用 VARIANT 数据类型? 不知如何使用 VARIANT 数据类型, 有不少朋友对 VARIANT 这个新的数据类型大感头疼。
SetOutput函数中 需要的 VARIANT 参数还可以使用 COleVariant 类的构造函数简单生成,现在 GetInput函数的返回值也成了 VARIANT 类型,那么如何从返回的值中提取有用的内容。
VARIANT 及由之而派生出的 COleVariant 类主要用于在 OLE 自动化中传递数据。
实际上 VARIANT 也只不过是一个新定义的结构罢了,它的主要成员包括一个联合体及一个变量。
该联合体由各种类型的数据成员构成, 而该变量则用来指明联合体中目前起作用的数据类型。
我们所关心的接收到的数据就存储在该联合体的某个数据成员中。
该联合体中包含的数据类型很多,从一些简单的变量到非常复杂的数组和指针。
由于通过串口接收到的内容常常是一个字节串,我们将使用其中的某个数组或指针来访问接收到的数据。
这里推荐给大家的是指向一个 SAFEARRAY(COleSafeArray)类型变量。
新的数据类型 SAFEARRAY 正如其名字一样,是一个“安全数组”,它能根据系统环境自动调整其 16 位或 32 位的定义,并且不会被 OLE 改变(某些类型如 BSTR 在 16位或 32 位应用程序间传递时会被 OLE 翻译从而破坏其中的二进制数据)。
大家无须了解 SAFEARRAY 的具体定义,只要知道它是另外一个结构,其中包含一个 void 类型的指针 pvData,其指向的内存就是存放有用数据的地方。
简而言之,从 GetInput函数返回的 VARIANT 类型变量中,找出 parray 指针,再从该指针指向的 SAFEARRAY 变量中找出 pvData 指针,就可以向访问数组一样取得所接收到的数据了。
具体应用请参见void CSCommTestDlg::OnComm函数。
大概我现在也说不清这个问题,我自己从第一次接触这个东西,到现在还是给别人讲不清。
MSComm 控件使用详解 目 次MSComm 控件两种处理通讯的方式CommPort 属性RThreshold 属性CTSHolding 属性SThreshold 属性CDHolding 属性DSRHolding 属性Settings 属性InputLen 属性EOFEnable 属性Handshake 常数OnComm 常数InputMode 常数错误消息 MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。
MSComm 控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的 API 函数,而且在
VC、VB、Delphi 等语言中均可使用。
Microsoft Communications Control(以 是下简称 MSComm) Microsoft 公司提供的简化 Windows 下串行通信编程的 ActiveX 控件,它为应用程序提供了通过串行接口收发数据的简便方法。
具体的来说,它提供了两种处理通信问题的方法:一是事件驱动Event-driven方法,一是查询法。
1.MSComm 控件两种处理通讯的方式MSComm 控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。
1.1 事件驱动方式事件驱动通讯是处理串行端口交互作用的一种非常有效的方法。
在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect CD或 Request To Send RTS 线上一个字符到达或一个变化发生时。
在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件。
OnComm 事件还可以检查和处理通讯错误。
所有通讯事件和通讯错误的列表,参阅 CommEvent 属性。
在编程过程中,就可以在 OnComm 事件处理函数中加入自己的处理
代码。
这种方法的优点是程序响应及时,可靠性高。
每个 MSComm 控件对应着一个串行端口。
如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件。
1.2 查询方式查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷。
在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误。
如果应用程序较小,并且是自保持的,这种方法可能是更可取的。
例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“确定”响应。
2.MSComm 控件的常用属性MSComm 控件有很多重要的属性,但首先必须熟悉几个属性。
CommPort 设置并返回通讯端口号。
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen 设置并返回通讯端口的状态。
也可以打开和关闭端口。
Input 从接收缓冲区返回和删除字符。
Output 向传输缓冲区写一个字符串。
下面分别描述:CommPort 属性 设置并返回通讯端口号。
语法 object.CommPortvalue value 一整型值,说明端口号。
说明 在设计时,value 可以设置成从 1 到 16 的任何数(缺省值为 1)。
但是如果用 。
PortOpen 属性打开一个并不存在的端口时,MSComm 控件会产生错误 68(设备无效)注意:必须在打开端口之前设置 CommPort 属性。
RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生OnComm 之前,设置并返回的要接收的字符数。
语法 object.Rthreshold value (value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数。
)说明 当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件。
例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生OnComm 事件。
CTSHolding 属性:确定是否可通过查询 Clear To Send CTS 线的状态发送数据。
ClearTo Send 是调制解调器发送到相联计算机的信号,指示传输可以进行。
该属性在设计时无效,在运行时为只读。
语法: object.CTSHolding(Boolean)Mscomm 控件的 CTSHolding 属性设置值:True Clear To Send 线为高电平。
False Clear To Send 线为低电平。
说明:如果 Clear To Send 线为低电平 CTSHolding False 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO Clear To Send Timeout 并产生 OnComm事件。
Clear To Send 线用于 RTS/CTS Request To Send/Clear To Send 硬件握手。
如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法。
详细信息 有关握手协议,请参阅 Handshaking 属性。
SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm事件之前,设置并返回传输缓冲区中允许的最小字符数。
语法 object.SThreshold value value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数。
说明:若设置 Sthreshold 属性为 0(缺省值),数据传输事件不会产生 OnComm 事件。
若设置 Sthreshold 属性为 1,当传输缓冲区完全空时,MSComm 控件产生 OnComm 事件。
如果在传输缓冲区中的字符数小于 value,CommEvent 属性设置为 comEvSend,并产生 OnComm 事件。
comEvSend 事件仅当字符数与 Sthreshold 交叉时被激活一次。
例如,如果 Sthreshold 等于 5,仅当在输出队列中字符数从 5 降到 4 时,comEvSend 才发生。
如果在输出队列中从没有比 Sthreshold 多的字符,comEvSend 事件将绝不会发生。
Handshake 常数常数 值 描述comNone 0 无握手。
comXonXoff 1 XOn/Xoff 握手。
comRTS 2 Request-to-send/clear-to-send 握手。
comRTSXOnXOff 3 Request-to-send 和 clear-to-send 握手皆可。
OnComm 常数常数 值 描述comE.