串口通信编程(1):使用MSComm控件

时间:2022-09-06 10:19:08

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属性值及其含义如下:

串口通信编程(1):使用MSComm控件

串口通信编程(1):使用MSComm控件


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位。