串口通信系统
发布时间:2011-08-04 19:41:13
发布时间:2011-08-04 19:41:13
版权所有,参考请注明出处,请勿抄袭
联系方式:849110889@qq.com
中南民族大学
软件课程设计报告
电子信息工程 学院
2008 级
光信息科学与技术 专业
题目 串口通信系统
学生 XHL 学号 08074007
指导教师 SZY
2011年 05 月 11 日
串口通信系统
摘要:串口通信系统有着广泛的应用,涉及到远程通信,自动控制等行业。在Microsoft Windows下使用MSComm控件编制串口通信系统,实现基本的数据传输,文件传送等功能。用Microsoft Visual C++编程时可使用MFC把程序做成windows下的图形化界面程序,界面清晰直观,使用方便。
关键字:串口通信;MSComm;编程;Visual C++
引言
计算机串口编程在通信软件中有着十分广泛的应用,如电话、传真、视频控制、聊天软件等。涉及到远程通信、自动控制等行业。Visual C++功能强大且应用灵活,同时得到Microsoft系统的最好支持。所以熟悉计算机串口工作原理,掌握软件编程控制串口的方法,学会使用Visual C++进行软件编程,能设计简单的串口通信协议对今后的学习和工作都会有很大的帮助。
设计依据及框图
2.1 设计平台
本次课程设计软件用Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)微软公司的C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。VC++整合了便利的除错工具,特别是整合了微软视窗程式设计(Windows API)、三维动画DirectX API,Microsoft .NET框架。目前最新的版本是Microsoft Visual C++ 2010。Microsoft Visual C++以拥有“语法高亮”, IntelliSense(自动编译功能)以及高级除错功能而著称。比如,它允许用户进行远程调试,单步执行等。还有允许用户在调试期间重新编译被修改的代码,而不必重新启动正在调试的程序。其编译及建置系统以预编译头文件、最小重建功能及累加连结著称。这些特征明显缩短程式编辑、编译及连结的时间花费,在大型软件计划上尤其显著。
2.2 设计思想
本串口通信系统是通过虚拟串口软件将同一台电脑上两个串口通信对话框建立连接,按照自定义通信协议(SPCP)进行文本信息和二进制数据交换,通过虚拟串口实现聊天等功能。SPCP基于帧传输方式,即在向串口发送数据时是一帧一帧地发送。在Windows环境下,串口是系统资源的一部分。 应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。Windows2000以上的操作系统及Visual C++6.0语言环境下设计简单的串口通信系统,能进行简单的数据通信。通过合理布局图形化窗口,达到美观实用的效果。MSComm控件将通信的大部分底层操作都封装在控件内部,大大简化了编程工作。
2.3 设计框图、用户界面
串口连接
图1 串口通信系统设计框图
图2 用户界面
各模块功能及主要模块的流程图
3.1 各模块功能简介(程序代码见附录)
1) 输入用户名模块,单击确认。如图3.1和3.2
图 3.1 图 3.2 图 3.3 图 3.4 图 3.5
2) 串口模块,输入串口号,打开串口,打开后背景色改变,错误提醒。见图3.3、3.4、3.5
3) 改变颜色模块,通过滑块改变颜色,单击显示当前颜色,如图3.6、3.7。图3.8、3.9显示发送框和接收框颜色。
图 3.6 图 3.7
图 3.8 图 3.9
图 3.10 图 3.11
4) 保存聊天记录和查看聊天记录分别如图 3.10 和图3.11.
5) 接收框显示用户名和时间如图3.12
图 3.12 图3.13
图3.14 图3.15 图3.16
6) 背景功能模块,见用户界面。
7) 字体功能模块,见图3..13
8) 用Static按钮在对话框上添加文字用picture按钮添加图片,如图3.14和3.15
9) 接收框自动滚屏,显示最后一行,如图3.16
表1-对话框控件
3.2 主要流程图
软件调试分析
通过虚拟串口软件连接串口,打开串口可以调试。
调试过程中问题可以大致划分为如下几类:
1) 忘记定义变量,或滥用变量名。
2) 成员变量类型定义错误,成员定义错误。
3) 成员函数名称和命令ID及消息书写出现错误。
4) 对话框中各个控件属性设置出现错误。
5) 程序编写过程中换行之类的程序为编写。
经过仔细调试,逐个改正以上不完善的地方,程序最终通过编译,达到了实验要求,
如通过程序实现用户名和时间以及消息的合理排列,更加美观。在OnButtonManualsend()函数中添加滚屏函数代码后,对方接收框不滚屏,后来经过调试发现要在串口事件消息处理函数OnComm()中也要添加滚屏函数代码。
当然调试过程中也遇到一些问题任然没有完善,字体就是一个,经过多次调试,字体仍然无法达到满意效果,也是此次实验设计的一个遗憾。
软
结语
5.1 结论与讨论
课程设计的伊始,我就查阅了许多相关的书籍,在网上也了解了许多相关的知识,结合老师给的的资料,利用实验室的条件,完成了本次软件课程设计。
由于是第一次接触基于MSComm控件的串口调试程序,对C++知识的掌握也不是十分的完备,实验过程中也出现过许多问题,但是在舒振宇老师以及其他同学的帮助下顺利的解决了许多问题。这次软件课程设计既是对我过去所学知识的检验,也让我的知识得到了很大的提高。通过本次设计,我了解到Visual C++的更多功能。
串口通信在当前信息社会有着广泛的应用,通过本次设计我了解到串口通信的基本知识,为今后的学习和工作储备了一些必要的知识。
通过此次课程设计我更加深刻地认识到软件设计应该坚持模块化,这样既可以方便调试也可以是别人容易阅读理解,有利于软件的维护管理。
Microsoft Visual C++ 是一个不断更新的软件,目前最新的版本是Microsoft Visual C++ 2010,由于我的电脑系统已经不兼容Visual C++ 6.0,所以本次课程设计的部分功能我是在Visual C++ 2010中实现的,让我对Visual C++ 2010也有所了解。比如在Visual C++ 6.0定义#include
同时通过用Visio画流程图让我学会了Visio基本的用法,总之在这次课程设计的过程中收获颇多。
参考文献
[1]李现勇.Visual C++串口通信技术与工程实践[M].北京:人民邮电出版社,2003
[2]谭思亮,邹超群.Visual C++串口通信工程开发实例导航[M].北京:人民邮电出版社,2003
[2]百度空间.http://hi.baidu.com/_ynbg/blog/item/8eda41a07c6db68746106401.html
附录
主要程序列表(代码见电子文档 )
添加对话框背景程序
消息处理及滚屏程序
打开串口程序
发送数据及滚屏程序
用户名程序
保存聊天记录程序
查看聊天记录程序
清空窗口程序
字体颜色程序
字体类型程序
致谢
本次课程设计在设计的过程中得到了舒振宇老师的指导和支持,给予了很大的帮助,在这里请接受我诚挚的谢意,在调试修改的过程中也得到了班里恰一些同学的帮助,在此一并表示感谢。同时也感谢学校和学院为本次课程设计提供的良好条件。
部分程序
添加对话框背景程序
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BITMAP4);//位图ID
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);
dc.StretchBlt(rect.left,rect.top+10,rect.Width(),rect.Height(),&dcMem,0,0,
bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
CDialog::OnPaint();
}
}
消息处理及滚屏程序
void CSCommTestDlg::OnComm()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafe safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{ ////////以下你可以根据自己的通信协议加入处理代码
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafe型变量
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
for(k=0;k
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
m_strRXData+="\r\n";
}
UpdateData(FALSE); //更新编辑框内容
CEdit *pEt = (CEdit *)GetDlgItem(IDC_EDIT_RXDATA);
CString str="";
int nLength=pEt->SendMessage(WM_GETTEXTLENGTH);
pEt->SetSel(nLength,nLength);
pEt->ReplaceSel(str); //自动滚屏
pEt->LineScroll(pEt->GetLineCount());
}
打开串口程序
void CSCommTestDlg::OnBUTTONdakai()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
if(m_ctrlComm.GetPortOpen())
m_ctrlComm.SetPortOpen(FALSE);
m_ctrlComm.SetCommPort(m_ckh); //选择com
if( !m_ctrlComm.GetPortOpen())
m_ctrlComm.SetPortOpen(TRUE);//打开串口
else
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();//先预读缓冲区以清除残留数据
//以下改变背景表示串口打开
CBrush brush(RGB(0,255,0));//定义画刷
CDC *pDC;//定义一个设备指针
pDC=GetDC();//获取当前设备指针
pDC->SelectObject(brush);
CRect rect;
rect.bottom=260;//定义要画的区域(矩形)
rect.top=240;
rect.left=470;
rect.right=580;
pDC->FillRect(rect,&brush);
}
发送数据及滚屏程序
void CSCommTestDlg::OnButtonManualsend() //发送数据
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //读取编辑框内容
CTime time = CTime::GetCurrentTime(); ///构造CTime对象
int m_nYear = time.GetYear(); ///年
int m_nMonth = time.GetMonth(); ///月
int m_nDay = time.GetDay(); ///日
int m_nHour = time.GetHour(); ///小时
int m_nMinute = time.GetMinute(); ///分钟
int m_nSecond = time.GetSecond(); ///秒
CString m_strTime = time.Format("%Y-%m-%d %H:%M:%S");
m_strRXData+=m_yonghuming+":"+m_strTime+"\r\n"+" "+m_strTXData;
m_ctrlComm.SetOutput(COleVariant(m_yonghuming+":"+m_strTime+"\r\n"+" "+m_strTXData));//发送数据
m_strTXData="\0";
m_strRXData+="\r\n";
UpdateData(false);
//自动滚屏显示最新一行
CEdit *pEt = (CEdit *)GetDlgItem(IDC_EDIT_RXDATA);
CString str="";
int nLength=pEt->SendMessage(WM_GETTEXTLENGTH);
pEt->SetSel(nLength,nLength);
pEt->ReplaceSel(str); //自动滚屏
pEt->LineScroll(pEt->GetLineCount());
}
用户名程序
void CSCommTestDlg::OnBUTTONyonghuming()
{
// TODO: Add your control notification handler code here
UpdateData(true);
}
保存聊天记录程序
void CSCommTestDlg::OnButton1() //保存聊天记录
{
// TODO: Add your control notification handler code here
CString str;
CFileDialog FileDlg(FALSE,"txt","聊天记录",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT);
FileDlg.m_ofn.lpstrInitialDir="桌面:\\";
if(FileDlg.DoModal()==IDOK)
{
ofstream ofs(FileDlg.GetPathName());
GetDlgItem(IDC_EDIT_RXDATA)->GetWindowText(str);
ofs<
}
}
查看聊天记录程序
void CSCommTestDlg::OnButton2() //打开聊天记录
{
// TODO: Add your control notification handler code here
CFileDialog fileDlg(TRUE,"(*.txt)|*.txt","*.txt",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT ,"*.txt");
if(fileDlg.DoModal() == IDOK)
{
CString str;
CFile f;
f.Open(fileDlg.GetFileName(),CFile::modeReadWrite);
f.Read(str.GetBuffer(f.GetLength()),f.GetLength());
f.Close();
SetDlgItemText(IDC_EDIT_RXDATA,str);
//或者使用此语句: GetDlgItem(IDC_EDIT1)->SetWindowText(str);
}
}
清空窗口程序
void CSCommTestDlg::OnButton3() //清空聊天记录
{
// TODO: Add your control notification handler code here
m_strRXData.Empty();
UpdateData(FALSE);
}
字体颜色程序
HBRUSH CSCommTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
if(nCtlColor == CTLCOLOR_EDIT)
pDC->SetTextColor(colour); //设置文本颜色
// TODO: Return a different brush if the default is not desired
return hbr;
}
void CSCommTestDlg::OnCustomdrawSlider1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int temp1,temp2,temp3;
temp1=m_slide1.GetPos(); //获得滑动条的当前位置
temp2=m_slide2.GetPos();
temp3=m_slide3.GetPos();
colour = RGB(temp1,temp2,temp3);
m_edit2.SetFocus();
*pResult = 0;
}
void CSCommTestDlg::OnCustomdrawSlider2(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int temp1,temp2,temp3;
temp1=m_slide1.GetPos(); //获得滑动条的当前位置
temp2=m_slide2.GetPos();
temp3=m_slide3.GetPos();
colour = RGB(temp1,temp2,temp3);
m_edit2.SetFocus();
*pResult = 0;
}
void CSCommTestDlg::OnCustomdrawSlider3(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int temp1,temp2,temp3;
temp1=m_slide1.GetPos(); //获得滑动条的当前位置
temp2=m_slide2.GetPos();
temp3=m_slide3.GetPos();
colour = RGB(temp1,temp2,temp3);
m_edit2.SetFocus();
*pResult = 0;
}
void CSCommTestDlg::OnRadio1()
{
// TODO: Add your control notification handler code here
LOGFONT lf;
CFont font;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet=GB2312_CHARSET;
strcpy(lf.lfFaceName, "楷体_GB2312");
font.CreateFontIndirect(&lf);
font.Detach();
}
void CSCommTestDlg::OnRadio2()
{
// TODO: Add your control notification handler code here
LOGFONT lf;
CFont font;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet=GB2312_CHARSET;
strcpy(lf.lfFaceName, "黑体");
font.CreateFontIndirect(&lf);
font.Detach();
}
字体类型程序
void CSCommTestDlg::OnRadio3()
{
// TODO: Add your control notification handler code here
LOGFONT lf;
CFont font;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet=GB2312_CHARSET;
strcpy(lf.lfFaceName, "宋体");
font.CreateFontIndirect(&lf);
font.Detach();
}