串口控件编程

    串口即是我们常见的COM口,COM是PC为和外界通信所提供的一种串行数据传输的接口。作为一种物理通信的途径和设备,它和目前风靡的另一种串接口――USB所提供的功能是一致的。无论是在工业控制还是其他领域,串口都是比较常用的通信接口,关于串口的一些基本知识希望大家根据需要上网了解,大家可以先学习一些基本知识,以后学习单片机时大家就可以使用自己编写的串口调试助手啦......
    串口编程可以分为:基于MSCOMM控件编程和基于Win API的SDK编程 两种方式;基于控件的编程比较简单方便,我们将学习该编程方法。基于API的编程比较灵活,有兴趣并且学习过windows编程的同学可以尝试使用该方法编写。

    Visual C++为我们提供了一种好用的ActiveX控件Microsoft Communications Control(即MSComm)来支持应用程序对串口的访问,在应用程序中插入MSComm控件后就可以较为方便地实现通过串口在PC与单片机之间收发数据。

注意:串口控件MSCOMM的使用注册mscomm32.ocx,在没有安装的计算机上运行时要把mscomm32.ocx拷到Windows目录下的System32子目录中(或SysWow64)并注册。


1、学习了解其他串口软件的基本功能做出如下界面


2、根据需要完成软件界面的制作

void CXXXDlg::InitComboBox()
{
	//初始化COMM
	CComboBox *pComBoComm=(CComboBox*)GetDlgItem(IDC_COMBO_COMM);
	ASSERT(pComBoComm);
	for(int i=1;i<=8;i++)
	{
		CString strComm;
		strComm.Format(_T("COM%d"),i);
		pComBoComm->AddString(strComm);
	}
	pComBoComm->SetCurSel(0);
	//初始化BaudRate
	CComboBox *pComBoBaudRate=(CComboBox*)GetDlgItem(IDC_COMBO_BAUDRATE);
	ASSERT(pComBoBaudRate);
	pComBoBaudRate->SetItemData(pComBoBaudRate->AddString(_T("4800")),4800);
	pComBoBaudRate->SetItemData(pComBoBaudRate->AddString(_T("9600")),9600);
	pComBoBaudRate->SetItemData(pComBoBaudRate->AddString(_T("19200")),19200);
	pComBoBaudRate->SetItemData(pComBoBaudRate->AddString(_T("38400")),38400);
	pComBoBaudRate->SetItemData(pComBoBaudRate->AddString(_T("115200")),115200);
	pComBoBaudRate->SetCurSel(1);
	//初始化CheckBit
	CComboBox *pComBoCheckBit=(CComboBox*)GetDlgItem(IDC_COMBO_CHECKBIT);
	ASSERT(pComBoCheckBit);
	pComBoCheckBit->SetItemData(pComBoCheckBit->AddString(_T("无none")),NOPARITY);
	pComBoCheckBit->SetItemData(pComBoCheckBit->AddString(_T("奇ODD")),ODDPARITY);
	pComBoCheckBit->SetItemData(pComBoCheckBit->AddString(_T("偶EVEN")),EVENPARITY);
	pComBoCheckBit->SetCurSel(0);
	//初始化DataBit
	CComboBox *pComBoDataBit=(CComboBox*)GetDlgItem(IDC_COMBO_DATABIT);
	ASSERT(pComBoDataBit);
	pComBoDataBit->SetItemData(pComBoDataBit->AddString(_T("6")),6);
	pComBoDataBit->SetItemData(pComBoDataBit->AddString(_T("7")),7);
	pComBoDataBit->SetItemData(pComBoDataBit->AddString(_T("8")),8);
	pComBoDataBit->SetCurSel(2);
	//初始化StopBit
	CComboBox *pComBoStopBit=(CComboBox*)GetDlgItem(IDC_COMBO_STOPBIT);
	ASSERT(pComBoStopBit);
	pComBoStopBit->SetItemData(pComBoStopBit->AddString(_T("1")),ONESTOPBIT);
	pComBoStopBit->SetItemData(pComBoStopBit->AddString(_T("2")),TWOSTOPBITS);
	pComBoStopBit->SetCurSel(0);
}
void CXXXMDlg::OnBtnCommctrl() 
{
......
}
3、插入MSCOMM控件并分析相关头文件和cpp文件
 详见mymscomm.h文件中的注释如下:

#if !defined(AFX_MYMSCOMM_H__72ADD1D0_0008_431B_97FB_F32286F1F1EC__INCLUDED_)
#define AFX_MYMSCOMM_H__72ADD1D0_0008_431B_97FB_F32286F1F1EC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++

// NOTE: Do not modify the contents of this file.  If this class is regenerated by
//  Microsoft Visual C++, your modifications will be overwritten.

/
// CMSComm wrapper class

class CMSComm : public CWnd
{
protected:
	DECLARE_DYNCREATE(CMSComm)
public:
	CLSID const& GetClsid()
	{
		static CLSID const clsid
			= { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } };
		return clsid;
	}
	virtual BOOL Create(LPCTSTR lpszClassName,
		LPCTSTR lpszWindowName, DWORD dwStyle,
		const RECT& rect,
		CWnd* pParentWnd, UINT nID,
		CCreateContext* pContext = NULL)
	{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }

    BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,
		const RECT& rect, CWnd* pParentWnd, UINT nID,
		CFile* pPersist = NULL, BOOL bStorage = FALSE,
		BSTR bstrLicKey = NULL)
	{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
		pPersist, bStorage, bstrLicKey); }

// Attributes
public:

// Operations
public:
	void SetCDHolding(BOOL bNewValue);
	BOOL GetCDHolding();
	void SetCommID(long nNewValue);
	long GetCommID();
	void SetCommPort(short nNewValue);//设置端口号,如nNewValue =1表示COM1
	short GetCommPort();
	void SetCTSHolding(BOOL bNewValue);
	BOOL GetCTSHolding();
	void SetDSRHolding(BOOL bNewValue);
	BOOL GetDSRHolding();
	void SetDTREnable(BOOL bNewValue);
	BOOL GetDTREnable();
	void SetHandshaking(long nNewValue);
	long GetHandshaking();
	void SetInBufferSize(short nNewValue);
	short GetInBufferSize();
	void SetInBufferCount(short nNewValue);
	short GetInBufferCount();
	void SetBreak(BOOL bNewValue);
	BOOL GetBreak();
	void SetInputLen(short nNewValue);
	short GetInputLen();
	void SetNullDiscard(BOOL bNewValue);
	BOOL GetNullDiscard();
	void SetOutBufferSize(short nNewValue);
	short GetOutBufferSize();
	void SetOutBufferCount(short nNewValue);
	short GetOutBufferCount();
	void SetParityReplace(LPCTSTR lpszNewValue);
	CString GetParityReplace();
	void SetPortOpen(BOOL bNewValue);//打开或关闭串口,TRUE:打开,FALSE:关闭
	BOOL GetPortOpen();//串口是否已打开,TRUE:打开,FALSE:关闭
	void SetRThreshold(short nNewValue);//如果设置为1,表示一接收到字符就发送2号事件
	short GetRThreshold();
	void SetRTSEnable(BOOL bNewValue);//硬件握手使能
	BOOL GetRTSEnable();
	void SetSettings(LPCTSTR lpszNewValue);//Settings 由4部分组成,其格式为:"BBBB,P,D,S",即"波特率,是否奇偶校
                                           //验,数据位//个数,停止位",如设置为:"9600,n,8,1" 
	CString GetSettings();
	void SetSThreshold(short nNewValue);//如果保持缺省值0不变,则表示发送数据的过程中串口上不发生事件
	short GetSThreshold();
	void SetOutput(const VARIANT& newValue);//一个非常重要的函数,用于写串口,注意其接收的输入参数为VARIANT类型对象,
                                            //我们需要将字符串转化为VARIANT类型对象
	VARIANT GetOutput();
	void SetInput(const VARIANT& newValue);
	VARIANT GetInput();//一个非常重要的函数,用于读串口,注意其返回的是VARIANT类型对象,我们需要将其转化为字符串
	void SetCommEvent(short nNewValue);
	short GetCommEvent();//一个非常重要的函数,获得串口上刚发生的事件("事件"可以理解为软件意义上的"消息"或硬件意义上的"中断"),
	                     //事件的发送会导致OnComm消息的诞生
	void SetEOFEnable(BOOL bNewValue);
	BOOL GetEOFEnable();
	void SetInputMode(long nNewValue);
	long GetInputMode();
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MYMSCOMM_H__72ADD1D0_0008_431B_97FB_F32286F1F1EC__INCLUDED_)
 基本上,MSComm的诸多接口可以分为如下几类:
(1)打开与设置串口接口函数;
(2)获得串口设置和串口状态接口函数;
(3)设置串口发送数据方式、缓冲区接口及发送数据接口函数;
(4)设置串口接收数据方式、缓冲区接口及接收数据接口函数; 
4、串口的初始化
if(m_mscomm.GetPortOpen())
	m_mscomm.SetPortOpen(FALSE);	
m_mscomm.SetCommPort(nSelComm); //选择com
m_mscomm.SetInBufferSize(1024); //设置输入缓冲区的大小,Bytes 
m_mscomm.SetOutBufferSize(512); //设置输出缓冲区的大小,Bytes 
m_mscomm.SetPortOpen(TRUE);//打开串口
m_mscomm.SetInputMode(1); //设置输入方式为二进制方式
CString str;
str.Format(_T("%d,n,8,1"), nSelBaudRate);
m_mscomm.SetSettings(str); //波特率4800,无校验,8个数据位,1个停止位
m_mscomm.SetRThreshold(1); //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
//m_CommCtrl.SetInputLen(0); //设置当前接收区数据长度为0
m_mscomm.GetInput();//先预读缓冲区以清除残留数据
5、数据发送
void CXXXMDlg::OnBtnSend() 
{
	// TODO: Add your control notification handler code here
	if( !m_mscomm.GetPortOpen())
	{
		MessageBox(_T("串口未打开!请先打开串口!"), _T("失败"), MB_OK);	
		return;
	}

	CByteArray sendArr;  
	WORD wLength;
	CString m_send;
	GetDlgItem(IDC_EDIT_SEND)->GetWindowText(m_send);
	wLength = m_send.GetLength(); 
	sendArr.SetSize(wLength); 
	for(int i =0; i<wLength; i++) 
	{ 
		sendArr.SetAt(i, m_send.GetAt(i)); 
	} 
        m_mscomm.SetOutput(COleVariant(sendArr)); 
}
6、数据接收
为了处理接收事件,我们需要为MScomm控件添加对应的消息OnComm处理函数,函数名可自定义为OnMscomm。
void CXXXMDlg::OnMscomm() 
{
    // 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_mscomm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
    {             以下你可以根据自己的通信协议加入处理代码
        variant_inp=m_mscomm.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存放
	    //strtemp.Format("%3X",bt);//16进制
            m_strRXData+=strtemp; //加入接收编辑框对应字符串 
        }
    }
    UpdateData(FALSE);
}
7、16进制实现
接收时:strtemp.Format("%3X",bt);//16进制
发送时:
char CXXXDlg::HexChar(char c)//检测一个字符是不是十六进制字符,若是返回相应的值,否则返回0x10;
{	if((c>='0')&&(c<='9'))
	return c-0x30;
	else if((c>='A')&&(c<='F'))
	return c-'A'+10;
	else if((c>='a')&&(c<='f'))
	return c-'a'+10;
	else return 0x10;
}

int CXXXDlg::Str2Hex(CString str,CByteArray &data)
{//将一个字符串作为十六进制串转化为一个字节数组,字节间可用空格分隔,返回转换后的字节数组长度,同
 //时字节数组长度自动设置。
	int t,t1;
	int rlen=0,len=str.GetLength();
	data.SetSize(len/2);
	for(int i=0;i<len;)
	{char l,h=str[i];
	if(h==' ')
	{i++;
	continue;
	}
	i++;
	if(i>=len)break;
	l=str[i];
	t=HexChar(h);
	t1=HexChar(l);
	if((t==16)||(t1==16))
		break;
	else t=t*16+t1;
	i++;
	data[rlen]=(char)t;
	rlen++;
	}
	data.SetSize(rlen);
	return rlen;
}

CByteArray data;
CString m_SendData
m_SendData.Format("%02x", The data you want to send);
Str2Hex(m_SendData, data);

m_CommCtrl.SetOutput(COleVariant(data));


下面是我的工程地址:欢迎交流学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值