VC串列埠程式設計的例項2
阿新 • • 發佈:2019-02-13
本例程採用非同步串列埠操作,我們只介紹軟體部分,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();
}