久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

用vs2010開發(fā)基于VC++的MFC 串口通信一*****兩臺電腦同一個串口號之間的通信

 xinyz4104 2015-05-05
 

用vs2010開發(fā)基于VC++的MFC 串口通信一*****兩臺電腦同一個串口號之間的通信

此文章以visual C++數(shù)據(jù)采集與串口通信測控應用實戰(zhàn)為參考教程

此文章適合VC++串口通信入門

一、頁面布局及添加控件

1, 安裝好vs2010如圖


2, 新建一個基于VC++的MFC項目comm


注意:點擊ok,然后next,這時候要將application type改成dialog base,接著next到最后一個對話框是將generated dasses改成CcommDlg,,然后finish


4, 將新生成的項目的對話框默認dialog edit刪去,如圖


5,在對話框中添加兩個static text,,兩個edit text,,兩個按鈕,

成品圖如下


6,添加comm控件

    1)在解決方案窗口右擊新建的解決方案,,點擊add->class

     2)選擇MFC class from activex control如圖


點擊add,available activex controls選擇microsoft communication controls versions 6.0,然后點確定就行

這時候?qū)υ捒驎霈F(xiàn)一個電話圖標,,可能有一半白邊去不了,這時候右擊電話圖標點擊edit control就可以去掉了,。

7,同時定義各個控件的類型,、ID及相關(guān)屬性


注:此項目只添加了發(fā)送和退出程序按鈕

這時候得到了完整的串口通信對話框:


8, 添加成員變量,右擊對話框,,點擊class wizard,點擊member variables標簽,,選中需要添加的id,雙擊即可添加

依次為下表中的ID添加變量


期間,IDC_MSCOMM1控件在標簽中沒有,,則在生成的對話框中右擊comm控件點擊add variables即可

9, 為mscomm,,兩個button添加響應事件,切換到class wizard的virtual function雙擊控件ID,添加響應事件,,默認即可,,也可改為自己想要的標題

為comm控件添加響應事件可能雙擊不了(我就是遇到這種問題),這時候只要右擊comm控件圖標,,點擊add event handler即可,。如圖



這時候基本界面已經(jīng)布置好了,開始添加代碼了,。

二,、代碼添加

1、找到解決方案(solution explorer)的sources files點開,雙擊其中的mscommDlg.cpp我們的所有代碼將添加到這個源文件中

2,、進行串口初始化及其他串口設(shè)置

將以下代碼添加到oninitialdialog函數(shù)

m_ctrlcomm.put_CommPort(3);//選擇com3口
m_ctrlcomm.put_InputMode(1);//輸入方式為二進制方式
m_ctrlcomm.put_InBufferSize(1024);//輸入緩沖區(qū)大小為1024byte
m_ctrlcomm.put_OutBufferSize(512);//輸出緩沖區(qū)大小為512byte
m_ctrlcomm.put_Settings(_T("9600,n,8,1"));//設(shè)置串口參數(shù):9600波特率,,無奇偶校驗,8個數(shù)據(jù)位,,1個停止位
if(!m_ctrlcomm.get_PortOpen())
    m_ctrlcomm.put_PortOpen(1);//打開串口
m_ctrlcomm.put_RThreshold(1);//每當串口接收緩沖區(qū)有多余或等于1個字符時將引發(fā)一個接收數(shù)據(jù)的oncomm事件
m_ctrlcomm.put_InputLen(0);//設(shè)置當前接收區(qū)數(shù)據(jù)長度為0
m_ctrlcomm.get_Input();//預讀緩沖區(qū)以清空殘留數(shù)據(jù)

m_ctrlcomm.put_CommPort(3);//選擇com3口
m_ctrlcomm.put_InputMode(1);//輸入方式為二進制方式
m_ctrlcomm.put_InBufferSize(1024);//輸入緩沖區(qū)大小為1024byte
m_ctrlcomm.put_OutBufferSize(512);//輸出緩沖區(qū)大小為512byte
m_ctrlcomm.put_Settings(_T("9600,n,8,1"));//設(shè)置串口參數(shù):9600波特率,,無奇偶校驗,8個數(shù)據(jù)位,,1個停止位
if(!m_ctrlcomm.get_PortOpen())
    m_ctrlcomm.put_PortOpen(1);//打開串口
m_ctrlcomm.put_RThreshold(1);//每當串口接收緩沖區(qū)有多余或等于1個字符時將引發(fā)一個接收數(shù)據(jù)的oncomm事件
m_ctrlcomm.put_InputLen(0);//設(shè)置當前接收區(qū)數(shù)據(jù)長度為0
m_ctrlcomm.get_Input();//預讀緩沖區(qū)以清空殘留數(shù)據(jù)
2,、實現(xiàn)發(fā)送按鈕,退出按鈕相應的響應函數(shù)

void CmscommDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
CDialogEx::OnOK();
UpdateData(1);//讀取編輯框內(nèi)容
m_ctrlcomm.put_Output(COleVariant(m_strsend));//發(fā)送數(shù)據(jù)
}




void CmscommDlg::OnBnClickedExit()
{
// TODO: Add your control notification handler code here
m_ctrlcomm.put_PortOpen(0);//關(guān)閉串口
CDialog::OnCancel();//退出程序
}
3,、實現(xiàn)MSComm控件相應的響應函數(shù)OnOnCommMsComm1()

VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048];//設(shè)置byte數(shù)組
CString strtemp;
if(m_ctrlcomm.get_CommEvent()==2)//事件2表示接受緩沖區(qū)有字符
{
variant_inp=m_ctrlcomm.get_Input();//讀緩沖區(qū)
safearray_inp=variant_inp;//variant數(shù)據(jù)轉(zhuǎn)換成colesafearray型變量
len=safearray_inp.GetOneDimSize();//得到有效數(shù)據(jù)長度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//轉(zhuǎn)換為byte型數(shù)組
for(k=0;k<len;k++){//將數(shù)組轉(zhuǎn)換成CString型變量
BYTE bt=*(char *)(rxdata+k);//字符型
strtemp.Format((char) bt);//將字符送入臨時變量strtemp存放
m_strreceive+=strtemp;//加入接收編輯框相應字符串
}
}
UpdateData(0);//更新編輯框內(nèi)容

4,、編譯運行程序

在調(diào)試運行時,必須兩臺機子同時運行此程序,,并且都要開啟同一個串口號

VS2010下MFC的串口編程

串口通信簡介

  一般來說,,計算機都有一個或多個串行端口,這些串口提供了外部設(shè)備與PC進行數(shù)據(jù)傳輸和通信的通道,,在CPU和外設(shè)之間充當解釋器的角色,。當字符數(shù)據(jù)從CPU發(fā)送給外設(shè)時,這些字符數(shù)據(jù)將被轉(zhuǎn)換成串行比特流數(shù)據(jù),;當接收數(shù)據(jù)時,,比特流數(shù)據(jù)被轉(zhuǎn)換為字符數(shù)據(jù)傳遞給CPU,再進一步說,,在操作系統(tǒng)方面,Windows用通信驅(qū)動程序(COMM.DRV)調(diào)用API函數(shù)發(fā)送和接收數(shù)據(jù),;當用通信控件或聲明調(diào)用API函數(shù)時,,它們由COMM.DRV解釋并傳遞給設(shè)備驅(qū)動程序。作為一個程序員,,要編寫通信程序,,只需知道通信控件提供的Windows API通信函數(shù)的接口即可,換句話說,,只需設(shè)定和監(jiān)視通信控件的屬性和事件即可,。

  串口通信方法一般有以下幾種:

  1. 利用Windows API通信函數(shù);
  2. 利用Visual C++的標準通信函數(shù)_inp,、_inpw,、_inpd、_outp,、_outpw,、_outpd等直接對串口進行操作;
  3. 通過微軟的串口通信控件MSComm,它是一種ActiveX控件,;
  4. 利用第3方編寫的通信類,,比如MuMega Technologies公司提供的CSerail類;

  我在項目開發(fā)過程中用的是第三種方法——通過MSComm控件操作串口,,下面是我使用此控件的筆記,。

MSComm控件簡介

  MSComm 是 Microsoft 公司為簡化Windows下串行端口編程而提供的ActiveX控件,它提供了一系列標準通訊命令的使用接口,。MSComm 控件通過串行端口(serial port)傳送和接收數(shù)據(jù),,為應用程序提供了串行通訊功能。在可視化編程盛行的今天,,我們可以很方便的在Visual Basic(VB),、Visual C++(VC)、Delphi等語言及開發(fā)平臺中應用,。處理數(shù)據(jù)的方式有事件驅(qū)動(Event-driver),、查詢法(Inquire)兩種。

  事件驅(qū)動法:在使用事件驅(qū)動法設(shè)計程序時,,每當有新字符到達,、端口狀態(tài)變化或發(fā)生錯誤時,MSComm控件將觸發(fā)OnComm事件,,而應用程序在捕獲該事件后,,通過檢查MSComm控件的CommEvent屬性可以獲知所發(fā)生的事件或錯誤,從而采取相應的操作,。這種方法的優(yōu)點是程序響應及時,,可靠性高。

  查詢法:這種方法適合于較小的應用程序,。在這種情況下,,每當應用程序執(zhí)行完某一串行口操作后,將不斷檢查MSComm控件的CommEvent屬性以檢查執(zhí)行結(jié)果或者檢查某一事件是否發(fā)生,。例如,,當程序向串行設(shè)備發(fā)送了某個命令后,可能只是在等待收到一個特定的響應字符串,,而不是對收到的每一個字符都立刻響應并處理,。

  使用的每個MSComm控件都與一個串口對應。如果在應用程序中需要訪問多個串口,,必須使用多個MSComm控件,,可以在Windows 控制面板中修改串口地址的中斷地址。

MSComm控件的常用屬性

  • CommPort屬性:設(shè)置或返回通訊端口號,,可以設(shè)置為1到16之間的任何值,;
  • Settings屬性:以字符串形式設(shè)置或返回波特率,、奇偶校驗、數(shù)據(jù)位和停止位;
  • PortOpen屬性:設(shè)置或返回通訊口的狀態(tài)以及打開和關(guān)閉端口,,可通過把該屬性設(shè)置為true或者false來打開或者關(guān)閉端口,;
  • InBufferSize和OutBufferSize屬性:分別設(shè)置接收和發(fā)送緩沖區(qū)分配的內(nèi)存數(shù)量,單位為字節(jié),,缺省值分別為1024byte和512byte,;
  • InputLen屬性:確定希望從接收緩沖區(qū)移出的字符數(shù)量,當InputLen=0時,,一次把接收緩沖區(qū)的字符全部移出,;
  • Input屬性:從接收緩沖區(qū)中讀出數(shù)據(jù),然后將該數(shù)據(jù)從緩沖區(qū)移走,。
  • OutPut屬性:向發(fā)送緩沖區(qū)傳遞待發(fā)送的數(shù)據(jù),。
  • InBufferCountOutBufferCount屬性:分別確定當前駐留在接收緩沖區(qū)等待被取出和發(fā)送緩沖區(qū)準備發(fā)送的字符數(shù)量,這兩個屬性設(shè)置為0,,接收和發(fā)送緩沖區(qū)的內(nèi)容將被清除,;
  • InputMode屬性:設(shè)置接收傳入數(shù)據(jù)的格式,設(shè)置為0采用文本形式,,設(shè)置為1采用二進制格式,;
  • SThreshold屬性:保存一個產(chǎn)生發(fā)送OnComm事件的界限值,本系統(tǒng)設(shè)置該屬性為0,,發(fā)送數(shù)據(jù)時不產(chǎn)生OnComm事件,;
  • RThreshold屬性:設(shè)定當接收幾個字符時觸發(fā)OnComm事件,本系統(tǒng)設(shè)置該屬性為1,,每接收一個字符就產(chǎn)生一個OnComm事件,;

MSComm控件的事件

  MSCOMM控件只使用一個事件OnComm,用屬性CommEvent的17個值來區(qū)分不同的觸發(fā)時機,,主要有以下幾個:

  • CommEvent=1時:傳輸緩沖區(qū)中的字符個數(shù)已少于Sthreshold(可設(shè)置的屬性值)個,;
  • CommEvent=2時:接收緩沖區(qū)中收到Rthreshold(可設(shè)置的屬性值)個字符,利用此事件可編寫接收數(shù)據(jù)的過程,;
  • CommEvent=3時:CTS線發(fā)生變化,;
  • CommEvent=4時:DSR線發(fā)生變化,;
  • CommEvent=5時:CD線發(fā)生變化,;
  • CommEvent=6時:檢測到振鈴信號;

  另外十種情況是通信錯誤時產(chǎn)生,,即錯誤代碼,。

基于VS2010下MFC的MSComm串口程序的實現(xiàn)

1、注冊MSComm控件

  我在網(wǎng)上下載了MSComm控件之后,,將其放于項目目錄下,,并在當前目錄建了個.bat批處理文件,,其內(nèi)容如下:

copy .\\MSCOMM\\MSCOMM.SRG %windir%\system32
copy .\\MSCOMM\\MSCOMM32.DEP %windir%\system32
copy .\\MSCOMM\\MSCOMM32.oca %windir%\system32
copy .\\MSCOMM\\mscomm32.ocx %windir%\system32

regsvr32 mscomm32.ocx

雙擊此文件,即可注冊MSComm控件,。

2,、添加MSComm控件

  首先將MSComm控件添加進VS2010工具箱,再給項目添加該ActiveX控件對應的“基于MFC的ATL類”,,最后將工具箱中的MSComm控件(電話圖標)拖至對話框即可,。在對話框中添加MSComm控件后,其側(cè)面會有白色,,右擊此控件,,選擇“編輯控件”,即可去除白色,。

3,、添加控件變量

  在主對話框中添加與MSComm控件相關(guān)聯(lián)的控件變量(成員對象),通過此成員變量可操作串口,。

4,、串口信息配置及打開串口

  在對話框模板上右擊MSComm控件,選擇Property菜單項,,即可設(shè)置MSComm控件各項屬性,。在調(diào)制解調(diào)器通訊的程序中,設(shè)置“Control”屬性頁中Handshaking項為“2-comRTS”,,否則國內(nèi)部分廠家modem不能正常通訊,,其它接受缺省設(shè)置。另外亦可通過修改對話框類的OnInitDialog()函數(shù)來設(shè)置控件的屬性,。具體參考MSDN中的關(guān)于Comm Control的詳細說明,。

  我程序的串口設(shè)置代碼大致如下:

    //*********************** 串口設(shè)置 **************************//
    m_ctrlComm.put_CommPort(port);//選擇com口
    m_ctrlComm.put_InputMode(1);//輸入方式為二進制方式
    m_ctrlComm.put_InBufferSize(1024);//輸入緩沖區(qū)大小為1024byte
    m_ctrlComm.put_OutBufferSize(512);//輸出緩沖區(qū)大小為512byte

    CString strBaudrate;
    strBaudrate.Format(_T("%ld"),baudrate);
    m_ctrlComm.put_Settings(strBaudrate+_T(",n,8,1"));//設(shè)置串口參數(shù):9600波特率,無奇偶校驗,,8個數(shù)據(jù)位,,1個停止位
    
    if(!m_ctrlComm.get_PortOpen())
    {
        /*
        HANDLE m_hCom;        
        CString strCom;  
        strCom.Format(_T("\\\\.\\COM%d"),(int)(m_ctrlComm.get__CommPort()));  
        // 這里的CreateFile函數(shù)起了很大的作用,可以用來創(chuàng)建系統(tǒng)設(shè)備文件,,
        //如果該設(shè)備不存在或者被占用,,則會返回一個錯誤,即下面的 INVALID_HANDLE_VALUE ,,
        //據(jù)此可以判斷可使用性,。詳細參見MSDN中的介紹。  
        m_hCom = CreateFile(strCom, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);  
        if(m_hCom == INVALID_HANDLE_VALUE)//如果沒有該設(shè)備,,或者被其他應用程序在用  
        {  
            int errornum=GetLastError();  
            if(errornum==2)  
                strCom.Format(_T("端口%d 不存在"),(int)(m_ctrlComm.get__CommPort()));  
            else if(errornum==5)  
                strCom.Format(_T("端口%d被占用"),(int)(m_ctrlComm.get__CommPort()));  
            AfxMessageBox(strCom);  
            CloseHandle(m_hCom); // 關(guān)閉文件句柄,,后面我們采用控件,不用API  
            return ;//這是因為串口初始化封裝在另一個函數(shù)里面在OnInitDialog調(diào)用,。  
        }  
        CloseHandle(m_hCom); // 關(guān)閉文件句柄,,后面我們采用控件,,不用API  
        */
        try
        {
            m_ctrlComm.put_PortOpen(true);//打開串口
        }
        catch(COleDispatchException *e)
        {
            CString strError;
            strError.Format(_T("打開串口失敗,!\n\nError Number: %d \nError Message: %s"),
                e->m_wCode,e->m_strDescription);
            MessageBoxW(strError,_T("錯誤提示"),MB_ICONERROR);
            return;
        }
    }
    else
    {
        //MessageBox(_T("Cannot open serial port!"));
    }

    m_ctrlComm.put_RThreshold(1);//每當串口接收緩沖區(qū)有多余或等于1個字符時將引發(fā)一個接收數(shù)據(jù)的oncomm事件
    m_ctrlComm.put_InputLen(0);//設(shè)置當前接收區(qū)數(shù)據(jù)長度為0
    m_ctrlComm.get_Input();//預讀緩沖區(qū)以清空殘留數(shù)據(jù)

5,、串口數(shù)據(jù)的讀寫

  MSComm 類的讀寫函數(shù)比較簡單:get_Input()put_Output()。函數(shù)原形分別為VARIANT get_Input()和void put_Output(const VARIANT newValue),均使用VARIANT類型,。但PC機發(fā)送和接收數(shù)據(jù)時習慣用字符串形式,。MSDN中查閱VARIANT類型,可以用BSTR表示字符串,,但所有的BSTR都包含寬字符,,而只有Windows NT支持寬字符,Windows 9X并不支持,。所以要完成一個適應各平臺的串口應用程序必須解決這個問題,,這里使用CByteArray解決之。

  添加接收數(shù)據(jù)函數(shù),,在對話框中雙擊Comm Control,,接受默認函數(shù),則對話框類的成員函數(shù)為OnCommMscomm(),,其大致代碼如下:

   CDataTypeConverter DTC;
    //電話圖標可能有一半白邊去不了,,右擊電話圖標點擊edit control就可以去掉
    if(m_ctrlComm.get_CommEvent()==2)//事件值為2表示接收事件
    {
        BYTE rxdata[255]={0};//設(shè)置BYTE數(shù)組
        VARIANT variant_inp=m_ctrlComm.get_Input();//讀緩沖區(qū)
        COleSafeArray safearray_inp = variant_inp;//VARIANT型變量轉(zhuǎn)換為COleSafeArray變量
        long len=safearray_inp.GetOneDimSize();//得到有效數(shù)據(jù)長度
        for(long k=0;k<len;k++)
            safearray_inp.GetElement(&k,rxdata+k);//轉(zhuǎn)換為BYTE數(shù)組
        m_ctrlComm.put_OutBufferCount(0);//清空發(fā)送緩沖區(qū)
        m_ctrlComm.put_InBufferCount(0);//滑空接收緩沖區(qū)
        safearray_inp.Clear();
            
        for(long k=0;k<len;k++)
        {
            BYTE bt = *(char*)(rxdata+k);//字符型
            short int intDec=(int)bt;
            CString strtemp=DTC.Dec2Hex(intDec);
            m_strDataRXTemp+=strtemp;//加入接收編輯框?qū)址?/span>
        }
        m_strDataRX=m_strDataRXTemp;
        m_strDataRXTemp="";
   }

其中,Dec2Hex()函數(shù)的代碼如下:

CString CDataTypeConverter::Dec2Hex(unsigned int intDec)
{
    CString strHex;
    char charHex[255];
    sprintf(charHex,"%x",intDec);
    strHex=charHex;
    if(strHex.GetLength()==1)
        strHex=_T("0")+strHex;
    return strHex;
}

  發(fā)送數(shù)據(jù)的代碼大致如下:

//UpdateData(true);//讀取編輯框內(nèi)容m_strDataTX

//發(fā)送的字符串上表面為十六進制格式
CString m_strCtrlLightBL;
m_strCtrlLightBL="55AA0AAA6B4310100000";//"55aa0aaa6b4310100000"
    
CDataTypeConverter DTC;
COleVariant m_OleVariant=DTC.HexM2OleVariant(m_strCtrlLightBL);

m_ctrlComm.put_Output(m_OleVariant);//發(fā)送數(shù)據(jù)

其中,,HexM2OleVariant()函數(shù)定義如下:

COleVariant CDataTypeConverter::HexM2OleVariant(CString strHexM)
{
    BYTE bt[255];
    short int len=strHexM.GetLength();
    short int length=0;
    short int intDec;
    for(int n=0,i=0;n<len-1;n+=2,i++)
    {        
        intDec=Hex2Dec(strHexM.Mid(n,2));
        bt[i]=char(intDec);
        length=i+1;
    }
    CByteArray m_Array;
    m_Array.RemoveAll();
    m_Array.SetSize(length);
    for(int i=0;i<length;i++)
        m_Array.SetAt(i,bt[i]);
    return COleVariant(m_Array);
}

注意:接收數(shù)據(jù)時,,RThreshold屬性很重要,因為它影響著OnComm事件的觸發(fā)條件,,在程序中可以通過put_RThreshold()函數(shù)來設(shè)定RThreshold屬性,。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多