MFC串口通信的两种方法及注意事项

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()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码:

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()打开串口,加入如下代码:

// 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();//先预读缓冲区以清除残留数据

        ⑤.发送数据

        

CString m_send = _T("你想要发送的数据")

m_ctrlComm.SetOutput(COleVariant(m_send ));

2.基于win32 API的串口读写

        ①初始化打开串口

         优点:设置、使用更加灵活,因为是基于win32的api函数。所以显得更加通用,适用任何windows程序上引用,不仅仅限于MFC.

         缺点:需要主动的去读取串口上的数据,没有事件通知。

         这里有一点需要注意的是,当COM号大于10的时候,会出现打开错误,一般解决的办法是修改com的名称让它的com号是一位数。除此之外也有其他解决办法,见网上。

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;
}
        ②读串口信息
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);
	PurgeComm(handler, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);	
	return 0;
}

        ③写串口信息
int WriteData(HANDLE handler, char* buffer)
{
	unsigned long dwBytesWrite;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(handler, &dwErrorFlags, &ComStat);
	dwBytesWrite = strlen(buffer);
	bWriteStat=WriteFile(handler, buffer, dwBytesWrite, &dwBytesWrite, NULL);
	if(!bWriteStat)
	{
		AfxMessageBox("写串口失败!");
		return -1;
	}
	return 0;
}

展开阅读全文

没有更多推荐了,返回首页