VC串口通訊DLL_第1頁
VC串口通訊DLL_第2頁
VC串口通訊DLL_第3頁
VC串口通訊DLL_第4頁
VC串口通訊DLL_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、VC串口通訊DLL 串口在工業(yè)應(yīng)用是極為普遍的,我用API封裝了同步和異步的串口類,以及一個具有監(jiān)視線程的異步串口類;使用簡單高效,具有工業(yè)強(qiáng)度,我在BC, BCB, VC, BCBX, GCC下編譯通過,相信足夠應(yīng)付大多數(shù)情況,而且還可以繼承擴(kuò)展,下面簡單介紹使用方法 庫的層次結(jié)構(gòu): _base_com:虛基類,基本接口,可自行擴(kuò)展自己的串口類 _sync_com:_base_com 的子類, 同步應(yīng)用,適合簡單應(yīng)用 _asyn_com:_base_com 的子類, 異步應(yīng)用(重疊I/O),適合較高效應(yīng)用,NT平臺 _thread_com:_asyn_com 的子類, 異步應(yīng)用,監(jiān)視線程,適

2、合較復(fù)雜應(yīng)用,窗口通知消息和繼承擴(kuò)展的使用方式;幾個問題: 結(jié)束線程 如何從WaitCommEvent(pcom-_com_handle, &mask, &pcom-_wait_o)這個API退出以便順利結(jié)束線程: 方案1: SetCommMask(_com_handle, 0); 這個方法在MSDN有載,當(dāng)在一些情況下并不完全有效,原因未知; 方案2: SetEvent(_wait_o.hEvent); 直接激活重疊IO結(jié)構(gòu)中的事件句柄,絕對有效; 這份代碼我兩種都用; 打開10以上的COM端口 在NT/2000下打開編號10以上端口用 _com_handle = CreateFile( “

3、COM10“, GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, , /重疊I/O NULL );將提示錯誤, 這樣就OK:_com_handle = CreateFile( “.COM10“,/對應(yīng)的就是.COM10 GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, , /重疊I/O NULL ); 線程中循環(huán)的低效率問題 使用SetCommMask(pcom-_com_handle, EV_RXCHAR EV_ERR)監(jiān)視接受字符和錯誤消息;一旦有個字符來就會激活WaitCommEv

4、ent 通常作以下接受操作:if(!WaitCommEvent(pcom-_com_handle, &mask, &pcom-_wait_o) if(GetLastError() = ERROR_IO_PENDING) GetOverlappedResult(pcom-_com_handle, &pcom-_wait_o, &length, true); if(mask & EV_ERR) / = EV_ERR ClearCommError(pcom-_com_handle, &error, &stat); if(mask & EV_RXCHAR) / = EV_RXCHAR pcom-on_

5、receive();/接收到字符 /或發(fā)送到窗口消息 這樣頻繁的函數(shù)調(diào)用或接受發(fā)送消息,效率低下,我添加掃描緩沖區(qū)的代碼,當(dāng)字符數(shù)超過設(shè)定的字符數(shù)才作接受字符的操作;if(mask & EV_RXCHAR) / = EV_RXCHAR ClearCommError(pcom-_com_handle, &error, &stat); if(stat.cbInQue pcom-_notify_num) /_notify_num 是設(shè)定得字符數(shù) pcom-on_receive(); 類似于流的輸出方式我編了一個簡單的寫串口的方式,可以類似于流將簡單的數(shù)據(jù)類型輸出template _asyn_com&

6、 operator (T x) strstream s; s x ; write(s.str(), s.pcount(); return *this;就可以這樣使用_sync_com com1;com1.open(1, 9600);com1 “ then random() s return value is “ rand() “ .n“ ;com1.close();本串口類庫的主要接口class _base_com bool open(int port); bool open(int port, int baud_rate); bool open(int port, char * set_st

7、r); / set_str : “9600, 8, n, 1“ bool set_state(int BaudRate, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT) /設(shè)置內(nèi)置結(jié)構(gòu)串口參數(shù):波特率,停止位 bool set_state(char *set_str) bool is_open(); HANDLE get_handle(); virtual bool open_port()=0; /繼承用的重要函數(shù) virtual close();class _sync_com :public _base_

8、com /同步 int read(char *buf, int buf_size); /自動補(bǔ)上0,將用去一個字符的緩沖區(qū) int write(char *buf, int len); int write(char *buf);class _asyn_com :public _base_com /異步 int read(char *buf, int buf_size); /自動補(bǔ)上0,將用去一個字符的緩沖區(qū) int write(char *buf, int len); int write(char *buf);class _thread_com :public _asyn_com /線程 vi

9、rtual void on_receive() /供線程接受到字符時調(diào)用, 可繼承替換之 if(_notify_hwnd) PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0); else if(_func) _func(_port); void set_hwnd(HWND hwnd); /設(shè)置窗口句柄, 發(fā)送 ON_COM_RECEIVE WM_USER + 618 void set_func(void (*f)(int); /設(shè)置調(diào)用函數(shù) ,窗口句柄優(yōu)先 void set_notify_num(int num)

10、; /設(shè)定發(fā)送通知, 接受字符最小值一些應(yīng)用范例 當(dāng)然首先 #include _com.h 一、打開串口1同步寫 char str = com_class test; _sync_com com1; /同步 com1.open(1); / 相當(dāng)于 com1.open(1, 9600); com1.open(1, 9600,8,n,1); for(int i=0; i100; i+) Sleep(500); com1.write(str); /也可以 com1.write(str, strlen(str); com1.close(); 二、打開串口2異步讀 char str100; _asyn_

11、com com2; /異步 com2.open(2); / 相當(dāng)于 com2.open(2, 9600); com2.open(2, 9600,8,n,1); if(!com2.is_open() cout COM2 not open , error : GetLastError() endl; /* 也可以如下用法 if(!com2.open(2) cout COM2 not open , error : GetLastError() endl; */ for(int i=0; i 0) /異步讀,返回讀取字符數(shù) cout 0) /異步讀,返回讀取字符數(shù) cout str; ; int ma

12、in(int argc, char *argv) try char str100; _com_ex com2; /異步擴(kuò)展 com2.open(2); Sleep(10000); com2.close(); catch(exception &e) cout e.what() m_hWnd); 處理消息 LRESULT ComDlg:On_Receive(WPARAM wp, LPARAM lp) char str100; com2.read(str, 100); char com_str10; strcpy(com_str, COM); ltoa(long)wp, com_str + 3, 1

13、0); / WPARAM 保存端口號 MessageBox(str, com_str, MB_OK); return 0; C+ Builder class TForm1 : public TForm _published: / IDE-managed Components void _fastcall FormClose(TObject *Sender, TCloseAction &Action); void _fastcall FormCreate(TObject *Sender); private: / User declarations public: / User declarati

14、ons void On_Receive(TMessage& Message); _fastcall TForm1(TComponent* Owner); _thread_com com2; BEGIN_MESSAGE_MAP MESSAGE_HANDLER(ON_COM_RECEIVE, TMessage, On_Receive) END_MESSAGE_MAP(TForm) ; void _fastcall TForm1:FormClose(TObject *Sender, TCloseAction &Action) com2.close(); /- void _fastcall TForm

15、1:FormCreate(TObject *Sender) com2.open(2); com2.set_hwnd(Handle); /- void TForm1:On_Receive(TMessage& Message) char xx20; int port = Message.WParam; if(com2.read(xx, 20) 0) ShowMessage(xx); 錯誤和缺陷在所難免,歡迎來信批評指正; 附完整源代碼 _com.h/*串口基礎(chǔ)類庫(WIN32) ver 0.1編譯器 : BC+ 5; C+ BUILDER 4, 5, 6, X; VC+ 5, 6; VC.NET;

16、 GCC;class _base_com : 虛基類 基本串口接口;class _sync_com : 同步I/O 串口類;class _asyn_com : 異步I/O 串口類;class _thread_com : 異步I/O 輔助讀監(jiān)視線程 可轉(zhuǎn)發(fā)窗口消息 串口類(可繼承虛函數(shù)on_receive用于讀操作);class _com : _thread_com 同名copyright(c) 2004.8 llbird */*Example :*/#ifndef _COM_H_#define _COM_H_#pragma warning(disable: 4530)#pragma warni

17、ng(disable: 4786)#pragma warning(disable: 4800)#include #include #include #include #include using namespace std;#include class _base_com /虛基類 基本串口接口protected: volatile int _port; /串口號 volatile HANDLE _com_handle;/串口句柄 char _com_str20; DCB _dcb; /波特率,停止位,等 COMMTIMEOUTS _co; / 超時時間 virtual bool open_p

18、ort() = 0; void init() /初始化 memset(_com_str, 0, 20); memset(&_co, 0, sizeof(_co); memset(&_dcb, 0, sizeof(_dcb); _dcb.DCBlength = sizeof(_dcb); _com_handle = INVALID_HANDLE_VALUE; virtual bool setup_port() if(!is_open() return false; if(!SetupComm(_com_handle, 8192, 8192) return false; /設(shè)置推薦緩沖區(qū) if(!

19、GetCommTimeouts(_com_handle, &_co) return false; _co.ReadIntervalTimeout = 0xFFFFFFFF; _co.ReadTotalTimeoutMultiplier = 0; _co.ReadTotalTimeoutConstant = 0; _co.WriteTotalTimeoutMultiplier = 0; _co.WriteTotalTimeoutConstant = 2000; if(!SetCommTimeouts(_com_handle, &_co) return false; /設(shè)置超時時間 if(!Pur

20、geComm(_com_handle, PURGE_TXABORT PURGE_RXABORT PURGE_TXCLEAR PURGE_RXCLEAR ) return false; /清空串口緩沖區(qū) return true; inline void set_com_port(int port) char p12; _port = port; strcpy(_com_str, .COM); ltoa(_port, p, 10); strcat(_com_str, p); public: _base_com() init(); virtual _base_com() close(); /設(shè)置串口

21、參數(shù):波特率,停止位,等 支持設(shè)置字符串 9600, 8, n, 1 bool set_state(char *set_str) if(is_open() if(!GetCommState(_com_handle, &_dcb) return false; if(!BuildCommDCB(set_str, &_dcb) return false; return SetCommState(_com_handle, &_dcb) = TRUE; return false; /設(shè)置內(nèi)置結(jié)構(gòu)串口參數(shù):波特率,停止位 bool set_state(int BaudRate, int ByteSize

22、= 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT) if(is_open() if(!GetCommState(_com_handle, &_dcb) return false; _dcb.BaudRate = BaudRate; _dcb.ByteSize = ByteSize; _dcb.Parity = Parity; _dcb.StopBits = StopBits; return SetCommState(_com_handle, &_dcb) = TRUE; return false; /打開串口 缺省 9600, 8, n

23、, 1 inline bool open(int port) return open(port, 9600); /打開串口 缺省 baud_rate, 8, n, 1 inline bool open(int port, int baud_rate) if(port 1024) return false; set_com_port(port); if(!open_port() return false; if(!setup_port() return false; return set_state(baud_rate); /打開串口 inline bool open(int port, cha

24、r *set_str) if(port 1024) return false; set_com_port(port); if(!open_port() return false; if(!setup_port() return false; return set_state(set_str); inline bool set_buf(int in, int out) return is_open() ? SetupComm(_com_handle, in, out) : false; /關(guān)閉串口 inline virtual void close() if(is_open() CloseHan

25、dle(_com_handle); _com_handle = INVALID_HANDLE_VALUE; /判斷串口是或打開 inline bool is_open() return _com_handle != INVALID_HANDLE_VALUE; /獲得串口句炳 HANDLE get_handle() return _com_handle; operator HANDLE() return _com_handle; ;class _sync_com : public _base_comprotected: /打開串口 virtual bool open_port() if(is_o

26、pen() close(); _com_handle = CreateFile( _com_str, GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, , NULL ); assert(is_open(); return is_open();/檢測串口是否成功打開 public: _sync_com() /同步讀 int read(char *buf, int buf_len) if(!is_open() return 0; buf0 = 0; COMSTAT stat; DWORD error; if(ClearCommError(_co

27、m_handle, &error, &stat) & error 0) /清除錯誤 PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除輸入緩沖區(qū)*/ return 0; unsigned long r_len = 0; buf_len = min(buf_len - 1, (int)stat.cbInQue); if(!Read, buf, buf_len, &r_len, NULL) r_len = 0; bufr_len = 0; return r_len; /同步寫 int write(char *buf, int buf_

28、len) if(!is_open() !buf) return 0; DWORD error; if(ClearCommError(_com_handle, &error, NULL) & error 0) /清除錯誤 PurgeComm(_com_handle, PURGE_TXABORT PURGE_TXCLEAR); unsigned long w_len = 0; if(!Write, buf, buf_len, &w_len, NULL) w_len = 0; return w_len; /同步寫 inline int write(char *buf) assert(buf); re

29、turn write(buf, strlen(buf); /同步寫, 支持部分類型的流輸出 template _sync_com& operator (T x) strstream s; s 0) /清除錯誤 PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除輸入緩沖區(qū)*/ return 0; if(!stat.cbInQue)/ 緩沖區(qū)無數(shù)據(jù) return 0; unsigned long r_len = 0; buf_len = min(int)(buf_len - 1), (int)stat.cbInQue); if(!Re

30、ad, buf, buf_len, &r_len, &_ro) /2000 下 ReadFile 始終返回 True if(GetLastError() = ERROR_IO_PENDING) / 結(jié)束異步I/O /WaitForSingleObject(_ro.hEvent, time_wait); /等待20ms if(!GetOverlappedResult(_com_handle, &_ro, &r_len, false) if(GetLastError() != ERROR_IO_INCOMPLETE)/其他錯誤 r_len = 0; else r_len = 0; bufr_len

31、 = 0; return r_len; /異步寫 int write(char *buf, int buf_len) if(!is_open() return 0; DWORD error; if(ClearCommError(_com_handle, &error, NULL) & error 0) /清除錯誤 PurgeComm(_com_handle, PURGE_TXABORT PURGE_TXCLEAR); unsigned long w_len = 0, o_len = 0; if(!Write, buf, buf_len, &w_len, &_wo) if(GetLastErro

32、r() != ERROR_IO_PENDING) w_len = 0; return w_len; /異步寫 inline int write(char *buf) assert(buf); return write(buf, strlen(buf); /異步寫, 支持部分類型的流輸出 template _asyn_com& operator (T x) strstream s; s _notify_num)發(fā)送通知消息 volatile bool _run_flag; /線程運(yùn)行循環(huán)標(biāo)志 void (*_func)(int port); OVERLAPPED _wait_o; /WaitCo

33、mmEvent use /線程收到消息自動調(diào)用, 如窗口句柄有效, 送出消息, 包含窗口編號 virtual void on_receive() if(_notify_hwnd) PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0); else if(_func) _func(_port); /打開串口,同時打開監(jiān)視線程 virtual bool open_port() if(_asyn_com:open_port() _run_flag = true; DWORD id; _thread_handle = Cre

34、ateThread(NULL, 0, com_thread, this, 0, &id); /輔助線程 assert(_thread_handle); if(!_thread_handle) CloseHandle(_com_handle); _com_handle = INVALID_HANDLE_VALUE; else return true; return false; public: _thread_com() _notify_num = 0; _notify_hwnd = NULL; _thread_handle = NULL; _func = NULL; memset(&_wait

35、_o, 0, sizeof(_wait_o); _wait_o.hEvent = CreateEvent(NULL, true, false, NULL); assert(_wait_o.hEvent != INVALID_HANDLE_VALUE); _thread_com() close(); if(_wait_o.hEvent != INVALID_HANDLE_VALUE) CloseHandle(_wait_o.hEvent); /設(shè)定發(fā)送通知, 接受字符最小值 void set_notify_num(int num) _notify_num = num; int get_notif

36、y_num() return _notify_num; /送消息的窗口句柄 inline void set_hwnd(HWND hWnd) _notify_hwnd = hWnd; inline HWND get_hwnd() return _notify_hwnd; inline void set_func(void (*f)(int) _func = f; /關(guān)閉線程及串口 virtual void close() if(is_open() _run_flag = false; SetCommMask(_com_handle, 0); SetEvent(_wait_o.hEvent); i

37、f(WaitForSingleObject(_thread_handle, 100) != WAIT_OBJECT_0) TerminateThread(_thread_handle, 0); CloseHandle(_com_handle); CloseHandle(_thread_handle); _thread_handle = NULL; _com_handle = INVALID_HANDLE_VALUE; ResetEvent(_wait_o.hEvent); /*輔助線程控制*/ /獲得線程句柄 HANDLE get_thread() return _thread_handle; /暫停監(jiān)視線程 bool suspend() return _thread_handle != NULL ? SuspendThread(_thread_handle) != 0xFFFFF

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論