_com.h
资源名称:GPS_test.rar [点击查看]
上传用户:fudaml
上传日期:2013-05-28
资源大小:211k
文件大小:15k
源码类别:
GPS编程
开发平台:
Visual C++
- /*
- 串口基础类库(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 wushaojian@21cn.com
- */
- /*
- Example :
- */
- #ifndef _COM_H_
- #define _COM_H_
- #pragma warning(disable: 4530)
- #pragma warning(disable: 4786)
- #pragma warning(disable: 4800)
- #include <cassert>
- #include <strstream>
- #include <algorithm>
- #include <exception>
- #include <iomanip>
- #include <fstream>
- using namespace std;
- #include "GPSParam.h"
- #include <windows.h>
- class _base_com //虚基类 基本串口接口
- {
- protected:
- volatile int _port; //串口号
- volatile HANDLE _com_handle;//串口句柄
- char _com_str[20];
- 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 p[12];
- _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 = 9600, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT, char EvtChar='n' )
- {
- if(is_open())
- {
- if(!GetCommState(_com_handle, &_dcb))
- return false;
- _dcb.BaudRate = BaudRate;
- _dcb.ByteSize = ByteSize;
- _dcb.Parity = Parity;
- _dcb.StopBits = StopBits;
- _dcb.EvtChar = EvtChar;
- 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 < 1 || 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 < 1 || 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_com
- {
- protected:
- //打开串口
- 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;
- buf[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;
- buf[r_len] = ' ';
- 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<typename T>
- _sync_com& operator << (T x)
- {
- strstream s;
- s << x;
- write(s.str(), s.pcount());
- return *this;
- }
- };
- class _asyn_com : public _base_com
- {
- protected:
- OVERLAPPED _ro, _wo; // 重叠I/O
- virtual bool open_port()
- {
- if(is_open())
- close();
- _com_handle = CreateFile(
- _com_str,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //重叠I/O
- NULL
- );
- //assert(is_open());
- return is_open();//检测串口是否成功打开
- }
- public:
- _asyn_com()
- {
- memset(&_ro, 0, sizeof(_ro));
- memset(&_wo, 0, sizeof(_wo));
- _ro.hEvent = CreateEvent(NULL, true, false, NULL);
- assert(_ro.hEvent != INVALID_HANDLE_VALUE);
- _wo.hEvent = CreateEvent(NULL, true, false, NULL);
- assert(_wo.hEvent != INVALID_HANDLE_VALUE);
- }
- virtual ~_asyn_com()
- {
- close();
- if(_ro.hEvent != INVALID_HANDLE_VALUE)
- CloseHandle(_ro.hEvent);
- if(_wo.hEvent != INVALID_HANDLE_VALUE)
- CloseHandle(_wo.hEvent);
- }
- //异步读
- int read(char *buf, int buf_len, int time_wait = 20)
- {
- if(!is_open())
- return 0;
- buf[0] = ' ';
- COMSTAT stat;
- DWORD error;
- if(ClearCommError(_com_handle, &error, &stat) && error > 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 ), (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;
- }
- buf[r_len] = ' ';
- 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<typename T>
- _asyn_com& operator << (T x)
- {
- strstream s;
- s << x ;
- write(s.str(), s.pcount());
- return *this;
- }
- };
- //当接受到数据送到窗口的消息
- #define ON_COM_RECEIVE WM_USER + 618 // WPARAM 端口号
- class _thread_com : public _asyn_com
- {
- protected:
- volatile HANDLE _thread_handle; //辅助线程
- volatile HANDLE _file_thread_handle; //文件辅助线程
- CString m_filename; //文件名
- volatile HWND _notify_hwnd; // 通知窗口
- volatile long _notify_num;//接受多少字节(>_notify_num)发送通知消息
- volatile bool _run_flag; //线程运行循环标志
- void (*_func)(WPARAM wp, LPARAM lp);
- // GPSParam gps; //存储临时gps返回参数
- OVERLAPPED _wait_o; //WaitCommEvent use
- //线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含窗口编号
- virtual void on_receive()
- {
- char str[270];
- memset(str,10,270);
- this->read(str,270);
- int j=0;
- bool start=false;
- char order[90];
- for( int i=0; i<270; i++)
- {
- switch(str[i])
- {
- case '$':
- start=true;
- order[0]='$';
- j=1;
- break;
- case 10:
- if( start ) //得到一个完整指令
- {
- ////////////////////////////////////
- ///如果,消息响应不及时,gps内存有可能泄露
- GPSParam *gps=new GPSParam;
- gps->SetParam(order,90);
- if(gps->DataTransform())
- {
- if(_notify_hwnd)
- {
- PostMessage( _notify_hwnd, ON_COM_RECEIVE, WPARAM(gps), 0 );
- }
- else
- ; ///////////////////
- }
- //////////////////////////////////////////////////////
- /*
- //GPSParam gps(order,90);
- gps.SetParam(order,j);
- if(gps.DataTransform())
- {
- if(_notify_hwnd)
- PostMessage( _notify_hwnd, ON_COM_RECEIVE, WPARAM(gps.X), LPARAM(gps.Y) );
- else
- ; ///////////////////
- }
- */
- }
- start=false;
- j=0;
- memset(order,0,90);
- break;
- default:
- {
- if( start )
- {
- order[j]=str[i];
- j++;
- }
- }
- }
- }
- /*
- 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 = 250;
- _notify_hwnd = NULL;
- _thread_handle = NULL;
- _file_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)(WPARAM wp, LPARAM lp))
- {
- _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(_thread_handle) != 0xFFFFFFFF : false;
- }
- //恢复监视线程
- bool resume()
- {
- return _thread_handle != NULL ? ResumeThread(_thread_handle) != 0xFFFFFFFF : false;
- }
- //重建监视线程
- bool restart()
- {
- if(_thread_handle) /*只有已有存在线程时*/
- {
- _run_flag = false;
- SetCommMask(_com_handle, 0);
- SetEvent(_wait_o.hEvent);
- if(WaitForSingleObject(_thread_handle, 100) != WAIT_OBJECT_0)
- TerminateThread(_thread_handle, 0);
- CloseHandle(_thread_handle);
- _run_flag = true;
- _thread_handle = NULL;
- DWORD id;
- _thread_handle = CreateThread(NULL, 0, com_thread, this, 0, &id);
- return (_thread_handle != NULL); //辅助线程
- }
- return false;
- }
- bool Open_file(CString str)
- {
- if (_file_thread_handle ==NULL)
- {
- m_filename=str;
- DWORD id;
- _file_thread_handle=CreateThread(NULL,0,file_thread,this,0,&id);
- return (_file_thread_handle != NULL);
- }
- return false;
- }
- private:
- //监视线程
- static DWORD WINAPI com_thread(LPVOID para)
- {
- _thread_com *pcom = (_thread_com *)para;
- //制定串口的监视事件 接收到一个字符 或者出现错误
- if(!SetCommMask(pcom->_com_handle, EV_RXCHAR | EV_ERR | EV_RXFLAG ) )
- return 0;
- COMSTAT stat;
- DWORD error;
- for(DWORD length, mask = 0; pcom->_run_flag && pcom->is_open(); mask = 0)
- {
- 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 ) //线上错误
- ClearCommError(pcom->_com_handle, &error, &stat);
- //接收到事件字符
- if( mask & EV_RXFLAG ) // EV_RXFLAG事件产生
- {
- ClearCommError(pcom->_com_handle, &error, &stat);
- pcom->on_receive();
- }
- //接收到一个字符处理
- if(mask & EV_RXCHAR) // == EV_RXCHAR
- {
- ClearCommError(pcom->_com_handle, &error, &stat);
- if(stat.cbInQue > pcom->_notify_num)
- pcom->on_receive();
- }
- }
- return 0;
- }
- static DWORD WINAPI file_thread(LPVOID para)
- {
- _thread_com *pcom = (_thread_com *)para;
- ifstream in;
- in.open(pcom->m_filename);
- while (true)
- {
- // Sleep(5);
- char str[270];
- memset(str,10,270);
- if( !in.getline(str,270) )
- break;
- int j=0;
- bool start=false;
- char order[90]; //存储一条指令
- for( int i=0; i<270; i++)
- {
- switch(str[i])
- {
- case '$':
- start=true;
- order[0]='$';
- j=1;
- break;
- case 10:
- if( start ) //得到一个完整指令
- {
- GPSParam *gps=new GPSParam;
- gps->SetParam(order,90);
- if(gps->DataTransform())
- {
- if(pcom->_notify_hwnd)
- {
- PostMessage( pcom->_notify_hwnd, ON_COM_RECEIVE, WPARAM(gps), 0 );
- }
- else
- delete gps; ///////////////////
- /*
- if( pcom->_func )
- {
- // pcom->_func( (WPARAM)gps,(LPARAM)pcom->_notify_hwnd );
- }
- else
- delete gps;
- */
- }
- else
- delete gps;
- // delete gps;
- }
- start=false;
- j=0;
- memset(order,0,90);
- break;
- default:
- {
- if( start )
- {
- order[j]=str[i];
- j++;
- }
- }
- }
- }
- }
- return 0;
- }
- };
- typedef _thread_com _com; //名称简化
- #endif //_COM_H_