串口通信.docx
- 文档编号:30178867
- 上传时间:2023-08-05
- 格式:DOCX
- 页数:16
- 大小:49.48KB
串口通信.docx
《串口通信.docx》由会员分享,可在线阅读,更多相关《串口通信.docx(16页珍藏版)》请在冰豆网上搜索。
串口通信
VC++下用MSComm控件实现串口通讯2010-10-260:
47:
00
首先,在对话框中创建通信控件,若Control工具栏中缺少该控件,可通过菜单Project-->AddtoProject-->ComponentsandControl插入即可,再将该控件从工具箱中拉到对话框中。
此时,你只需要关心控件提供的对Windows通讯驱动程序的API函数的接口。
换句话说,只需要设置和监视MSComm控件的属性和事件。
打开所需串口后,需要考虑串口通信的时机。
在接收或发送数据过程中,可能需要监视并响应一些事件和错误,所以事件驱动是处理串行端口交互作用的一种非常有效的方法。
使用OnComm事件和CommEvent属性捕捉并检查通讯事件和错误的值。
发生通讯事件或错误时,将触发OnComm事件,CommEvent属性的值将被改变,应用程序检查CommEvent属性值并作出相应的反应
//若是在SDI中使用该控件则要调用下两句,在对话框程序中该语句有MFC自己创建
//所以不用人为添加
DWORDstyle=WS_VISIBLE;
m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);
//串口控件的初始化
DWORDstyle=WS_VISIBLE;
m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);
if(m_MSComm.GetPortOpen())//如果串口是打开的,则行关闭串口
{
m_MSComm.SetPortOpen(FALSE);
}
m_MSComm.SetCommPort
(1);//选择COM1
m_MSComm.SetInBufferSize(1024);//接收缓冲区
m_MSComm.SetOutBufferSize(1024);//发送缓冲区
m_MSComm.SetInputLen(0);//设置当前接收区数据长度为0,表示全部读取
m_MSComm.SetInputMode
(1);//以二进制方式读写数据
m_MSComm.SetRThreshold
(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
m_MSComm.SetSettings("9600,n,8,1");//波特率9600无检验位,8个数据位,1个停止位
if(!
m_MSComm.GetPortOpen())//如果串口没有打开则打开
m_MSComm.SetPortOpen(TRUE);//打开串口
else
m_MSComm.SetOutBufferCount(0);
//控件事件的响应声明
//*.h
//{{AFX_MSG(CGolfView)
afx_msgBOOLOnComm();
DECLARE_EVENTSINK_MAP()
//}}AFX_MSG
//*.cpp
BEGIN_EVENTSINK_MAP(CGolfView,CView)
//{{AFX_EVENTSINK_MAP(CAboutDlg)
ON_EVENT(CGolfView,IDC_MSCOMM1,1/*OnComm*/,OnComm,VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
//控件事件的响应
BOOLCGolfView:
:
OnComm()
{
VARIANTvariant_inp;
COleSafeArraysafearray_inp;
LONGlen,k;
BYTErxdata[2048];//设置BYTE数组An8-bitintegerthatisnotsigned.
CStringstrtemp;
switch(m_MSComm.GetCommEvent())
{
case1:
//comEvSend发送数据
break;
case2:
//comEvReceive读取数据
//MessageBox(_T("读取数据事件"),_T("TRACE"),MB_OK);
variant_inp=m_MSComm.GetInput();//读缓冲区
safearray_inp=variant_inp;//VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize();//得到有效数据长度
//接受数据
for(k=0;k { safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组 BYTEbt=*(char*)(rxdata+k);//字符型 strtemp.Format("%c",bt);//将字符送入临时变量strtemp存放 recd+=strtemp; } //UpdateData(TRUE); break; default: //传输事件出错 m_MSComm.SetOutBufferCount(0); break; } UpdateData(FALSE);//更新图象内容 returnTRUE; } 核心代码 初始化函数 BOOLCSCommTestDlg: : OnInitDialog() { CDialog: : OnInitDialog(); //Add"About..."menuitemtosystemmenu.madebylzycsd //IDM_ABOUTBOXmustbeinthesystemcommandrange. ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX<0xF000); CMenu*pSysMenu=GetSystemMenu(FALSE); if(pSysMenu! =NULL) { CStringstrAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if(! strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu); } } //Settheiconforthisdialog.Theworkdoesthisautomatically //whentheapplication'smainwindowisnotadialog SetIcon(m_hIcon,TRUE); //Setbigicon SetIcon(m_hIcon,FALSE); //Setsmallicon //TODO: Addextrainitializationhere //////////////////////////////////////////////// ////其他初始化 m_ctrlComboComPort.SetCurSel(0); //初始选择串口1 m_ctrlComboBaudRate.SetCurSel(6); //初始选择波特率9600 m_ctrlComboParityBit.SetCurSel(0); //初始选择校验位无 m_ctrlComboDataBit.SetCurSel(3); //初始选择数据位8位 m_ctrlComboStopBit.SetCurSel(0); //初始选择停止位1位 m_strSendPeriod="1000";//初始自动发送周期为1000毫秒 UpdateData(FALSE);//修改编辑框内容 //GetDlgItem(IDC_EDIT_SENDPERIOD)->SetWindowText("1000");另一种方法设置 ////其他初始化 //////////////////////////////////////////////// //串口初始化 m_ctrlComm.SetCommPort(m_ctrlComboComPort.GetCurSel()+1); //选择COM1 //波特率9600,无校验,8个数据位,1个停止位 m_ctrlComm.SetInputMode (1); //输入方式为二进制方式 m_ctrlComm.SetInBufferSize(1024); //设置输入缓冲区大小 m_ctrlComm.SetOutBufferSize(512); //设置输出缓冲区大小 //波特率9600,无校验,8个数据位,1个停止位 m_ctrlComm.SetSettings("9600,N,8,1"); if(! m_ctrlComm.GetPortOpen()) //{ m_ctrlComm.SetPortOpen(TRUE); //打开串口SetPortOpen函数返回值为void //m_ctrlOpenCom.EnableWindow(FALSE);//使按钮变灰 //if(! m_ctrlComm.GetPortOpen()) //如果串口已经打开(打开串口失败),会走到这里来,加上你的判断就可以了…… //AfxMessageBox("没有发现此串口或被其他程序占用"); //m_ctrlCloseCom.EnableWindow(FALSE);//打开串口失败 //m_ctrlOpenCom.EnableWindow(TRUE); //} //else //{ //m_ctrlOpenCom.EnableWindow(FALSE); //} m_ctrlComm.SetRThreshold (1); //参数1表示每当串口接受缓冲区中有多于或等于1个字符时将引发一个接受数据的OnComm事件 m_ctrlComm.SetInputLen(0); //设置当前接受区数据长度为0 m_ctrlComm.GetInput(); //先预读缓冲区以清除残留数据 m_bSerialPortOpened=TRUE;//串口成功打开 m_ctrlOpenCom.EnableWindow(! m_bSerialPortOpened);//打开串口按钮失效 m_ctrlCloseCom.EnableWindow(m_bSerialPortOpened);//关闭串口按钮有效 returnTRUE; //returnTRUEunlessyousetthefocustoacontrol } 从串口接受数据并显示在接受编辑框中 staticlongrxdatacount=0; //接受字符计数 voidCSCommTestDlg: : OnComm() { //TODO: Addyourcontrolnotificationhandlercodehere VARIANTvariant_inp; COleSafeArraysafearray_inp; LONGlen,k; BYTErxdata[2048]; //设置BYTE数组 CStringstrtemp; if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接受缓冲区内有字符 { variant_inp=m_ctrlComm.GetInput(); //读缓冲区 safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 len=safearray_inp.GetOneDimSize(); //得到有效数据长度 for(k=0;k safearray_inp.GetElement(&k,rxdata+k); //转换为BYTE型数组 for(k=0;k { BYTEbt=*(char*)(rxdata+k); //字符型 strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放 m_strEditRXData+=strtemp; //加入接受编辑框对应字符串 //////////////////////////////////////////////////// //放在这里计数会卡 //rxdatacount++;//接受的字节计数 //CStringtemp; //temp.Format("%ld",rxdatacount); //temp="接受: "+temp; //m_ctrlRXCount.SetWindowText(temp);//显示接受计数 //////////////////////////////////////////////////// } rxdatacount+=len; //m_ctrlRXCount.SetWindowText("接受: "+rxdatacount); CStringtemp; temp.Format("%ld",rxdatacount); temp="接受: "+temp; m_ctrlRXCount.SetWindowText(temp);//显示接受计数 } UpdateData(FALSE); //更新编辑框内容 } 点击发送按钮处理函数 //手工发送数据 longTX_count=0; voidCSCommTestDlg: : OnButtonManualsend() { //TODO: Addyourcontrolnotificationhandlercodehere UpdateData(TRUE); //读取编辑框内容 m_ctrlComm.SetOutput(COleVariant(m_strEditTXData)); //发送数据 X_count+=m_strEditTXData.GetLength();//发送计数 CStringstrTemp; strTemp.Format("发送: %d",TX_count); m_ctrlTXCount.SetWindowText(strTemp);//显示计数 GetDlgItem(IDC_BUTTON_MANUALSEND)->EnableWindow(TRUE); } voidCSCommTestDlg: : OnEditchangeComboComport() { //TODO: Addyourcontrolnotificationhandlercodehere } 改变串口时的处理函数 voidCSCommTestDlg: : OnSelchangeComboComport() { //TODO: Addyourcontrolnotificationhandlercodehere //intCpos=m_ctrlComboComPort.GetCurSel()+1;//获取当前选择的串口号 //测试用 //CStringmyString; //myString.Format("%d",Cpos); //CWnd* pWnd = GetDlgItem(IDC_STATIC1); //pWnd->SetWindowText(_T(myString)); //测试用 //if(m_ctrlComm) if(m_ctrlComm.GetPortOpen()) { m_ctrlComm.SetPortOpen(FALSE);//关闭串口 m_bSerialPortOpened=FALSE;//串口成功关闭 m_ctrlOpenCom.EnableWindow(! m_bSerialPortOpened);//打开串口按钮有效 m_ctrlCloseCom.EnableWindow(m_bSerialPortOpened);//关闭串口按钮失效 } //打开串口//选择相应的波特率,校验位,数据位,停止位 m_ctrlComm.SetCommPort(m_ctrlComboComPort.GetCurSel()+1); //选择相应的COM m_ctrlComm.SetInputMode (1); //输入方式为二进制方式 m_ctrlComm.SetInBufferSize(1024);//设置输入缓冲区大小 m_ctrlComm.SetOutBufferSize(512); //设置输出缓冲区大小 //选择相应的波特率,校验位,数据位,停止位 CString setstr; CStringtempstr; m_ctrlComboBaudRate.GetWindowText(tempstr); //获取波特率 setstr=tempstr; setstr+=","; m_ctrlComboParityBit.GetWindowText(tempstr); //获取校验位 tempstr=tempstr.Left (1);//取第一个单词 setstr=setstr+tempstr+","; m_ctrlComboDataBit.GetWindowText(tempstr); //获取数据位 setstr=setstr+tempstr+","; m_ctrlComboStopBit.GetWindowText(tempstr); //获取停止位 setstr+=tempstr; /* intBaudRate=9600; charParityBit=n; intDataBit=8; intStopBit=1; setstr.Format("%d,%c,%d,%d",BaudRate,ParityBit,DataBite,StopBit); SetSettings(setstr); */ //m_ctrlComm.SetSettings("9600,N,8,1"); m_ctrlComm.SetSettings(setstr); if(! m_ctrlComm.GetPortOpen()) m_ctrlComm.SetPortOpen(TRUE); //打开串口 m_ctrlComm.SetRThreshold (1); //参数1表示每当串口接受缓冲区中有多于或等于1个字符时将引发一个接受数据的OnComm事件 m_ctrlComm.SetInputLen(0); //设置当前接受区数据长度为0 m_ctrlComm.GetInput(); //先预读缓冲区以清除残留数据 m_bSerialPortOpened=TRUE;//串口成功打开 m_ctrlOpenCom.EnableWindow(! m_bSerialPortOpened);//打开串口按钮失效 m_ctrlCloseCom.EnableWindow(m_bSerialPortOpened);//关闭串口按钮有效 } 打开串口 voidCSCommTestDlg: : OnButtonOpen() { //TODO: Addyourcontrolnotificationhandlercodehere if(! m_ctrlComm.GetPortOpen()) { m_ctrlComm.SetPortOpen(TRUE); m_bSerialPortOpened=TRUE;//串口成功打开 m_ctrlOpenCom.EnableWindow(! m_bSerialPortOpened);//打开串口按钮失效 m_ctrlCloseCom.EnableWindow(m_bSerialPortOpened);//关闭串口按钮有效 } } 关闭串口 voidCSCommTestDlg: : OnButtonClose() { //TODO: Addyourcontrolnotificationhandlercodehere if(m_ctrlComm.GetPortOpen()) { m_ctrlComm.SetPortOpen(FALSE); m_bSerialPortOpened=FALSE;//串口成功关闭 m_ctrlOpenCom.EnableWindow(! m_bSerialPortOpened);//打开串口按钮有效 m_ctrlCloseCom.EnableWindow(m_bSerialPortOpened);//关闭串口按钮失效 } } 定时器触发后运行的函数 voidCSCommTestDlg: : OnTimer(UINTnIDEvent) { //TODO: Addyourmessagehandlercodehereand/orcalldefault //添加你要处理的函数,当定时时间到时自动调用 //通过调用SetTimer(1,1000,NULL)启动定时器,通过调用KillTimer(intnIDEvent)关闭定时器 OnButtonManualsend(); CDialog: : OnTimer(nIDEvent); } 选择自动发送触发的函数 voidCSCommTestDlg: : OnCheckAutosend() { //TODO: Addyourcontrolnotificationhandlercodehere if(m_ctrlAutoSend.GetCheck()) { //自动发送 inti=atoi(m_strSendPeriod); SetTimer(1,i,NULL); //函数反回值就是第一个参数值1,表示此定时器的ID号。 //第二个参数表示要等待100毫秒时间再重新处理一次。 第三个参数在这种方法中一般用NULL。 //注意: 设置第二个参数时要注意,如果设置的等待时间比处理时间短,程序就会出问题了。 //OnButtonManualsend(); } else { //取消自动
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 串口 通信