VC 串口通信实现方式
Posted deep_learninger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC 串口通信实现方式相关的知识,希望对你有一定的参考价值。
利用师姐QT2440开发板控制机械臂, 串口通信出现问题, 找到usb转串口后,任然找不到相应的驱动。初步打算用单片机实现。
1.基于Active控件的方式(MSComm)
优点是:直接利用控件,在串口有数据到达时,会促发相应的事件响应函数,然后你可以在实践响应函数里,进行数据的读取。
缺点是:数据在发送和接受的过程中VARIANT、 COleSafeArray 类型的转换,显得繁琐。
步骤:
①插入控件
选择Project菜单下Add To Project子菜单中的 Components and Controls…选项,在弹出的对话框中双击Registered ActiveX Controls项,则所有注册过的ActiveX控件出现在列表框中。 选择Microsoft Communications Control, version 6.0,单击Insert按钮将它插入到我们的Project中来,接受缺省的选项。这时在ClassView视窗中就可以看到CMSComm类了,并且在控件工具栏Controls中出现了电话图标,现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
②为拖入对话框的 CMSComm控件添加对应的控制变量 m_ctrlComm。
③添加对应的消息响应函数OnComm()
打开ClassWizard->Message Maps,选择类CSCommTestDlg,选择IDC_MSCOMM1,双击消息OnComm,将弹出的对话框中将函数名改为OnComm,这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码:
[cpp] view plain copy- void CSCommTestDlg::OnComm()
- // TODO: Add your control notification handler code here
- VARIANT variant_inp;
- COleSafeArray 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型变量转换为ColeSafeArray型变量
- len=safearray_inp.GetOneDimSize(); //得到有效数据长度
- for(k=0;k<len;k++)
- safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
- for(k=0;k<len;k++) //将数组转换为Cstring型变量
- BYTE bt=*(char*)(rxdata+k); //字符型
- strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
- m_strRXData+=strtemp; //加入接收编辑框对应字符串
- UpdateData(FALSE); //更新编辑框内容
④.打开串口和设置串口参数
现在我们在主对话框的CSCommTestDlg::OnInitDialog()打开串口,加入如下代码:
[cpp] view plain copy- // 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);//打开串口
- else
- AfxMessageBox("cannot open serial port");
- m_ctrlComm.SetSettings("9600,n,8,1"); //波特率9600,无校验,8个数据位,1个停止位
- m_ctrlComm.SetInputModel(1); //1:表示以二进制方式检取数据
- m_ctrlComm.SetRThreshold(1);
- //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
- m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为0
- m_ctrlComm.GetInput();//先预读缓冲区以清除残留数据
⑤.发送数据
[cpp] view plain copy
- CString m_send = _T("你想要发送的数据")
- m_ctrlComm.SetOutput(COleVariant(m_send ));
2.基于win32 API的串口读写
①初始化打开串口
优点:设置、使用更加灵活,因为是基于win32的api函数。所以显得更加通用,适用任何windows程序上引用,不仅仅限于MFC.
缺点:需要主动的去读取串口上的数据,没有事件通知。
这里有一点需要注意的是,当COM号大于10的时候,会出现打开错误,一般解决的办法是修改com的名称让它的com号是一位数。除此之外也有其他解决办法,见网上。
[cpp] view plain copy- HANDLE InitCom(char* comName)
- HANDLE hCom;
- hCom = CreateFile(comName,//COM7口
- GENERIC_READ|GENERIC_WRITE, //允许读和写
- 0, //独占方式
- NULL,
- OPEN_EXISTING, //打开而不是创建
- 0, //同步方式
- NULL);
- if(hCom == (HANDLE)-1)
- return NULL;
- SetupComm(hCom,100,100); //输入缓冲区和输出缓冲区的大小都是100
- COMMTIMEOUTS TimeOuts;
- //设定读超时
- TimeOuts.ReadIntervalTimeout=MAXDWORD;
- TimeOuts.ReadTotalTimeoutMultiplier=0;
- TimeOuts.ReadTotalTimeoutConstant=0;
- //在读一次输入缓冲区的内容后读操作就立即返回,
- //而不管是否读入了要求的字符。
- //设定写超时
- TimeOuts.WriteTotalTimeoutMultiplier=100;
- TimeOuts.WriteTotalTimeoutConstant=500;
- SetCommTimeouts(hCom,&TimeOuts); //设置超时
- DCB dcb;
- GetCommState(hCom, &dcb);
- dcb.BaudRate=115200; //波特率为9600
- dcb.ByteSize=8; //每个字节有8位
- dcb.Parity=NOPARITY; //无奇偶校验位
- dcb.StopBits=1; //两个停止位
- SetCommState(hCom, &dcb);
- PurgeComm(hCom, PURGE_TXCLEAR|PURGE_RXCLEAR);
- return hCom;
[cpp] view plain copy
- int ReadData(HANDLE handler, char* buffer)
- char readBuffer[512];
- memset(readBuffer, 0, 512);
- DWORD wCount= 512;//读取的字节数
- BOOL bReadStat;
- bReadStat = ReadFile(handler, readBuffer, wCount, &wCount, NULL);
- if(!bReadStat)
- AfxMessageBox("读串口失败!");
- return -1;
- strcpy(buffer, readBuffer);
- 8051单片机串口波特率计算方式