VC串口通讯DLL.doc_第1页
VC串口通讯DLL.doc_第2页
VC串口通讯DLL.doc_第3页
VC串口通讯DLL.doc_第4页
VC串口通讯DLL.doc_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

VC串口通讯DLL 串口在工业应用是极为普遍的,我用API封装了同步和异步的串口类,以及一个具有监视线程的异步串口类;使用简单高效,具有工业强度,我在BC, BCB, VC, BCBX, GCC下编译通过,相信足够应付大多数情况,而且还可以继承扩展,下面简单介绍使用方法 库的层次结构: _base_com:虚基类,基本接口,可自行扩展自己的串口类 _sync_com:_base_com 的子类, 同步应用,适合简单应用 _asyn_com:_base_com 的子类, 异步应用(重叠I/O),适合较高效应用,NT平台 _thread_com:_asyn_com 的子类, 异步应用,监视线程,适合较复杂应用,窗口通知消息和继承扩展的使用方式;几个问题: 结束线程 如何从WaitCommEvent(pcom-_com_handle, &mask, &pcom-_wait_o)这个API退出以便顺利结束线程: 方案1: SetCommMask(_com_handle, 0); 这个方法在MSDN有载,当在一些情况下并不完全有效,原因未知; 方案2: SetEvent(_wait_o.hEvent); 直接激活重叠IO结构中的事件句柄,绝对有效; 这份代码我两种都用; 打开10以上的COM端口 在NT/2000下打开编号10以上端口用 _com_handle = CreateFile( “COM10“, GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL FILE_FLAG_OVERLAPPED, /重叠I/O NULL );将提示错误, 这样就OK:_com_handle = CreateFile( “.COM10“,/对应的就是.COM10 GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL FILE_FLAG_OVERLAPPED, /重叠I/O NULL ); 线程中循环的低效率问题 使用SetCommMask(pcom-_com_handle, EV_RXCHAR EV_ERR)监视接受字符和错误消息;一旦有个字符来就会激活WaitCommEvent 通常作以下接受操作: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_receive();/接收到字符 /或发送到窗口消息 这样频繁的函数调用或接受发送消息,效率低下,我添加扫描缓冲区的代码,当字符数超过设定的字符数才作接受字符的操作;if(mask & EV_RXCHAR) / = EV_RXCHAR ClearCommError(pcom-_com_handle, &error, &stat); if(stat.cbInQue pcom-_notify_num) /_notify_num 是设定得字符数 pcom-on_receive(); 类似于流的输出方式我编了一个简单的写串口的方式,可以类似于流将简单的数据类型输出template _asyn_com& 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_str); / set_str : “9600, 8, n, 1“ bool set_state(int BaudRate, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT) /设置内置结构串口参数:波特率,停止位 bool set_state(char *set_str) bool is_open(); HANDLE get_handle(); virtual bool open_port()=0; /继承用的重要函数 virtual close();class _sync_com :public _base_com /同步 int read(char *buf, int buf_size); /自动补上0,将用去一个字符的缓冲区 int write(char *buf, int len); int write(char *buf);class _asyn_com :public _base_com /异步 int read(char *buf, int buf_size); /自动补上0,将用去一个字符的缓冲区 int write(char *buf, int len); int write(char *buf);class _thread_com :public _asyn_com /线程 virtual void on_receive() /供线程接受到字符时调用, 可继承替换之 if(_notify_hwnd) PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0); else if(_func) _func(_port); void set_hwnd(HWND hwnd); /设置窗口句柄, 发送 ON_COM_RECEIVE WM_USER + 618 void set_func(void (*f)(int); /设置调用函数 ,窗口句柄优先 void set_notify_num(int num); /设定发送通知, 接受字符最小值一些应用范例 当然首先 #include _com.h 一、打开串口1同步写 char str = com_class test; _sync_com com1; /同步 com1.open(1); / 相当于 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_com com2; /异步 com2.open(2); / 相当于 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) /异步读,返回读取字符数 cout 0) /异步读,返回读取字符数 cout str; ; int main(int argc, char *argv) try char str100; _com_ex com2; /异步扩展 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, 10); / 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 declarations 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 TForm1: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/*串口基础类库(WIN32) ver 0.1编译器 : BC+ 5; C+ BUILDER 4, 5, 6, X; VC+ 5, 6; VC.NET; GCC;class _base_com : 虚基类 基本串口接口;class _sync_com : 同步I/O 串口类;class _asyn_com : 异步I/O 串口类;class _thread_com : 异步I/O 辅助读监视线程 可转发窗口消息 串口类(可继承虚函数on_receive用于读操作);class _com : _thread_com 同名copyright(c) 2004.8 llbird */*Example :*/#ifndef _COM_H_#define _COM_H_#pragma warning(disable: 4530)#pragma warning(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_port() = 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; /设置推荐缓冲区 if(!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; /设置超时时间 if(!PurgeComm(_com_handle, PURGE_TXABORT PURGE_RXABORT PURGE_TXCLEAR PURGE_RXCLEAR ) return false; /清空串口缓冲区 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(); /设置串口参数:波特率,停止位,等 支持设置字符串 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; /设置内置结构串口参数:波特率,停止位 bool set_state(int BaudRate, int ByteSize = 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, 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, char *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; /关闭串口 inline virtual void close() if(is_open() CloseHandle(_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_open() close(); _com_handle = CreateFile( _com_str, GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , 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(_com_handle, &error, &stat) & error 0) /清除错误 PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除输入缓冲区*/ return 0; unsigned long r_len = 0; buf_len = min(buf_len - 1, (int)stat.cbInQue); if(!ReadFile(_com_handle, buf, buf_len, &r_len, NULL) r_len = 0; bufr_len = 0; return r_len; /同步写 int write(char *buf, int buf_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(!WriteFile(_com_handle, buf, buf_len, &w_len, NULL) w_len = 0; return w_len; /同步写 inline int write(char *buf) assert(buf); return write(buf, strlen(buf); /同步写, 支持部分类型的流输出 template _sync_com& operator (T x) strstream s; s 0) /清除错误 PurgeComm(_com_handle, PURGE_RXABORT PURGE_RXCLEAR); /*清除输入缓冲区*/ return 0; if(!stat.cbInQue)/ 缓冲区无数据 return 0; unsigned long r_len = 0; buf_len = min(int)(buf_len - 1), (int)stat.cbInQue); if(!ReadFile(_com_handle, buf, buf_len, &r_len, &_ro) /2000 下 ReadFile 始终返回 True if(GetLastError() = ERROR_IO_PENDING) / 结束异步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 = 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(!WriteFile(_com_handle, buf, buf_len, &w_len, &_wo) if(GetLastError() != 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)发送通知消息 volatile bool _run_flag; /线程运行循环标志 void (*_func)(int port); OVERLAPPED _wait_o; /WaitCommEvent use /线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含窗口编号 virtual void on_receive() if(_notify_hwnd) PostMessage(_notify_hwnd, ON_COM_RECEIVE, WPARAM(_port), LPARAM(0); else if(_func) _func(_port); /打开串口,同时打开监视线程 virtual bool open_port() if(_asyn_com:open_port() _run_flag = true; DWORD id; _thread_handle = CreateThread(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_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); /设定发送通知, 接受字符最小值 void set_notify_num(int num) _notify_num = num; int get_notify_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; /关闭线程及串口 virtual void close() if(is_open() _run_flag = false; SetCommMask(_com_handle, 0); SetEvent(_wait_o.hEvent); if(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; /暂停监视线程 bool suspend() return _thread_handle != NULL ? SuspendThread(_thre

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论