原创 基于MSCOMM控件串口通讯(MFC)

2010-7-26 16:55 6220 5 8 分类: 软件与OS

个人收集和理解所书,转载注明出处


虽然网上很多关于这个的资料了,但还是自己总结下


 


获取当前可用的串口


 


可以通过读取注册表获取相应的值。当前可用的COM口在注册表中的位置:


HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM


通过枚举来获取所有的COM口。实现如下:


 


调用举例:


enum_reg_key_value(HKEY_LOCAL_MACHINE, ”HARDWARE\\DEVICEMAP\\SERIALCOMM”);


 


bool CValueDlg::enum_reg_key_value(HKEY hKey, LPCTSTR lpSubKey)


{


#define MAX_VALUE_NAME 100


 


    HKEY    hOpenKey;


    long    lResult = 0;


    CHAR    achClass[MAX_PATH];


    DWORD   cchClassNameLen;


    DWORD   cMaxClassLen;


    DWORD   cSubKeysNum;


    DWORD   cbMaxSubKeyLen;


    DWORD   cbValuesNum;


    DWORD   cbMaxValueNameLen;


    DWORD   cbMaxValueLen;


    DWORD   cbSecurityDescriptor;


    FILETIME ftLastWriteTime;


 


    CHAR  achValue[MAX_VALUE_NAME];


    DWORD cbValue = MAX_VALUE_NAME;


   


    DWORD DataType;


    BYTE  Data[255];


    DWORD DataLen;


    CString StrData = L"";


 


    lResult = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &hOpenKey);


 


    if(ERROR_SUCCESS != lResult)


    {


        return FALSE;


    }


 


    RegQueryInfoKey(hOpenKey, //已打开的键的句柄


                                       achClass, //类型名称


                                       &cchClassNameLen, //类型名称的长度


                                      NULL, //保留


                                    &cSubKeysNum, // 返回子键的数目


                                    &cbMaxSubKeyLen, // 返回最长的子键长度


                                   &cMaxClassLen, // 返回最长的类长度


                                  &cbValuesNum, // 返回值的数目


                                 &cbMaxValueNameLen, // 返回最长的值项,名称的长度


                                 &cbMaxValueLen, // 返回最长的值的长度


                                &cbSecurityDescriptor, //返回安全描述


                               &ftLastWriteTime); // 返回键最后被写入的时间


 


    for (DWORD j = 0, retValue = ERROR_SUCCESS; j < cbValuesNum; j++)


   {


        cbValue = MAX_VALUE_NAME;


        memset(achValue, 0, sizeof(achValue));


        memset(Data, 0, sizeof(Data));


        StrData = L"";


 


        retValue = RegEnumValue(hOpenKey,


                                                           j,


                                                          achValue,


                                                          &cbValue,


                                                          NULL,


                                                          &DataType,


                                                         Data,


                                                        &DataLen);


 


         if (retValue == (DWORD) ERROR_SUCCESS )


         { 


             StrData.Format("%s", Data);


             m_ComboComSelect.AddString(StrData);  


         }


    }


 


    RegCloseKey(hOpenKey);


    return true;


 


#undef MAX_VALUE_NAME


}


打开串口


 


m_CMSComm.SetCommPort(4);


m_CMSComm. SetInBufferSize(1024);


m_CMSComm. SetOutBufferSize(512);


 


if(!m_CMSComm.GetPortOpen())


{


       try


       {


              m_CMSComm.SetPortOpen(TRUE); //打开串口


       }


       catch(COleDispatchException *e)//如果所要打开的串口已经被其他程序使用,会报异常


       {    


              AfxMessageBox("Error:The COM has been occupied or isn't Exist");


              e = NULL;


              return;


       }


 


       m_CMSComm.SetInputMode(0); //设置输入方式为Text


       m_CMSComm.SetSettings(m_Uart_Struct.settings);


       m_CMSComm.SetRThreshold(1); //为1表示接收到一个字符便出发接收事件


       m_CMSComm.SetInputLen(0);// 设置当前接收区数据长度为0,表示全部读取


}


else


{


              AfxMessageBox("Error:The COM has been occupied or isn't Exist");


}


 


串口数据发送


关于串口数据的发送网上很多的写法都是利用以下的方法


CByteArray array;


DWORD len = 0;


char TxData [1024 + 1];


CString StrData = L"";


 


len = StrData.GetLength();


memset(TxData, 0, sizeof(TxData));


strcpy(TxData, StrData);


array.RemoveAll();


array.SetSize(len);


 


for(DWORD i=0; i<len; i++)


{


       array.SetAt(i, TxData);


}


      


m_CMSComm.SetOutput(COleVariant(array)); …………………………①


其实所有的关键都在于①这条语句,传入的数据类型强制转换为任意数据类型COleVariant,于是将所要发送的字符串直接强制转换也是可以的。以上代码便以下面一条语句即可实现发送数据的操作。


m_CMSComm.SetOutput(COleVariant(StrData));


 


数据接收


 


事件2表示接收事件,其他事件所对应的值可以网上查下,很多有介绍了。如


http://blog.ednchina.com/bobi2005/175488/message.aspx


其实这里的关键就在于接收到的数据存在数据类型VARIANT中,关于它的使用也自己查吧。以下是接收的一种写法。


 


void CValueDlg::OnComm ()


{


       VARIANT          vResponse;


       int                        rec_data_len;


 


       if(m_CMSComm.GetCommEvent() == 2)


       {


              rec_data_len = m_CMSComm.GetInBufferCount();


 


              if(rec_data_len > 0)


              {


                     vResponse = m_CMSComm.GetInput();


                    


                     if(VT_BSTR == vResponse.vt)


                     {


                            save_rec_data(CString(vResponse.bstrVal));


                     }


              } 


       }


 


       return;


}


 


以下介绍另外两种接收数据写法,注意,这两种写法需要将open函数中的模式设为二进制模式即


m_CMSComm.SetInputMode(1);


 


方法 一、


 


void CValueDlg::OnComm ()


{


       VARIANT variant_inp;


       int rec_data_len;


       CString strtemp;


       char chData[1024 + 1];


 


       if(m_CMSComm.GetCommEvent() == 2)


       {


              variant_inp = m_CMSComm.GetInput();


              rec_data_len = variant_inp.parray->rgsabound->cElements;


 


              if (rec_data_len > 0)


              {


                     memset(chData, 0, sizeof(chData));


                     memcpy(chData, (char *)variant_inp.parray->pvData, rec_data_len);


                     strtemp.Format("%s", chData);


                     save_rec_data(strtemp);


              }


       }


 


       return;


}


 


方法 二、


这种方法是网上很多人转帖的写法,也可以实现接收的功能。如下


 


void CValueDlg::OnComm ()


{


    VARIANT      variant_tmp;


    COleSafeArray  safe_array_tmp;


    long length, i;


    BYTE data[1024];


    CString str ="";


    CString strTemp;


 


    if(m_CMSComm.GetCommEvent() == 2)


   {


       variant_tmp  =  m_CMSComm.GetInput();


       safe_array_tmp  =  variant_tmp;………………②


       length = safe_array_tmp.GetOneDimSize();


           


       for(i=0; i<length; i++)


      {


              safe_array_tmp.GetElement(&i, data+i); //将数据转换为BYTE型


     }


           


      for(i=0; i<length; i++) //将数组转换为Cstring型变量


      {


           BYTE bt = *(char*)(data+i);


           strTemp.Format("%c",bt);


           m_strReceiveMsg += strTemp;


            ……


      }


  }


}


 


       我最开始看到的也是这种方法,但是和许多的网友一样在执行到②语句的时候,就弹出一个警告框,忽略后还是可以继续运行。还以为是这种写法有错呢,硬着头皮看了VARIANT和COleSafeArray这两个类确定没错,回头仔细检查打开串口的设置发现设置输入模式的地方错了,如果你要用以上这种方法需要将输入模式设置成二进制模式,这样②这条语句便可以正确执行了,不知道其他人是否也很我一样的这样解决的,提出来分享下。


    以上三法希望你可以找到合适的。


 


关闭串口


 


if(m_CMSComm.GetPortOpen())


{


       m_CMSComm.SetPortOpen(FALSE);


}


        用控件虽然大大简化,但是如果有台上位机没装VC++程序,那么Release出来的程序也是不能运行的,这里下了个批处理文件,来注册控件,见附件。这样串口通信就OK了。

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户1579310 2014-7-22 09:45

学习了

用户377235 2014-5-29 20:16

转载很多的,估计都是看了龚建伟的串口助手v1.0公开的源码

用户1511430 2013-10-5 13:35

用户1280885 2013-4-16 17:07

正需要看一下怎麼設定,太感激了

用户416974 2013-4-16 15:47

感谢分享,先收下

用户925091 2011-5-2 17:39

LZ的guide不错,赞! 另,E_Eff相关于预置频率下的电长度,RF/MW应用中需要关注,SI应用中可忽略
相关推荐阅读
用户286528 2011-03-14 22:36
Mstar之Service
注:以下来自Mstar官方培训文档。       Service不具有使用者接口,透过API提供服务给多个不同的APP或Service;     Service大多于手机开机时并启动。生命周期比App...
用户286528 2011-03-14 20:34
Mstar之事件流程分析
注:个人收集和理解所书,有误请指出,转载请注明出处!                在事件流程的PPT已经讲的蛮详细了。本来还想写写架构,看了一下,文档里已经介绍的可以了。还是只记录下事件方面的。  ...
用户286528 2011-03-04 11:12
Mstar之RS文件分析
注:个人理解所书,有误请指出,转载注明出处。        在每个App底下都有一个res文件夹。这些文件的主要功能是将UI layout从程序中分离,变更的时候无需更改代码。        这些文件...
用户286528 2011-03-03 15:26
Mstar XRG分析
     注:为个人收集和理解所书,如有误请指出,转载请注明出处        用XRG(XMMI Resource Generator)打开一个工程后,如果是原始release过来的工程,我想在左侧...
用户286528 2011-03-02 21:24
Mstar 入门级资料
如果你也在做Mstar平台,欢迎加入Q群:24819695,共同交流学习MStar事件流程.pptMSTAR平台详细介绍-zj(Feature_List).xlsmstar_wifi_MSB7601_...
用户286528 2011-01-16 13:47
PCB Layout资料
我自己是没怎么研究了,给需要的同志吧,放在我这浪费了cadence版图设计.pdfpcb 可测性设计.pdfpcb板的emc问题.pdfpcb布线面临的关键时刻.pdfthe effects of v...
EE直播间
更多
我要评论
3
5
关闭 站长推荐上一条 /3 下一条