




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年石英纖維及制品項(xiàng)目建議書
- 高效節(jié)能電機(jī)項(xiàng)目規(guī)劃設(shè)計方案(參考)
- 2025年Α-乙酰乳酸脫羧酶項(xiàng)目合作計劃書
- 2025年文物遺址保護(hù)服務(wù)項(xiàng)目合作計劃書
- 2025年聚砜PSF項(xiàng)目建議書
- 2025年智能垃圾分類運(yùn)營模式在垃圾分類行業(yè)技術(shù)創(chuàng)新動態(tài)報告
- 農(nóng)村金融服務(wù)創(chuàng)新模式研究-2025年農(nóng)村金融信用體系建設(shè)與評價報告
- 醫(yī)院信息化2025年電子病歷系統(tǒng)優(yōu)化與醫(yī)療信息化標(biāo)準(zhǔn)對接報告
- 2025年能源互聯(lián)網(wǎng)分布式能源交易與分布式熱力網(wǎng)的融合創(chuàng)新報告
- 金融衍生品市場創(chuàng)新與風(fēng)險防范:2025年政策法規(guī)與監(jiān)管體系改革探討與實(shí)踐001
- 塑料箱項(xiàng)目安全評估報告
- 圖說工廠品質(zhì)管理
- (一模)烏魯木齊地區(qū)2025年高三年級第一次質(zhì)量英語試卷(含答案)
- 《高齡(≥75歲)急性冠脈綜合征患者規(guī)范化診療》解讀
- 社會調(diào)查研究與方法-001-國開機(jī)考復(fù)習(xí)資料
- 《個體防護(hù)裝備安全管理規(guī)范AQ 6111-2023》知識培訓(xùn)
- 菏澤學(xué)院社會心理學(xué)(專升本)復(fù)習(xí)題
- 九年級語文上冊《你是人間的四月天》課件
- 人工智能語言與倫理學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 2024年部編版九年級語文上冊電子課本(高清版)
- 湖南省長沙市平高教育集團(tuán)六校2023-2024學(xué)年高二下學(xué)期期末聯(lián)考+化學(xué)試卷(含答案)
評論
0/150
提交評論