深入浅出VC++串口编程之第三方类

上传人:pia****nwu 文档编号:157043666 上传时间:2022-09-28 格式:DOC 页数:19 大小:59.51KB
收藏 版权申诉 举报 下载
深入浅出VC++串口编程之第三方类_第1页
第1页 / 共19页
深入浅出VC++串口编程之第三方类_第2页
第2页 / 共19页
深入浅出VC++串口编程之第三方类_第3页
第3页 / 共19页
资源描述:

《深入浅出VC++串口编程之第三方类》由会员分享,可在线阅读,更多相关《深入浅出VC++串口编程之第三方类(19页珍藏版)》请在装配图网上搜索。

1、深入浅出VC+串口编程之第三方类 深入浅出VC+串口编程之第三方类源代码下载串口类从本系列文章连载三、四可以看出,与通过WIN32 API进行串口访问相比,通过MScomm这个Activex控件进行串口访问要来的方便许多,它基本上可以向用户屏蔽多线程的细节,以事件(发出OnComm消息)方式实现串口的异步访问。尽管如此,MScomm控件的使用仍有诸多不便,譬如其发送和接收数据都要进行VARIANT类型对象与字符串的转化等。因此,国内外许多优秀的程序员自己编写了一些串口类,使用这些类,我们将可以更方便的操作串口。在笔者的深入浅出Win32多线程程序设计之综合实例(网址:)一文中,曾向读者展示了由

2、Remon Spekreijse编写的CSerialPort串口类,而本文将向您展示由程序员llbird编写的cnComm(中国串口?)串口类。llbird是一位优秀的程序员,他的代码风格简洁而紧凑,类的声明和实现都被定义在一个头文件中,使用这个类的朋友只需要在工程中包含这一头文件即可:/*Comm Base Library(WIN98/NT/2000) ver 1.1Compile by: BC+ 5; C+ BUILDER 4, 5, 6, X; VC+ 5, 6; VC.NET; GCC;copyright(c) 2004.5 - 2005.8 llbird wushaojian*/ #

3、ifndef _CN_COMM_H_#define _CN_COMM_H_#pragma warning(disable: 4530)#pragma warning(disable: 4786)#pragma warning(disable: 4800)#include #include #include /送到窗口的消息 WPARAM 端口号#define ON_COM_RECEIVE WM_USER + 618#define ON_COM_CTS WM_USER + 619 /LPARAM 1 valid#define ON_COM_DSR WM_USER + 621 /LPARAM 1

4、valid#define ON_COM_RING WM_USER + 623#define ON_COM_RLSD WM_USER + 624#define ON_COM_BREAK WM_USER + 625#define ON_COM_TXEMPTY WM_USER + 626#define ON_COM_ERROR WM_USER + 627 /LPARAM save Error ID#define DEFAULT_COM_MASK_EVENT EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING |

5、 EV_RLSDclass cnCommpublic:/-Construction-/第1个参数为是否在打开串口时启动监视线程, 第2个参数为IO方式 阻塞方式(0)/ 异步重叠方式(默认)cnComm(bool fAutoBeginThread = true, DWORD dwIOMode =FILE_FLAG_OVERLAPPED): _dwIOMode(dwIOMode), _fAutoBeginThread(fAutoBeginThread)Init();virtual cnComm()Close();UnInit();/-Attributes-/判断串口是否打开inline bool

6、 IsOpen()return _hCommHandle != INVALID_HANDLE_VALUE;/判断串口是否打开operator bool()return _hCommHandle != INVALID_HANDLE_VALUE;/获得串口句炳inline HANDLE GetHandle()return _hCommHandle;/获得串口句炳operator HANDLE()return _hCommHandle;/获得串口参数 DCBDCB *GetState()return IsOpen() & :GetCommState(_hCommHandle, &_DCB) = TR

7、UE ?&_DCB: NULL;/设置串口参数 DCBbool SetState(DCB *pdcb = NULL)return IsOpen() ? :SetCommState(_hCommHandle, pdcb = NULL ? &_DCB:pdcb) = TRUE: false;/设置串口参数:波特率,停止位,等 支持设置字符串 9600, 8, n, 1bool SetState(char *szSetStr)if (IsOpen()if (:GetCommState(_hCommHandle, &_DCB) != TRUE)return false;if (:BuildCommDC

8、B(szSetStr, &_DCB) != TRUE)return false;return :SetCommState(_hCommHandle, &_DCB) = TRUE;return false;/设置串口参数:波特率,停止位,等bool SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity =NOPARITY, DWORD dwStopBits = ONESTOPBIT)if (IsOpen()if (:GetCommState(_hCommHandle, &_DCB) != TRUE)return false

9、;_DCB.BaudRate = dwBaudRate;_DCB.ByteSize = (unsigned char)dwByteSize;_DCB.Parity = (unsigned char)dwParity;_DCB.StopBits = (unsigned char)dwStopBits;return :SetCommState(_hCommHandle, &_DCB) = TRUE;return false;/获得超时结构LPCOMMTIMEOUTS GetTimeouts(void)return IsOpen() & :GetCommTimeouts(_hCommHandle,

10、&_CO) = TRUE ?&_CO: NULL;/设置超时bool SetTimeouts(LPCOMMTIMEOUTS lpCO)return IsOpen() ? :SetCommTimeouts(_hCommHandle, lpCO) = TRUE:false;/设置串口的I/O缓冲区大小bool SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)return IsOpen() ? :SetupComm(_hCommHandle, dwInputSize, dwOutputSize)= TRUE: false;/关联消息的窗口句柄i

11、nline void SetWnd(HWND hWnd)assert(:IsWindow(hWnd);_hNotifyWnd = hWnd;/设定发送通知, 接受字符最小值inline void SetNotifyNum(DWORD dwNum)_dwNotifyNum = dwNum;/线程是否运行inline bool IsThreadRunning()return _hThreadHandle != NULL;/获得线程句柄inline HANDLE GetThread()return _hThreadHandle;/设置要监视的事件, 打开前设置有效void SetMaskEvent(

12、DWORD dwEvent = DEFAULT_COM_MASK_EVENT)_dwMaskEvent = dwEvent;/获得读缓冲区的字符数int GetInputSize()COMSTAT Stat;DWORD dwError;return :ClearCommError(_hCommHandle, &dwError, &Stat) = TRUE ? Stat.cbInQue : (DWORD) - 1L;/-Operations-/打开串口 缺省 9600, 8, n, 1bool Open(DWORD dwPort)return Open(dwPort, 9600);/打开串口 缺

13、省 baud_rate, 8, n, 1bool Open(DWORD dwPort, DWORD dwBaudRate)if (dwPort 1024)return false;BindCommPort(dwPort);if (!OpenCommPort()return false;if (!SetupPort()return false;return SetState(dwBaudRate);/打开串口, 使用类似9600, 8, n, 1的设置字符串设置串口bool Open(DWORD dwPort, char *szSetStr)if (dwPort 1024)return fals

14、e;BindCommPort(dwPort);if (!OpenCommPort()return false;if (!SetupPort()return false;return SetState(szSetStr);/读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据DWORD Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 10)if (!IsOpen()return 0;COMSTAT Stat;DWORD dwError;if (:ClearCommError(_h

15、CommHandle, &dwError, &Stat) & dwError 0):PurgeComm(_hCommHandle,PURGE_RXABORT | PURGE_RXCLEAR);return 0;if (!Stat.cbInQue)/ 缓冲区无数据return 0;unsigned long uReadLength = 0;dwBufferLength = dwBufferLength Stat.cbInQue ? Stat.cbInQue :dwBufferLength;if (!:ReadFile(_hCommHandle, Buffer, dwBufferLength, &

16、uReadLength,&_ReadOverlapped)if (:GetLastError() = ERROR_IO_PENDING)WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime);/ 结束异步I/Oif (!:GetOverlappedResult(_hCommHandle, &_ReadOverlapped,&uReadLength, false)if (:GetLastError() != ERROR_IO_INCOMPLETE)uReadLength = 0;elseuReadLength = 0;return uRea

17、dLength;/读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯char *ReadString(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime =20)unsigned long uReadLength = Read(szBuffer, dwBufferLength - 1,dwWaitTime);szBufferuReadLength = 0;return szBuffer;/写串口 可写任意数据 abcd or x0x1x2DWORD Write(

18、LPVOID Buffer, DWORD dwBufferLength)if (!IsOpen()return 0;DWORD dwError;if (:ClearCommError(_hCommHandle, &dwError, NULL) & dwError 0):PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);unsigned long uWriteLength = 0;if (!:WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength,&_WriteOver

19、lapped)if (:GetLastError() != ERROR_IO_PENDING)uWriteLength = 0;return uWriteLength;/写串口 写ANSI C 模式字符串指针 DWORD Write(const char *szBuffer)assert(szBuffer);return Write(void*)szBuffer, strlen(szBuffer);/读串口 同步应用DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength)if (!IsOpen()return 0;DWORD dwError;if

20、(:ClearCommError(_hCommHandle, &dwError, NULL) & dwError 0):PurgeComm(_hCommHandle,PURGE_RXABORT | PURGE_RXCLEAR);return 0;DWORD uReadLength = 0;:ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL);return uReadLength;/写串口 同步应用DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength)if (!Is

21、Open()return 0;DWORD dwError;if (:ClearCommError(_hCommHandle, &dwError, NULL) & dwError 0):PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);unsigned long uWriteLength = 0;:WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL);return uWriteLength;/写串口 szBuffer 可以输出格式字符串 包含缓冲区长度D

22、WORD Write(char *szBuffer, DWORD dwBufferLength, char *szFormat, .)if (!IsOpen()return 0;va_list va;va_start(va, szFormat);_vsnprintf(szBuffer, dwBufferLength, szFormat, va);va_end(va);return Write(szBuffer);/写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出DWORD Write(char *szBuffer, char *szFormat, .)if (!IsOp

23、en()return 0;va_list va;va_start(va, szFormat);vsprintf(szBuffer, szFormat, va);va_end(va);return Write(szBuffer);/关闭串口 同时也关闭关联线程virtual void Close()if (IsOpen()PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);EndThread();:CloseHandle(_hCommHandle);_hCommHandle = INVALID_HANDLE_VALUE;/DTR 电平控制

24、bool SetDTR(bool OnOrOff)return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR :CLRDTR): false;/RTS 电平控制bool SetRTS(bool OnOrOff)return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS :CLRRTS): false;/bool SetBreak(bool OnOrOff)return IsOpen() ? EscapeCommFunction(_hCommHa

25、ndle, OnOrOff ? SETBREAK: CLRBREAK): false;/辅助线程控制 建监视线程bool BeginThread()if (!IsThreadRunning()_fRunFlag = true;_hThreadHandle = NULL;DWORD id;_hThreadHandle = :CreateThread(NULL, 0, CommThreadProc, this, 0,&id);return (_hThreadHandle != NULL);return false;/暂停监视线程inline bool SuspendThread()return I

26、sThreadRunning() ? :SuspendThread(_hThreadHandle) !=0xFFFFFFFF: false;/恢复监视线程inline bool ResumeThread()return IsThreadRunning() ? :ResumeThread(_hThreadHandle) !=0xFFFFFFFF: false;/终止线程bool EndThread(DWORD dwWaitTime = 100)if (IsThreadRunning()_fRunFlag = false;:SetCommMask(_hCommHandle, 0);:SetEven

27、t(_WaitOverlapped.hEvent);if (:WaitForSingleObject(_hThreadHandle, dwWaitTime) !=WAIT_OBJECT_0)if (!:TerminateThread(_hThreadHandle, 0)return false;:CloseHandle(_hThreadHandle);:ResetEvent(_WaitOverlapped.hEvent);_hThreadHandle = NULL;return true;return false;protected:volatile DWORD _dwPort; /串口号vo

28、latile HANDLE _hCommHandle; /串口句柄char _szCommStr20; /保存COM1类似的字符串DCB _DCB; /波特率,停止位,等COMMTIMEOUTS _CO; /超时结构DWORD _dwIOMode; / 0 同步 默认 FILE_FLAG_OVERLAPPED重叠I/O异步OVERLAPPED _ReadOverlapped, _WriteOverlapped; / 重叠I/Ovolatile HANDLE _hThreadHandle; /辅助线程volatile HWND _hNotifyWnd; / 通知窗口volatile DWORD

29、_dwNotifyNum; /接受多少字节(=_dwNotifyNum)发送通知消息volatile DWORD _dwMaskEvent; /监视的事件volatile bool _fRunFlag; /线程运行循环标志bool _fAutoBeginThread; /Open() 自动 BeginThread();OVERLAPPED _WaitOverlapped; /WaitCommEvent use/初始化void Init()memset(_szCommStr, 0, 20);memset(&_DCB, 0, sizeof(_DCB);_DCB.DCBlength = sizeof

30、(_DCB);_hCommHandle = INVALID_HANDLE_VALUE;memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped);memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped);_ReadOverlapped.hEvent = :CreateEvent(NULL, true, false, NULL);assert(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);_WriteOverlapped.hEvent = :Create

31、Event(NULL, true, false, NULL);assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);_hNotifyWnd = NULL;_dwNotifyNum = 0;_dwMaskEvent = DEFAULT_COM_MASK_EVENT;_hThreadHandle = NULL;memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped);_WaitOverlapped.hEvent = :CreateEvent(NULL, true, false, NULL);as

32、sert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);/析构void UnInit()if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)CloseHandle(_ReadOverlapped.hEvent);if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)CloseHandle(_WriteOverlapped.hEvent);if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)Clos

33、eHandle(_WaitOverlapped.hEvent);/绑定串口void BindCommPort(DWORD dwPort)assert(dwPort = 1 & dwPort = _dwNotifyNum)OnReceive();break;case EV_TXEMPTY:OnTXEmpty();break;case EV_CTS:OnCTS();break;case EV_DSR:OnDSR();break;case EV_RING:OnRing();break;case EV_RLSD:OnRLSD();break;case EV_BREAK:OnBreak();break;

34、case EV_ERR:OnError();break; /case /forreturn 0;private:/the function protectedcnComm(const cnComm &);cnComm &operator = (const cnComm &);/base function for threadstatic DWORD WINAPI CommThreadProc(LPVOID lpPara)return (cnComm*)lpPara)-ThreadFunc();#endif /_CN_COMM_H_2.实例程序的功能和界面(如下图)都与本文连载三、四中基于WIN

35、32 API的串口编程和基于控件的串口编程相同,不同的只是本节的串口通信要以llbird定义的cnComm类来实现。我们需要为串口的接收事件定义一个用户消息ON_COM_RECEIVE,因此对话框的消息映射为:BEGIN_MESSAGE_MAP(CSerialPortClassDlg, CDialog)/AFX_MSG_MAP(CSerialPortClassDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClearButton)ON_BN_CLICKED(IDC

36、_SEND_BUTTON, OnSendButton)ON_MESSAGE(ON_COM_RECEIVE,OnCommRecv)/AFX_MSG_MAPEND_MESSAGE_MAP()同时,我们需要在对话框类的头文件中定义cnComm类的成员变量com和接收数据消息处理函数OnCommRecv:cnComm com;afx_msg void OnCommRecv(WPARAM wParam, LPARAM lParam);在对话框初始化时调用打开串口:BOOL CSerialPortClassDlg:OnInitDialog()CDialog:OnInitDialog();/ Add Abo

37、ut. menu item to system menu./ IDM_ABOUTBOX must be in the system command range.ASSERT(IDM_ABOUTBOX &0xFFF0) = IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);/ Set the icon for this dialog. The framework does this automatically/

38、when the applications main window is not a dialogSetIcon(m_hIcon, TRUE); / Set big iconSetIcon(m_hIcon, FALSE); / Set small icon/ TODO: Add extra initialization herecom.Open(1); /打开串口1并使用默认设置com.SetWnd(AfxGetMainWnd()-m_hWnd); /设置消息处理窗口return TRUE; / return TRUE unless you set the focus to a control

39、发送字符串的过程很简单,只需要调用cnComm类的Write函数:/发送按钮函数(完成数据的发送功能)void CSerialPortClassDlg:OnSendButton()/ TODO: Add your control notification handler code hereUpdateData(true);com.Write(m_send); /发送字符串接收字符串的过程也很简单,只需要调用cnComm类的ReadString函数: void CSerialPortClassDlg:OnCommRecv(WPARAM wParam, LPARAM lParam)UpdateData(true);/读取串口上的字符char str100;com.ReadString(str, 100);m_recv += str;UpdateData(false);读者朋友们这时一定会发出感慨:使用cnComm类后,进行串口数据收发的程序是多么简单啊!的确,串口的初始化、读写几乎都是用12条语句搞定的!这就是我们要特别用一次连载来讲述使用第三方类来进行串口通信的原因。实际上,笔者在进行网络通信程序编程时,也不认为MS提供的CSocket类是最方便的选择,照样习惯使用第三方的网络通信类。它们的确有非常简洁明快的接口,这一点也是值得MS哥哥们学习的。

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!