vc串口编程与曲线绘制 长时间运行内存减少

15:24 提问
急!VC编写的串口程序,但数据老是接收不全,请大家看看问题出在哪里,在此先谢谢!!
下面是处理串口接收数据的函数,我是用一个进程函数来实现的,串口采用的是同步方式,问题出在下面这一段函数,老是没接收完就退出了:
下面为处理接收数据的进程函数
按赞数排序
我在调试的时候,字符串str3都可以正常接收,但一自动运行,str3里面的数据就会只有一小段。
先不对收到的内容进行处理,将收到的内容一个个打印出来看下。
此问题已解决,软件没有问题,是硬件连线的问题,望以后有此问题的同学多多注意硬件是否完好!!
其他相似问题实验一:VC串口通信实验
一、实验目的
通过实验让学生了解串口通信的工作原理。
二、实验器材
计算机两台
串口连接线一根GND(pin5)&
TXD(pin3)&&RXD(pin2)
RXD(pin2)&&TXD(pin3)
RTS(pin7)&&CTS(pin8)
CTS(pin8)&&RTS(pin7)
DSR(pin6)&&DTR(pin4)
DTR(pin4)&&DSR(pin6)
三、实验要求
用VC++对计算机的串口进行编程,并作一个简单的串口查询通讯程序。用一条九针的DB-9串口通讯线将计算机的com1口和com2口相连,com1作为接受口,com2作为发送口。
四、实验步骤
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中来,接受缺省的选项。(如果你在控件列表中看不到Microsoft Communications Control, version 6.0,那可能是你在安装VC6时没有把ActiveX一项选上,重新安装VC6,选上ActiveX就可以了),这时在ClassView视窗中就可以看到CMSComm类了,(注意:此类在ClassWizard中看不到,重构clw文件也一样),并且在控件工具栏Controls中出现了电话图标(如图1所示),现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用ClassWizard定义CMSComm类控制对象&
打开ClassWizard-&Member Viariables选项卡,选择CSCommTestDlg类,为IDC_MSCOMM1添加控制变量:m_ctrlComm,这时你可以看一看,在对话框头文件中自动加入了//{{AFX_INCLUDES()& #include "mscomm.h"& //}}AFX_INCLUDES (这时运行程序,如果有错,那就再从头开始)。
4.在对话框中添加控件&
向主对话框中添加两个编辑框,一个用于接收显示数据ID为IDC_EDIT_RXDATA,另一个用于输入发送数据,ID为IDC_EDIT_TXDATA,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其ID设为IDC_BUTTON_MANUALSEND。别忘记了将接收编辑框的Properties-&Styles中把Miltiline和Vertical Scroll属性选上,发送编辑框若你想输入多行文字,也可选上Miltiline。再打开ClassWizard-&Member Viariables选项卡,选择CSCommTestDlg类,为IDC_EDIT_RXDATA添加CString变量m_strRXData, 为IDC_EDIT_TXDATA添加CString变量m_strTXData。说明: m_strRXData和m_strTXData分别用来放入接收和发送的字符数据。
5.添加串口事件消息处理函数OnComm()
打开ClassWizard-&Message Maps,选择类CSCommTestDlg,选择IDC_MSCOMM1,双击消息OnComm,将弹出的对话框中将函数名改为OnComm 。 这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码:
void CSCommTestDlg::OnComm()
// TODO: Add your control notification handler code here&&& VARIANT variant_&&& COleSafeArray safearray_&&& LONG len,k;&&& BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.&&& CS&&& if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符&&& {&&&&&&&&&&&& ////////以下你可以根据自己的通信协议加入处理代码&&&&&&& variant_inp=m_ctrlComm.GetInput(); //读缓冲区&&&&&&& safearray_inp=variant_ //VARIANT型变量转换为ColeSafeArray型变量&&&&&&& len=safearray_inp.GetOneDimSize(); //得到有效数据长度&&&&&&& for(k=0;k&k++)&&&&&&&&&&& safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组&&&&&&& for(k=0;k&k++) //将数组转换为Cstring型变量&&&&&&& {&&&&&&&&&&& BYTE bt=*(char*)(rxdata+k); //字符型&&&&&&&&&&& strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放&&&&&&&&&&& m_strRXData+= //加入接收编辑框对应字符串&&&&&&&& }&&& }&&& UpdateData(FALSE); //更新编辑框内容}
6.打开串口和设置串口参数&
你可以在你需要的时候打开串口,例如在程序中做一个开始按钮,在该按钮的处理函数中打开串口。现在我们在主对话框的CSCommTestDlg::OnInitDialog()打开串口,加入如下代码:
// TODO: Add extra initialization here
if(m_ctrlComm.GetPortOpen())
m_ctrlComm.SetPortOpen(FALSE);
m_ctrlComm.SetCommPort(1); //选择com1
if( !m_ctrlComm.GetPortOpen())
m_ctrlComm.SetPortOpen(TRUE);//打开串口
AfxMessageBox("cannot open serial port");
m_ctrlComm.SetSettings("9600,n,8,1"); //波特率9600,无校验,8个数据位,1个停止位
m_ctrlComm.SetInputMode(1); //1:表示以二进制方式检取数据m_ctrlComm.SetRThreshold(1);&
//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为0
m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据
现在你可以试试程序了,将串口线接好后,打开,并将串口设在com2,选上自动发送,也可以等会手动发送。再执行你编写的程序,接收框里应该有数据显示了。
7.发送数据&
先为发送按钮添加一个单击消息即BN_CLICKED处理函数,打开ClassWizard-&Message Maps,选择类CSCommTestDlg,选择IDC_BUTTON_MANUALSEND,双击BN_CLICKED添加OnButtonManualsend()函数,并在函数中添加如下代码:
void CSCommTestDlg::OnButtonManualsend()&
// TODO: Add your control notification handler code here
&UpdateData(TRUE); //读取编辑框内容
m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送数据
最后说明一下,由于用到VC控件,在没有安装VC的计算机上运行时要从VC中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到Windows目录下的System子目录中(win2000为System32)并再进行注册设置,
8.发送十六进制字符
&&& 在主对话框中加入一个复选接钮,ID为IDC_CHECK_HEXSEND ,Caption: 十六进制发送,再利用ClassWizard为其添加控制变量:m_ctrlHexSend;
&&& 在ClassView中为SCommTestDlg类添加以下两个PUBLIC成员函数,并输入相应代码;
//由于这个转换函数的格式限制,在发送框中的十六制字符应该每两个字符之间插入一个空隔//如:A1 23 45 0B 00 29//CByteArray是一个动态字节数组,可参看MSDN帮助int CSCommTestDlg::String2Hex(CString str, CByteArray &senddata){int hexdata,int hexdatalen=0;int len=str.GetLength();senddata.SetSize(len/2);for(int i=0;i&){char lstr,hstr=str[i];if(hstr==' '){i++;}i++;if(i&=len)lstr=str[i];hexdata=ConvertHexChar(hstr);lowhexdata=ConvertHexChar(lstr);if((hexdata==16)||(lowhexdata==16))else&hexdata=hexdata*16+i++;senddata[hexdatalen]=(char)hexdatalen++;}senddata.SetSize(hexdatalen);}//这是一个将字符转换为相应的十六进制值的函数//好多C语言书上都可以找到//功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1char CSCommTestDlg::ConvertHexChar(char ch)&{if((ch&='0')&&(ch&='9'))return ch-0x30;else if((ch&='A')&&(ch&='F'))return ch-'A'+10;else if((ch&='a')&&(ch&='f'))return ch-'a'+10;else return (-1);}
& 再将CSCommTestDlg::OnButtonManualsend()修改成以下形式:
void CSCommTestDlg::OnButtonManualsend()&{// TODO: Add your control notification handler code hereUpdateData(TRUE); //读取编辑框内容if(m_ctrlHexSend.GetCheck()){CByteAint len=String2Hex(m_strTXData,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数m_ctrlComm.SetOutput(COleVariant(hexdata)); //发送十六进制数据}else&m_ctrlComm.SetOutput(COleVariant(m_strTXData));//发送ASCII字符数据}
现在,你先将串口线接好并打开串口调试助手V2.1,选上以十六制显示,设置好相应串口,然后运行我们这个程序,在发送框中输入00 01 02 03 A1 CC等十六进制字符,并选上以十六进制发送,单击手动发送,在串口调试助手的接收框中应该可以看到00 01 02 03 A1 CC了。
9.在接收框中以十六进制显示
&&& 在主对话框中加入一个复选接钮,IDC_CHECK_HEXDISPLAY, Caption: 十六进制显示,再利用ClassWizard为其添加控制变量:m_ctrlHexDisplay。 然后修改CSCommTestDlg::OnComm()函数:
void CSCommTestDlg::OnComm()&{// TODO: Add your control notification handler code hereVARIANT variant_COleSafeArray safearray_LONG len,k;BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.CSif(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符{variant_inp=m_ctrlComm.GetInput(); //读缓冲区safearray_inp=variant_ //VARIANT型变量转换为ColeSafeArray型变量len=safearray_inp.GetOneDimSize(); //得到有效数据长度for(k=0;k&k++)safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组for(k=0;k&k++) //将数组转换为Cstring型变量{BYTE bt=*(char*)(rxdata+k); //字符型if(m_ctrlHexDisplay.GetCheck())strtemp.Format("%02X ",bt); //将字符以十六进制方式送入临时变量strtemp存放,注意这里加入一个空隔else&strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放m_strRXData+= //加入接收编辑框对应字符串&}}UpdateData(FALSE); //更新编辑框内容}
测试:在串口调试助手发送框中输入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::OnTimer(UINT nIDEvent) 函数,这个函数是放入&时间到&后要处理的代码:
void CSCommTestDlg::OnTimer(UINT nIDEvent)&{// TODO: Add your message handler code here and/or call defaultOnButtonManualsend();CDialog::OnTimer(nIDEvent);}
再在在主对话框中加入一个复选接钮,ID为IDC_CHECK_AUTOSEND Caption: 自动发送(周期1秒),再利用ClassWizard为其添加BN_CLICK消息处理函数void CSCommTestDlg::OnCheckAutosend():
void CSCommTestDlg::OnCheckAutosend()&{// TODO: Add your control notification handler code herem_bAutoSend=!m_bAutoSif(m_bAutoSend){SetTimer(1,1000,NULL);//时间为1000毫秒}else{KillTimer(1);& //取消定时}}
其中:m_bAutoSend为BOOL型变量,在CLASSVIEW中为CSCommTestDlg类加入,并在构造函数中初始化:
&&&&& m_bAutoSen=FALSE;现在可以运行程序测试了。
源程序如下:
#include &stdio.h&#include &dos.h&#include &conio.h&#include &io.h&#include &alloc.h&#include &ctype.h&#define Com1Base 0x3f8        //定义串口com1的基地址;#define Com2Base 0x2f8        //定义串口com2的基地址;void main(){&& int st,fp,jp,&& int d=0;&& outportb(Com2Base+3,0x80);    //允许访问com2的波特率因子寄存器,禁止串口中断,无校验,无停止位;&& outportb(Com2Base+0,0x0c);    //设置com2的波特率低八位;&& outportb(Com2Base+1,0x00);    //设置com2的波特率高八位;&& outportb(Com2Base+3,0x03);    //禁止访问com2口的波特率因子寄存器,禁止串口中断,无校验,无停止位,八位数据;&& outportb(Com2Base+4,0);      //初始化串口com2的MODEM寄存器;&& outportb(Com2Base+1,0);      //初始化com2的中断允许寄存器,屏蔽串口com2                  的中断;&& outportb(Com1Base+3,0x80);    //允许访问com1的波特率因子寄存器,禁止串口中断,无校验,无停止位;
&& outportb(Com1Base+0,0x0c);&&&&&&& //设置com1的波特率低八位;&& outportb(Com1Base+1,0x00);&&&&&&& //设置com2的波特率高八位;&& outportb(Com1Base+3,0x03);&&&&&&& 禁止访问com2口的波特率因子寄存器,禁止串口中断,无校验,无停止位,八位数据;
&& outportb(Com1Base+4,0);&&&&&&&&&&&& //初始化串口com2的MODEM寄存器;&& outportb(Com1Base+1,0);&&&&&&&&&&&& //初始化com2的中断允许寄存器,屏蔽串口com2                  的中断;
&& printf("please transfer a character to com2:\n");&& do{&&&& do{& st=inportb(Com2Base+5);& printf("%x\n",st);&&&&&& }while(st&0x20!=0x20);&&&&&&&&& //查询com2的线路状态寄存器(LSR)的第五位                   的状态是否为1,即发送保持寄存器是否为空?也就是com2口是否准备好发送数据;若否则循环等待;&&&& while(1)&&&& {&&&&&& printf("%x\n",d+1);&&&&&& outportb(Com2Base,++d);    //从com2口发送数据;&&&&&& do{&&& fp=inportb(Com2Base+5);}while((fp&0x20)!=0x20);   //查询等待com2的线路状态寄存器(LSR)的第五位的状态是否为1,即发送保持寄存器是否为空?若否则循环等待;&&&&&&           //com2的线路状态寄存器(LSR)的第五位的状态是否为1,即发送保持寄存器为空,跳出数据发送程序。&&&& }&&&& printf("display& the character while was just received from com1\n");&&&& do&&&&& {&&& jp=inportb(Com1Base+5);&}while((jp&0x01)!=1);  &&&&&   //查询等待com1的线路状态寄存器(LSR)的第五位的状态是否为1,即发送保持寄存器是否为空?若否则循环等待;
&&&& printf("%x\n",inportb(Com1Base+0));& //com1口读入数据,并在屏幕上显示出来; &&& do&&&& {& op=inportb(Com1Base+5);&&&&&& }while((op&0x01)!=0);    //查询等待com1的线路状态寄存器(LSR)的第五位的状态是否为1,即发送保持寄存器是否为空?若否则循环等待;
&&&&& delay(10000);&&&&&&&&&&&&&&&&&&&&&&& //延时;& }while(!kbhit());             //敲任意键退出程序;}
阅读(...) 评论()当前位置: →
→ vc串口编程实例
vc串口编程实例
& 作者及来源: 顶顶顶顶 - 博客园 &
&收藏到→_→:
摘要: vc 串口编程实例
"vc串口编程实例"::
今天总结一下使用vc++操作串口的程序,使用vc++编写的串口程序,大致分为一下几种
&&&&&&1.使用win32 api函数编写串口程序;
&&&&&&2.使用vc++自带的控件mscomm控件;
&&&&& 3.网上有许多程序爱好者自己编写了串口通信类,我们可以下下来使用;
&&&&&&首先,介绍一下使用api编写串口通信,这个我用的最多了,因为程序本身代码很少,易读,给大家推荐一个网站/programming/vc/89.htm, 这个网站详细的介绍了程序中的几个比较重要的函数,win32 中用于打开串口的api 函数为 createfile(),readfile();函数用来接收数据,writefile();用来向串口中写数据,closehandle()用来关闭 文件,就是关闭串口。上面介绍了几个主要的函数,下面我用mfc写此文来自: 马开东博客
转载请注明出处 网址:
了一个简单的串口通信的例子,使用api函数,其中为了调试使用初始化串口为 &com2&,能够完成简单的接收和发送功能。部分代码如下:
& 好啦,主要代码就这么多,完成了,至于其中的变量自己看看就明白了啊。
完整的mfc工程代码,我已经上传到了新浪资源共享里了,免资源分的。
&&&&& 下一种串口通信的方法就是使用vc中的mscomm控件,具体的编程方法通过一篇 文章介绍的很详细了,我也上传到了新浪资源共享中,http://ishare..cn/c/1929.html,想共同学习的朋友可以下载下来看一下。
&&&&& 我了,今天就总结这么多,下一篇打算说说vc++在绘图方面的使用。 搜索此文相关文章:此文来自: 马开东博客
网址: 站长QQ
vc串口编程实例_博客园相关文章
博客园_总排行榜
博客园_最新
博客园_月排行榜
博客园_周排行榜
博客园_日排行榜

我要回帖

更多关于 vc 串口编程例子 的文章

 

随机推荐