1、主要操作函数
MSComm属于ActiveX控件,其主要操作有:
//设置/获得端口号,如nNewValue=1表示COM1 CommPort(short newValue); //设置/获得接收缓冲区的大小,默认值为1024字节 InBufferSize(short newValue); //设置/获得接收缓冲区内等待读取的字节数,参数为0表示清空缓冲区 InBufferCount(short newValue); //设置/获得接收缓冲区内用Input读入的字节数,设置该值为0表示Input读取缓冲区内所有字节 InputLen(short newValue); //设置/获得发送缓冲区的大小,默认值为512字节 OutBufferSize(short newValue); //设置/获得input读取数据的拣出模式,0:Input通过一个Variant返回文本数据(默认)1、Input通过一个Variant返回二进制数据的数组 InputMode(long newValue) //设置/获得发送缓冲区内等待发送的字节数,0为清空发送缓冲区 OutBufferCount(short newValue); //打开或关闭串口/判断串口是否已经打开,TRUE打开,FALSE关闭 PortOpen(BOOL newValue); //设置/获得当接收缓冲区内的字节个数达到或超过该值后产生代码为ComEvReceive的OnComm事件。 //如果设置为1,表示一接收到字符就产生事件 RThreshold(short newValue); // 硬件握手使能 RTSEnable(BOOL newValue); //设置/获得串口通信参数:波特率、是否奇偶校验、数据位的个数、停止位,格式为“BBBB,P,D,S” Settings(LPCTSTR newValue); //设置/获得当发送缓冲区内的字节数少于该值后就产生代码为ComEvSend的OnComm事件 SThreshold(short newValue); //写串口,即向发送缓冲区发送一串字符。参数为VARIANT类型,需要将字符串转化为VARIANT类型对象 Output(VARIANT newValue); //读串口,即从接收缓冲区读取一串字符。返回值是VARIANT类型对象,需要将其转化为字符串 Input(); //获得/设置窗口上刚发生的事件(事件可理解为软件意义上的“消息”或硬件意义上的“中断”),事件的发送会导致OnComm消息诞生 CommEvent();
2、OnComm事件
如果在通信过程中发生事件或错误,则会触发OnComm事件,并由CommEvent获得代码反应错误类型,可以根据该属性值执行不同的操作,CommEvent属性值及其含义如下:
3、处理通讯方式
MSComm控件有两种处理通讯的方式,事件驱动方式和查询方式:
事件驱动方式:在事件发生时,需要得到通知,例如,在串口接收缓冲区中有字符,或RTS线上一个字符到达或一个变化发生时。在这些情况下,可以利用OnComm捕获并处理这些事件,OnComm还可以检查和处理通讯错误,通讯事件或通讯错误列表参阅CommEvent属性。每个MSComm控件对应一个串行端口,如果需要访问多个串行端口,必须使用多个MSComm控件。
查询方式:查询方式实质上也是事件驱动方式的。在程序的每个关键功能之后,可以通过检查CommEvent属性的值来查询事件或错误。如果应用程序较小,并且是自保持的,这种方法可能是最可取的。例如,写一个简单的电话拨号程序,则没有必要对没接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“确定”响应。
4、MSComm控件使用范例
先给对话框资源插入ActiveX控件microsoft communications control,然后右键添加事件处理程序OnComm,再关联一个控件变量m_ctrlComm。
串口初始化设置:
BOOL Ctest2Dlg::OnInitDialog() { CDialog::OnInitDialog(); ...... // TODO: 在此添加额外的初始化代码 m_ctrlComm.put_CommPort(1);//选择COM1 m_ctrlComm.put_InputMode(1);//设置接收数据拣出模式为二进制模式 m_ctrlComm.put_InBufferSize(1024);//设置串口的接收缓冲区大小为1024 m_ctrlComm.put_OutBufferSize(512);//设置串口发送缓冲区大小为512 m_ctrlComm.put_Settings(L"9600,N,8,1");//设置串口波特率为9600bps,无校验,8位数据位,1位停止位 m_ctrlComm.put_PortOpen(TRUE);//打开串口 m_ctrlComm.put_RThreshold(1);//设置接收事件触发门槛:每当收到一个及一个以上字节时触发一个接收事件 m_ctrlComm.put_InputLen(0);//每次读取时,一次性读取接收缓冲区中的全部数据 m_ctrlComm.put_InBufferCount(0);//清空接收缓冲区 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE }
串口接收数据的代码应在事件处理程序OnComm中添加:
void Ctest2Dlg::OnCommMscomm1() { // TODO: 在此处添加消息处理程序代码 VARIANT variant_inp; COleSafeArray safearray_inp; LONG len, k; BYTE rxdata[2048];//设置BYTE型数组 CString strtemp; //COleVariant myVar; if(m_ctrlComm.get_CommEvent() == 2)//接收数据事件 { //myVar.Attach(m_ctrlComm.get_Input()); //safearray_inp = myVar; variant_inp = m_ctrlComm.get_Input();//读接收缓冲区 safearray_inp = variant_inp;//VARIANT型转换为COleSafeArray型 len = safearray_inp.GetOneDimSize();//得到有效数据长度 for(k=0; k<len; k++)//将数据保存到字符数组中 safearray_inp.GetElement(&k,rxdata+k); m_strRecvData += rxdata;//字符数组转换为CString,即接收编辑框对应的映射变量m_strRecvData } UpdateData(FALSE);//更新接收编辑框的内容 }串口发送数据:
void Ctest2Dlg::OnButtonSend() { UpdateData(TRUE);//获得发送数据到编辑框对应的映射变量m_strSendData /*CByteArray sendAry; WORD wLen; wLen = m_strSendData.GetLength();//获得发送数据的长度 sendAry.SetSize(wLen);//设置sendAry的长度 for(int i=0; i<wLen; i++)//将发送数据转换为CByteArray类型用于发送数据 sendAry.SetAt(i, m_strSendData.GetAt(i)); m_ctrlComm.put_Output(COleVariant(sendAry));//发送数据*/ m_ctrlComm.put_Output(COleVariant(m_strSendData));//发送数据 }
5、其它需要注意的地方
如果想要接收ASCII码为0或大于127的字节数据,必须设置二进制接收数据拣出模式InputMode(1),将NullDiscard属性设置为FALSE(缺省),数据位设置为8位。