1. 程式人生 > >VC串列埠程式設計的例項2

VC串列埠程式設計的例項2

  本例程採用非同步串列埠操作,我們只介紹軟體部分,RS485介面接線方法不作介紹,感興趣的讀者可以查閱相關資料。
  開啟VC++6.0,新建基於對話方塊的工程RS485Comm,在主對話方塊視窗IDD_RS485COMM_DIALOG上新增兩個按鈕,ID分別為IDC_SEND和IDC_RECEIVE,標題分別為“傳送”和“接收”;新增一個靜態文字框IDC_DISP,用於顯示串列埠接收到的內容。

1. 新增串列埠的全域性變數

在RS485CommDlg.cpp檔案中新增全域性變數:

HANDLE hCom; //全域性變數

2. 初始化串列埠引數

  串列埠控制代碼在RS485CommDlg.cpp檔案中的OnInitDialog()函式新增如下程式碼:

hCom=CreateFile("COM1",//COM1口
    GENERIC_READ|GENERIC_WRITE, //允許讀和寫
    0, //獨佔方式
    NULL,
    OPEN_EXISTING, //開啟而不是建立
    FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重疊方式
    NULL);
if(hCom==(HANDLE)-1)
{
    AfxMessageBox("開啟COM失敗!");
    return FALSE;
}

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=9600; //波特率為9600 dcb.ByteSize=8; //每個位元組有8位 dcb.Parity=NOPARITY; //無奇偶校驗位 dcb.StopBits=TWOSTOPBITS; //兩個停止位 SetCommState(hCom,&dcb); PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);

3.添加發送和接收函式

  分別雙擊IDC_SEND按鈕和IDC_RECEIVE按鈕,新增兩個按鈕的響應函式:

//向串列埠寫入資料
void CRS485CommDlg::OnSend() 
{
    // TODO: Add your control notification handler code here
    OVERLAPPED m_osWrite;
    memset(&m_osWrite,0,sizeof(OVERLAPPED));
    m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

    char lpOutBuffer[7];
    memset(lpOutBuffer,''\0'',7);
    lpOutBuffer[0]=''\x11'';
    lpOutBuffer[1]=''0'';
    lpOutBuffer[2]=''0'';
    lpOutBuffer[3]=''1'';
    lpOutBuffer[4]=''0'';
    lpOutBuffer[5]=''1'';
    lpOutBuffer[6]=''\x03'';

    DWORD dwBytesWrite=7;
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    BOOL bWriteStat;
    ClearCommError(hCom,&dwErrorFlags,&ComStat);
    bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,&m_osWrite);

    if(!bWriteStat)
    {
        if(GetLastError()==ERROR_IO_PENDING)
        {
            WaitForSingleObject(m_osWrite.hEvent,1000);
        }
    }
}

//接受串列埠資訊
void CRS485CommDlg::OnReceive() 
{
    // TODO: Add your control notification handler code here
    OVERLAPPED m_osRead;
    memset(&m_osRead,0,sizeof(OVERLAPPED));
    m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

    COMSTAT ComStat;
    DWORD dwErrorFlags;

    char str[100];
    memset(str,''\0'',100);
    DWORD dwBytesRead=100;//讀取的位元組數
    BOOL bReadStat;

    ClearCommError(hCom,&dwErrorFlags,&ComStat);
    dwBytesRead=min(dwBytesRead, (DWORD)ComStat.cbInQue);
    bReadStat=ReadFile(hCom,str,dwBytesRead,&dwBytesRead,&m_osRead);
    if(!bReadStat)
    {
        if(GetLastError()==ERROR_IO_PENDING)//GetLastError()函式返回ERROR_IO_PENDING,表明串列埠正在進行讀操作
        {
            WaitForSingleObject(m_osRead.hEvent,2000);
            //使用WaitForSingleObject函式等待,直到讀操作完成或延時已達到2秒鐘
            //當串列埠讀操作進行完畢後,m_osRead的hEvent事件會變為有訊號
        }
    }

    PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
    m_disp=str;
    UpdateData(FALSE);
}

4. 關閉串列埠

  開啟ClassWizard,為靜態文字框IDC_DISP新增CString型別變數m_disp,同時新增WM_CLOSE的相應函式:

void CRS485CommDlg::OnClose() 
{
// TODO: Add your message handler code here and/or call default
    CloseHandle(hCom); //程式退出時關閉串列埠
    CDialog::OnClose();
}