vc串口通信編程
❶ 如何在vc6.0中為實現串口通信
首先創建一個VC6.0基於對話框的程序,然後在資源視圖中,Project --- > Add To Project ---> compoents and controls...,如下圖所示
在彈出的窗口選擇「Registered ActiveX Controls」,雙擊進入該文件夾,如下圖所示
在列表中找到「Microsoft Communications Control, version 6.0」,點擊「Insert」按鈕,如下圖所示
接下來就會在資源視圖中看到一個電話圖標,如下圖所示
右鍵該電話圖標,選擇「ClassWizard...」,如下圖所示
在Member Variables下為該控制項添加一個控制項變數,如下圖所示
在Message Maps下為該控制項添加OnComm消息,如下圖所示
在OnInitDialog()函數中,加入窗口控制項初始化函數,如下圖所示
在OnComm() 函數中,加入串口消息處理函數,處理串口接收的數據,如下圖所示
❷ VC編寫的串口通信程序
這東西自己網路一下 「VC 串口通信 原碼」 就有了。
另一方法:到你附近的書店裡買本關於 VC 串口通信 類的書,帶光碟的,裡面就有了。
❸ 使用C/C++在VC6下編寫簡單串口通信程序
http://hi..com/yiweisky99/blog/item/4f57cbf52d092729720eecba.html
❹ 怎樣用VC++實現串口通信編程(怎樣快速學會)
推薦 入門書 看看
Visual C++_Turbo C串口通信編程實踐
需要 pdf 電子文檔 可以 聯系
❺ RS422串口通信VC編程問題
盡量不要用MSComm,裡面很多東西工控上都不穩定。
VC直接用 CreateFile("\\\\.\\com12"..)打開串口,用SetCommState進行串口設置,再用WriteFile和ReadFile讀寫即可,非常簡單,少繞一個大彎子,因為MSComm本身就是用CreateFile/ReadFile/WriteFile寫的
❻ 如何用VC進行串口編程
1、新建MFC對話框工程如下
雙擊兩個Button按鈕;
代碼中顯示如下:
[cpp] view plain print?
voidCMSCommTestDlg::OnBnClickedBtnopen()
{
//TODO:
}
voidCMSCommTestDlg::OnBnClickedBtnsend()
{
//TODO:
}
voidCMSCommTestDlg::OnOncommMscomm1()
{
//TODO:Addyourmessagehandlercodehere
}
- void CMSCommTestDlg::OnBnClickedBtnopen()
- {
- // TODO: Add your control notification handler code here
- }
- void CMSCommTestDlg::OnBnClickedBtnsend()
- {
- // TODO: Add your control notification handler code here
- }
- void CMSCommTestDlg::OnOncommMscomm1()
- {
- // TODO: Add your message handler code here
- }
voidCMSCommTestDlg::OnClickedBtnopen()
{
//TODO:
//如果埠已經開啟,那麼先關閉
if(m_comm1.get_PortOpen())
{
m_comm1.put_PortOpen(FALSE);
}
m_comm1.put_CommPort(3);//選擇com3,可以根據具體情況更改
m_comm1.put_InBufferSize(1024);//設置輸入緩沖區的大小,Bytes
m_comm1.put_OutBufferSize(1024);//設置輸出緩沖區的大小,Bytes
m_comm1.put_Settings(_T("9600,n,8,1"));//波特率9600,無校驗,8個數據位,停止位1
m_comm1.put_InputMode(1);//1:表示以二進制方式檢索數據
m_comm1.put_RThreshold(1);//參數1表示每當串口接收緩沖區中有多於或等於1個字元時將引發一個接收數據的OnComm事件
m_comm1.put_InputLen(0);//設置當前接收區長度是0
if(!m_comm1.get_PortOpen())
{
m_comm1.put_PortOpen(TRUE);
}
else
{
AfxMessageBox(_T("Cannotopenserialport!"));
}
m_comm1.get_Input();//先預讀緩沖區以清除殘留數據
UpdateData(FALSE);
}
voidCMSCommTestDlg::OnClickedBtnsend()
{
//TODO:
UpdateData(TRUE);
m_comm1.put_Output(COleVariant(m_sTXDATA));//發送數據
}
voidCMSCommTestDlg::OnOncommMscomm1()
{
//TODO:Addyourmessagehandlercodehere
VARIANTvariant_inp;
COleSafeArraysafearray_inp;
LONGlen,k;
BYTErxdata[2048];
CStringstrtemp;
if(m_comm1.get_CommEvent()==2)//事件值為2表示緩沖區內有字元
{
variant_inp=m_comm1.get_Input();//讀緩沖區
safearray_inp=variant_inp;//VARIANT型變數轉換為ColeSafeArray型變數
len=safearray_inp.GetDim();//得到有效數據長度
for(k=0;k<len;k++)
{
safearray_inp.GetElement(&k,rxdata+k);//轉換為BYTE型數組
}
for(k=0;k<len;k++)//將數組轉換為CString型變數
{
BYTEbt=*(char*)(rxdata+k);//字元型
strtemp.Format(_T("%c"),bt);//將字元送入臨時變數strtemp存放
m_sRXDATA+=strtemp;//接收到的數據放到編輯框對應的變數中
}
}
SetDlgItemText(IDC_EDIT_RXDATA,m_sRXDATA);
}
5、將上面代碼補全如下:
[cpp] view plain print?
❼ VC串口通信問題
串口的操作可以有兩種操作方式:同步操作方式和重疊操作方式(又稱為非同步操作方式)。同步操作時,API函數會阻塞直到操作完成以後才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監聽線程);而重疊操作方式,API函數會立即返回,操作在後台進行,避免線程的阻塞。
無論那種操作方式,一般都通過四個步驟來完成:
(1) 打開串口
(2) 配置串口
(3) 讀寫串口
(4) 關閉串口
(1) 打開串口
Win32系統把文件的概念進行了擴展。無論是文件、通信設備、命名管道、郵件槽、磁碟、還是控制台,都是用API函數CreateFile來打開或創建的。該函數的原型為:
lpFileName:將要打開的串口邏輯名,如「COM1」;
dwDesiredAccess:指定串口訪問的類型,可以是讀取、寫入或二者並列;
dwShareMode:指定共享屬性,由於串口不能共享,該參數必須置為0;
lpSecurityAttributes:引用安全性屬性結構,預設值為NULL;
dwCreationDistribution:創建標志,對串口操作該參數必須置為OPEN_EXISTING;
dwFlagsAndAttributes:屬性描述,用於指定該串口是否進行非同步操作,該值為FILE_FLAG_OVERLAPPED,表示使用非同步的I/O;該值為0,表示同步I/O操作;
hTemplateFile:對串口而言該參數必須置為NULL;
同步I/O方式打開串口的示例代碼:
HANDLE hCom; //全局變數,串口句柄
hCom=CreateFile("COM1",//COM1口
GENERIC_READ|GENERIC_WRITE, //允許讀和寫
0, //獨占方式
NULL,
OPEN_EXISTING, //打開而不是創建
0, //同步方式
NULL);
if(hCom==(HANDLE)-1)
{
AfxMessageBox("打開COM失敗!");
return FALSE;
}
return TRUE;
(2)、配置串口
在打開通訊設備句柄後,常常需要對串口進行一些初始化配置工作。這需要通過一個DCB結構來進行。DCB結構包含了諸如波特率、數據位數、奇偶校驗和停止位數等信息。在查詢或配置串口的屬性時,都要用DCB結構來作為緩沖區。
一般用CreateFile打開串口後,可以調用GetCommState函數來獲取串口的初始配置。要修改串口的配置,應該先修改DCB結構,然後再調用SetCommState函數設置串口。
typedef struct _DCB{
………
//波特率,指定通信設備的傳輸速率。這個成員可以是實際波特率值或者下面的常量值之一:
DWORD BaudRate;
CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, CBR_38400,
CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000, CBR_14400
DWORD fParity; // 指定奇偶校驗使能。若此成員為1,允許奇偶校驗檢查
…
BYTE ByteSize; // 通信位元組位數,4—8
BYTE Parity; //指定奇偶校驗方法。此成員可以有下列值:
EVENPARITY 偶校驗 NOPARITY 無校驗
MARKPARITY 標記校驗 ODDPARITY 奇校驗
BYTE StopBits; //指定停止位的位數。此成員可以有下列值:
ONESTOPBIT 1位停止位 TWOSTOPBITS 2位停止位
ONE5STOPBITS 1.5位停止位
………
} DCB;
winbase.h文件中定義了以上用到的常量。如下:
#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define ONESTOPBIT 0
#define ONE5STOPBITS 1
#define TWOSTOPBITS 2
#define CBR_110 110
#define CBR_300 300
#define CBR_600 600
#define CBR_1200 1200
#define CBR_2400 2400
#define CBR_4800 4800
#define CBR_9600 9600
#define CBR_14400 14400
#define CBR_19200 19200
#define CBR_38400 38400
#define CBR_56000 56000
#define CBR_57600 57600
#define CBR_115200 115200
#define CBR_128000 128000
#define CBR_256000 256000
GetCommState函數可以獲得COM口的設備控制塊,從而獲得相關參數: BOOL GetCommState(
HANDLE hFile, //標識通訊埠的句柄
LPDCB lpDCB //指向一個設備控制塊(DCB結構)的指針
);
SetCommState函數設置COM口的設備控制塊:
BOOL SetCommState(
HANDLE hFile,
LPDCB lpDCB
);
除了在BCD中的設置外,程序一般還需要設置I/O緩沖區的大小和超時。Windows用I/O緩沖區來暫存串口輸入和輸出的數據。如果通信的速率較高,則應該設置較大的緩沖區。調用SetupComm函數可以設置串列口的輸入和輸出緩沖區的大小。 BOOL SetupComm(
HANDLE hFile, // 通信設備的句柄
DWORD dwInQueue, // 輸入緩沖區的大小(位元組數)
DWORD dwOutQueue // 輸出緩沖區的大小(位元組數)
);
在用ReadFile和WriteFile讀寫串列口時,需要考慮超時問題。超時的作用是在指定的時間內沒有讀入或發送指定數量的字元,ReadFile或WriteFile的操作仍然會結束。
要查詢當前的超時設置應調用GetCommTimeouts函數,該函數會填充一個COMMTIMEOUTS結構。調用SetCommTimeouts可以用某一個COMMTIMEOUTS結構的內容來設置超時。
讀寫串口的超時有兩種:間隔超時和總超時。間隔超時是指在接收時兩個字元之間的最大時延。總超時是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時均支持。用COMMTIMEOUTS結構可以規定讀寫操作的超時。
COMMTIMEOUTS結構的定義為: typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; //讀間隔超時
DWORD ReadTotalTimeoutMultiplier; //讀時間系數
DWORD ReadTotalTimeoutConstant; //讀時間常量
DWORD WriteTotalTimeoutMultiplier; // 寫時間系數
DWORD WriteTotalTimeoutConstant; //寫時間常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
COMMTIMEOUTS結構的成員都以毫秒為單位。總超時的計算公式是:
總超時=時間系數×要求讀/寫的字元數+時間常量
例如,要讀入10個字元,那麼讀操作的總超時的計算公式為:
讀總超時=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant
可以看出:間隔超時和總超時的設置是不相關的,這可以方便通信程序靈活地設置各種超時。
如果所有寫超時參數均為0,那麼就不使用寫超時。如果ReadIntervalTimeout為0,那麼就不使用讀間隔超時。如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都為0,則不使用讀總超時。如果讀間隔超時被設置成MAXDWORD並且讀時間系數和讀時間常量都為0,那麼在讀一次輸入緩沖區的內容後讀操作就立即返回,而不管是否讀入了要求的字元。
在用重疊方式讀寫串口時,雖然ReadFile和WriteFile在完成操作以前就可能返回,但超時仍然是起作用的。在這種情況下,超時規定的是操作的完成時間,而不是ReadFile和WriteFile的返回時間。
配置串口的示例代碼: SetupComm(hCom,1024,1024); //輸入緩沖區和輸出緩沖區的大小都是1024
COMMTIMEOUTS TimeOuts;
//設定讀超時
TimeOuts.ReadIntervalTimeout=1000;
TimeOuts.ReadTotalTimeoutMultiplier=500;
TimeOuts.ReadTotalTimeoutConstant=5000;
//設定寫超時
TimeOuts.WriteTotalTimeoutMultiplier=500;
TimeOuts.WriteTotalTimeoutConstant=2000;
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);
在讀寫串口之前,還要用PurgeComm()函數清空緩沖區,該函數原型: BOOL PurgeComm(
HANDLE hFile, //串口句柄
DWORD dwFlags // 需要完成的操作
);
參數dwFlags指定要完成的操作,可以是下列值的組合: PURGE_TXABORT 中斷所有寫操作並立即返回,即使寫操作還沒有完成。
PURGE_RXABORT 中斷所有讀操作並立即返回,即使讀操作還沒有完成。
PURGE_TXCLEAR 清除輸出緩沖區
PURGE_RXCLEAR 清除輸入緩沖區
(3)、讀寫串口
我們使用ReadFile和WriteFile讀寫串口,下面是兩個函數的聲明:
BOOL ReadFile(
HANDLE hFile, //串口的句柄
// 讀入的數據存儲的地址,
// 即讀入的數據將存儲在以該指針的值為首地址的一片內存區
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead, // 要讀入的數據的位元組數
// 指向一個DWORD數值,該數值返回讀操作實際讀入的位元組數
LPDWORD lpNumberOfBytesRead,
// 重疊操作時,該參數指向一個OVERLAPPED結構,同步操作時,該參數為NULL。
LPOVERLAPPED lpOverlapped
);
BOOL WriteFile(
HANDLE hFile, //串口的句柄
// 寫入的數據存儲的地址,
// 即以該指針的值為首地址的nNumberOfBytesToWrite
// 個位元組的數據將要寫入串口的發送數據緩沖區。
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite, //要寫入的數據的位元組數
// 指向指向一個DWORD數值,該數值返回實際寫入的位元組數
LPDWORD lpNumberOfBytesWritten,
// 重疊操作時,該參數指向一個OVERLAPPED結構,
// 同步操作時,該參數為NULL。
LPOVERLAPPED lpOverlapped
);
在用ReadFile和WriteFile讀寫串口時,既可以同步執行,也可以重疊執行。在同步執行時,函數直到操作完成後才返回。這意味著同步執行時線程會被阻塞,從而導致效率下降。在重疊執行時,即使操作還未完成,這兩個函數也會立即返回,費時的I/O操作在後台進行。
ReadFile和WriteFile函數是同步還是非同步由CreateFile函數決定,如果在調用CreateFile創建句柄時指定了FILE_FLAG_OVERLAPPED標志,那麼調用ReadFile和WriteFile對該句柄進行的操作就應該是重疊的;如果未指定重疊標志,則讀寫操作應該是同步的。ReadFile和WriteFile函數的同步或者非同步應該和CreateFile函數相一致。
ReadFile函數只要在串口輸入緩沖區中讀入指定數量的字元,就算完成操作。而WriteFile函數不但要把指定數量的字元拷入到輸出緩沖區,而且要等這些字元從串列口送出去後才算完成操作。
如果操作成功,這兩個函數都返回TRUE。需要注意的是,當ReadFile和WriteFile返回FALSE時,不一定就是操作失敗,線程應該調用GetLastError函數分析返回的結果。例如,在重疊操作時如果操作還未完成函數就返回,那麼函數就返回FALSE,而且GetLastError函數返回ERROR_IO_PENDING。這說明重疊操作還未完成。
您可以觀察返回的字元串,其中有和儀表顯示值相同的部分,您可以進行相應的字元串操作取出儀表的顯示值。
打開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();
}
程序的相應部分已經在代碼內部作了詳細介紹。連接好硬體部分,編譯運行程序,細心體會串口同步操作部分。
常式2
打開VC++6.0,新建基於對話框的工程RS485Comm,在主對話框窗口IDD_RS485COMM_DIALOG上添加兩個按鈕,ID分別為IDC_SEND和IDC_RECEIVE,標題分別為「發送」和「接收」;添加一個靜態文本框IDC_DISP,用於顯示串口接收到的內容。在RS485CommDlg.cpp文件中添加全局變數:
HANDLE hCom; //全局變數,
串口句柄在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);
分別雙擊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);
}
打開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();
}
這是我看過的一個資料。打開、設置和讀寫串口的方法都說的很詳細了。由於網路知道回答問題是有長度限制的。有些例子被我刪了。如果需要就加我QQ。給你發信息了。