VC++ 基于Win32 API的串口编程 要实现程序跟单片机的串口通讯最好是有实例有的话发到邮箱[email protected] 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 这里比较多:http://www.codeproject.com/info/search.aspx?artkw=Serial+Port 晕倒个个都是Page Not Found呀 #ifndef _SERIALPORT_H//SerialPort.h#define _SERIALPORT_H#pragma once#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <process.h>#include <tchar.h>#include "FrameDef.h"#define NAMEBUF_SIZE 64 //存放串口名字的数组大小//送到窗口的消息 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 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 | EV_RLSDclass DLLDIR CSerialPort {public: struct InnerLock { CSerialPort* ptr; InnerLock(CSerialPort* p) : ptr(p) { ptr->Lock(); } ~InnerLock() { ptr->Unlock(); } }; //------------------------------Construction----------------------------------- //第1个参数为是否在打开串口时启动监视线程, 第2个参数为IO方式 阻塞方式(0)/ 异步重叠方式(默认) CSerialPort(BOOL bAutoBeginThread = TRUE, DWORD dwIOMode = FILE_FLAG_OVERLAPPED); virtual ~CSerialPort(); //----------------------------------Attributes---------------------------------- inline BOOL IsOpen(); //判断串口是或打开 operator BOOL (); //判断串口是或打开 HANDLE GetHandle(); //获得串口句炳 operator HANDLE(); //获得串口句炳 const int GetPortID(); //获得串口序号 LPCTSTR GetPortName(); //获得串口全名 DCB *GetState(); //获得串口参数 DCB BOOL SetState(DCB *pdcb = NULL); //设置串口参数 DCB BOOL SetState(LPCTSTR lpszSetStr); //设置串口参数:波特率,停止位,等 支持设置字符串 "9600, n, 8, 1" //设置串口参数:波特率,停止位,等 BOOL SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity = NOPARITY, DWORD dwStopBits = ONESTOPBIT); LPCOMMTIMEOUTS GetTimeouts(void); //获得超时结构 BOOL SetTimeouts(LPCOMMTIMEOUTS lpCO); //设置超时 BOOL SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize); //设置串口的I/O缓冲区大小 void ClearInputBuffer(); //清除接受缓冲区 void ClearOutputBuffer(); //清除发送缓冲区 inline void SetWnd(HWND hWnd); //关联消息的窗口句柄 inline void SetNotifyNum(DWORD dwNum); //设定发送通知, 接受字符最小值 inline BOOL IsThreadRunning(); //线程是否运行 inline HANDLE GetThread(); //获得线程句柄 void SetMaskEvent(DWORD dwEvent = DEFAULT_COM_MASK_EVENT); //设置要监视的事件, 打开前设置有效 int GetInputSize(); //获得读缓冲区的字符数 //----------------------------------Operations---------------------------------- BOOL Open(DWORD dwPort); //打开串口 缺省 9600, n, 8, 1 BOOL Open(DWORD dwPort, DWORD dwBaudRate); //打开串口 缺省 baud_rate, n, 8, 1 BOOL Open(DWORD dwPort, LPCTSTR lpszSetStr); //打开串口, 使用类似"9600, n, 8, 1"的设置字符串设置串口 DWORD Read(LPVOID Buffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer = TRUE); //读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据 DWORD ReadString(char *szBuffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer = TRUE); //读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯 DWORD Write(LPCVOID Buffer, DWORD dwBufferLength); //写串口 可写任意数据 "abcd" or "x0x1x2" DWORD Write(const char *szBuffer); //写串口 写ANSI C 模式字符串指针 DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength); //读串口 同步应用 DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength); //写串口 同步应用 DWORD Write(char *szBuffer, DWORD dwBufferLength, char * szFormat, ...); //写串口 szBuffer 可以输出格式字符串 包含缓冲区长度 virtual void Close(); //关闭串口 同时也关闭关联线程 void Lock(); //锁定资源 void Unlock(); BOOL SetDTR(BOOL OnOrOff); //DTR 电平控制 BOOL SetRTS(BOOL OnOrOff); //RTS 电平控制 BOOL SetBreak(BOOL OnOrOff); BOOL BeginThread(); //辅助线程控制 建监视线程 inline BOOL SuspendThread(); //暂停监视线程 inline BOOL ResumeThread(); //恢复监视线程 BOOL EndThread(DWORD dwWaitTime = 100); //终止线程protected: volatile DWORD m_dwPort; //串口号 volatile HANDLE m_hCommHandle; //串口句柄 TCHAR m_tszCommStr[NAMEBUF_SIZE]; //保存COM1类似的字符串 DCB m_DCB; //波特率,停止位,等 COMMTIMEOUTS m_CO; //超时结构 DWORD m_dwIOMode; // 0 同步 默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步 OVERLAPPED m_readOverlapped; // 重叠I/O OVERLAPPED m_writeOverlapped; volatile HANDLE m_hThreadHandle; //辅助线程 volatile HWND m_hNotifyWnd; // 通知窗口 volatile DWORD m_dwNotifyNum; //接受多少字节(>=m_dwNotifyNum)发送通知消息 volatile DWORD m_dwMaskEvent; //监视的事件 volatile BOOL m_bRunFlag; //线程运行循环标志 BOOL m_bAutoBeginThread; //Open() 自动 BeginThread(); OVERLAPPED m_bWaitOverlapped; //WaitCommEvent use virtual void Init(); //初始化 virtual void Destroy(); //析构 void BindCommPort(DWORD dwPort); //绑定串口 virtual BOOL OpenCommPort(); //打开串口 virtual BOOL SetupPort(); //设置串口 //---------------------------------------threads callback----------------------------------------------------- //线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展 virtual void OnReceive(); virtual void OnDSR(); virtual void OnCTS(); virtual void OnBreak(); virtual void OnTXEmpty(); virtual void OnError(); virtual void OnRing(); virtual void OnRLSD(); virtual DWORD ThreadFunc();private: //the function protected CSerialPort(const CSerialPort&); CSerialPort &operator = (const CSerialPort&); CRITICAL_SECTION _Mutex; //base function for thread#ifdef _MT static UINT APIENTRY CommThreadProc(LPVOID lpPara);#else static DWORD WINAPI CommThreadProc(LPVOID lpPara);#endif};#endif //_SERIALPORT_H #include "stdafx.h"#include "SerialPort.h"CSerialPort::CSerialPort(BOOL bAutoBeginThread /*= TRUE*/, DWORD dwIOMode /*= FILE_FLAG_OVERLAPPED*/) : m_dwIOMode(dwIOMode), m_bAutoBeginThread(bAutoBeginThread){ Init(); }CSerialPort::~CSerialPort(void){ Close(); Destroy();}BOOL CSerialPort::IsOpen(){ return m_hCommHandle != INVALID_HANDLE_VALUE;}CSerialPort::operator BOOL (){ return m_hCommHandle != INVALID_HANDLE_VALUE;}HANDLE CSerialPort::GetHandle() //获得串口句炳{ return m_hCommHandle;}CSerialPort::operator HANDLE() //获得串口句炳{ return m_hCommHandle;}const int CSerialPort::GetPortID() //获得串口序号{ return m_dwPort;}LPCTSTR CSerialPort::GetPortName() //获得串口全名{ return m_tszCommStr;}DCB* CSerialPort::GetState() //获得串口参数 DCB{ return IsOpen() && ::GetCommState(m_hCommHandle, &m_DCB) == TRUE ? &m_DCB : NULL;}///设置串口参数 DCBBOOL CSerialPort::SetState(DCB *pdcb /*= NULL*/){ return IsOpen() ? ::SetCommState(m_hCommHandle, pdcb == NULL ? &m_DCB : pdcb) == TRUE : FALSE;}///设置串口参数:波特率,停止位,等 支持设置字符串 "9600, n, 8, 1"BOOL CSerialPort::SetState(LPCTSTR lpszSetStr) { if(IsOpen()) { if(::GetCommState(m_hCommHandle, &m_DCB) != TRUE) return FALSE; if(::BuildCommDCB(lpszSetStr, &m_DCB) != TRUE) return FALSE; return ::SetCommState(m_hCommHandle, &m_DCB) == TRUE; } return FALSE;}///设置串口参数:波特率,停止位,等BOOL CSerialPort::SetState(DWORD dwBaudRate, DWORD dwByteSize /*= 8*/, DWORD dwParity /*= NOPARITY*/, DWORD dwStopBits /*= ONESTOPBIT*/){ if(IsOpen()) { if(::GetCommState(m_hCommHandle, &m_DCB) != TRUE) return FALSE; m_DCB.BaudRate = dwBaudRate; m_DCB.ByteSize = (unsigned char)dwByteSize; m_DCB.Parity = (unsigned char)dwParity; m_DCB.StopBits = (unsigned char)dwStopBits; return ::SetCommState(m_hCommHandle, &m_DCB) == TRUE; } return FALSE;}///获得超时结构LPCOMMTIMEOUTS CSerialPort::GetTimeouts(void){ return IsOpen() && ::GetCommTimeouts(m_hCommHandle, &m_CO) == TRUE ? &m_CO : NULL;}///设置超时BOOL CSerialPort::SetTimeouts(LPCOMMTIMEOUTS lpCO){ return IsOpen() ? ::SetCommTimeouts(m_hCommHandle, lpCO) == TRUE : FALSE;}///设置串口的I/O缓冲区大小BOOL CSerialPort::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize){ return IsOpen() ? ::SetupComm(m_hCommHandle, dwInputSize, dwOutputSize) == TRUE : FALSE; }///清除接受缓冲区void CSerialPort::ClearInputBuffer(){ if(IsOpen()) ::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR );}///清除发送缓冲区void CSerialPort::ClearOutputBuffer(){ if(IsOpen()) ::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR );}///关联消息的窗口句柄void CSerialPort::SetWnd(HWND hWnd){ assert(::IsWindow(hWnd)); m_hNotifyWnd = hWnd;}///设定发送通知, 接受字符最小值void CSerialPort::SetNotifyNum(DWORD dwNum){ m_dwNotifyNum = dwNum;}///线程是否运行BOOL CSerialPort::IsThreadRunning(){ return m_hThreadHandle != NULL;}///获得线程句柄HANDLE CSerialPort::GetThread(){ return m_hThreadHandle;}///设置要监视的事件, 打开前设置有效void CSerialPort::SetMaskEvent(DWORD dwEvent /*= DEFAULT_COM_MASK_EVENT*/){ m_dwMaskEvent = dwEvent;}///获得读缓冲区的字符数int CSerialPort::GetInputSize(){ COMSTAT Stat; DWORD dwError; return ::ClearCommError(m_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;}//////----------------------------------Operations----------------------------------///打开串口 缺省 9600, n, 8, 1BOOL CSerialPort::Open(DWORD dwPort){ return Open(dwPort, 9600);}///打开串口 缺省 baud_rate, n, 8, 1BOOL CSerialPort::Open(DWORD dwPort, DWORD dwBaudRate){ if(dwPort < 1 || dwPort > 1024) return FALSE; BindCommPort(dwPort); if(!OpenCommPort()) return FALSE; if(!SetupPort()) return FALSE; return SetState(dwBaudRate);}///打开串口, 使用类似"9600, n, 8, 1"的设置字符串设置串口BOOL CSerialPort::Open(DWORD dwPort, LPCTSTR lpszSetStr){ if(dwPort < 1 || dwPort > 1024) return FALSE; BindCommPort(dwPort); if(!OpenCommPort()) return FALSE; if(!SetupPort()) return FALSE; return SetState(lpszSetStr);}///读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据DWORD CSerialPort::Read(LPVOID Buffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer /*= TRUE*/){ if(!IsOpen()) return 0; COMSTAT Stat; DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, &Stat) && dwError > 0) { ::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR); return 0; } if(bOnlyGetBuffer) dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength; unsigned long uReadLength = 0; if(!::ReadFile(m_hCommHandle, Buffer, dwBufferLength, &uReadLength, &m_readOverlapped)) { if(::GetLastError() == ERROR_IO_PENDING) { while(!::GetOverlappedResult(m_hCommHandle, &m_readOverlapped, &uReadLength, TRUE)) { if(::GetLastError() != ERROR_IO_INCOMPLETE) { ::ClearCommError(m_hCommHandle, &dwError, &Stat); break; } } } else ::ClearCommError(m_hCommHandle, &dwError, &Stat); } return uReadLength;}///读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯DWORD CSerialPort::ReadString(char* szBuffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer /*= TRUE*/){ DWORD uReadLength = Read(szBuffer, dwBufferLength - 1, bOnlyGetBuffer); szBuffer[uReadLength] = '\0'; return uReadLength;}///写串口 可写任意数据 "abcd" or "x0x1x2"DWORD CSerialPort::Write(LPCVOID Buffer, DWORD dwBufferLength){ if(!IsOpen()) return 0; DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0) ::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); unsigned long uWriteLength = 0; if(!::WriteFile(m_hCommHandle, Buffer, dwBufferLength, &uWriteLength, &m_writeOverlapped)) if(::GetLastError() != ERROR_IO_PENDING) uWriteLength = 0; return uWriteLength;}///写串口 写ANSI C 模式字符串指针 DWORD CSerialPort::Write(const char *szBuffer){ assert(szBuffer); return (DWORD)Write((void *)szBuffer, strlen(szBuffer));}///读串口 同步应用DWORD CSerialPort::ReadSync(LPVOID Buffer, DWORD dwBufferLength){ if(!IsOpen()) return 0; DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0) { ::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR); return 0; } DWORD uReadLength = 0; ::ReadFile(m_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL); return uReadLength;}///写串口 同步应用DWORD CSerialPort::WriteSync(LPVOID Buffer, DWORD dwBufferLength){ if(!IsOpen()) return 0; DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0) ::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); unsigned long uWriteLength = 0; ::WriteFile(m_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL); return uWriteLength;}///写串口 szBuffer 可以输出格式字符串 包含缓冲区长度DWORD CSerialPort::Write(char *szBuffer, DWORD dwBufferLength, char * szFormat, ...){ if(!IsOpen()) return 0; va_list va; va_start(va, szFormat); vsnprintf_s(szBuffer, dwBufferLength, dwBufferLength, szFormat, va); va_end(va); return Write(szBuffer);} ///关闭串口 同时也关闭关联线程void CSerialPort::Close(){ if(IsOpen()) { PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); EndThread(); ::CloseHandle(m_hCommHandle); m_hCommHandle = INVALID_HANDLE_VALUE; }}///锁定资源void CSerialPort::Lock(){ ::EnterCriticalSection(&_Mutex);}void CSerialPort::Unlock(){ ::LeaveCriticalSection(&_Mutex);}///DTR 电平控制BOOL CSerialPort::SetDTR(BOOL OnOrOff){ return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETDTR : CLRDTR) != 0 : FALSE;}///RTS 电平控制BOOL CSerialPort::SetRTS(BOOL OnOrOff){ return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETRTS : CLRRTS) != 0 : FALSE;}//////BOOL CSerialPort::SetBreak(BOOL OnOrOff){ return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) != 0 : FALSE;}///辅助线程控制 建监视线程BOOL CSerialPort::BeginThread() { if(!IsThreadRunning()) { m_bRunFlag = TRUE; m_hThreadHandle = NULL;#ifdef _MT unsigned int id; m_hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, CommThreadProc, this, 0, &id);#else DWORD id; m_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0, &id); #endif return (m_hThreadHandle != NULL); } return FALSE;}///暂停监视线程BOOL CSerialPort::SuspendThread(){ return IsThreadRunning() ? ::SuspendThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE;}///恢复监视线程BOOL CSerialPort::ResumeThread(){ return IsThreadRunning() ? ::ResumeThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE;}///终止线程BOOL CSerialPort::EndThread(DWORD dwWaitTime /*= 100*/){ if(IsThreadRunning()) { m_bRunFlag = FALSE; ::SetCommMask(m_hCommHandle, 0); ::SetEvent(m_bWaitOverlapped.hEvent); if(::WaitForSingleObject(m_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0) if(!::TerminateThread(m_hThreadHandle, 0)) return FALSE; ::CloseHandle(m_hThreadHandle); ::ResetEvent(m_bWaitOverlapped.hEvent); m_hThreadHandle = NULL; return TRUE; } return FALSE;}///初始化void CSerialPort::Init() { memset(m_tszCommStr, 0, NAMEBUF_SIZE*sizeof(TCHAR)); memset(&m_DCB, 0, sizeof(m_DCB)); m_DCB.DCBlength = sizeof(m_DCB); m_hCommHandle = INVALID_HANDLE_VALUE; memset(&m_readOverlapped, 0, sizeof(m_readOverlapped)); memset(&m_writeOverlapped, 0, sizeof(m_writeOverlapped)); m_readOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); assert(m_readOverlapped.hEvent != NULL); m_writeOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); assert(m_writeOverlapped.hEvent != NULL); m_hNotifyWnd = NULL; m_dwNotifyNum = 0; m_dwMaskEvent = DEFAULT_COM_MASK_EVENT; m_hThreadHandle = NULL; m_dwPort = 0; memset(&m_bWaitOverlapped, 0, sizeof(m_bWaitOverlapped)); m_bWaitOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); assert(m_bWaitOverlapped.hEvent != NULL); ::InitializeCriticalSection(&_Mutex);} ///析构void CSerialPort::Destroy(){ if(m_readOverlapped.hEvent != NULL) CloseHandle(m_readOverlapped.hEvent); if(m_writeOverlapped.hEvent != NULL) CloseHandle(m_writeOverlapped.hEvent); if(m_bWaitOverlapped.hEvent != NULL) CloseHandle(m_bWaitOverlapped.hEvent); ::DeleteCriticalSection(&_Mutex);}///绑定串口void CSerialPort::BindCommPort(DWORD dwPort){ assert(dwPort >= 1 && dwPort <= 1024); TCHAR p[5]; TCHAR* lpszCom = _T("\\\\.\\COM"); m_dwPort = dwPort; _tcscpy_s(m_tszCommStr, _tcslen(lpszCom), lpszCom); _ltot_s(m_dwPort, p, 5, 10); _tcscat_s(m_tszCommStr, NAMEBUF_SIZE, p);}///打开串口 BOOL CSerialPort::OpenCommPort(){ if(IsOpen()) Close(); m_hCommHandle = ::CreateFile( m_tszCommStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | m_dwIOMode, NULL ); if(m_bAutoBeginThread) { if(IsOpen() && BeginThread()) return TRUE; else { Close(); ///创建线程失败 return FALSE; } } return IsOpen();}///设置串口BOOL CSerialPort::SetupPort(){ if(!IsOpen()) return FALSE; if(!::SetupComm(m_hCommHandle, 4096, 4096)) return FALSE; if(!::GetCommTimeouts(m_hCommHandle, &m_CO)) return FALSE; m_CO.ReadIntervalTimeout = 0; m_CO.ReadTotalTimeoutMultiplier = 1; m_CO.ReadTotalTimeoutConstant = 1000; m_CO.WriteTotalTimeoutMultiplier = 1; m_CO.WriteTotalTimeoutConstant = 1000; if(!::SetCommTimeouts(m_hCommHandle, &m_CO)) return FALSE; if(!::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )) return FALSE; return TRUE;} //////---------------------------------------threads callback-----------------------------------------------------///线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展 void CSerialPort::OnReceive()///EV_RXCHAR{ if(::IsWindow(m_hNotifyWnd)) ::PostMessage(m_hNotifyWnd, ON_COM_RECEIVE, WPARAM(m_dwPort), LPARAM(0));}void CSerialPort::OnDSR(){ if(::IsWindow(m_hNotifyWnd)) { DWORD Status; if(GetCommModemStatus(m_hCommHandle, &Status)) ::PostMessage(m_hNotifyWnd, ON_COM_DSR, WPARAM(m_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0)); }}void CSerialPort::OnCTS(){ if(::IsWindow(m_hNotifyWnd)) { DWORD Status; if(GetCommModemStatus(m_hCommHandle, &Status)) ::PostMessage(m_hNotifyWnd, ON_COM_CTS, WPARAM(m_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0)); }}void CSerialPort::OnBreak(){ if(::IsWindow(m_hNotifyWnd)) { ::PostMessage(m_hNotifyWnd, ON_COM_BREAK , WPARAM(m_dwPort), LPARAM(0)); }}void CSerialPort::OnTXEmpty(){ if(::IsWindow(m_hNotifyWnd)) ::PostMessage(m_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(m_dwPort), LPARAM(0));}void CSerialPort::OnError(){ DWORD dwError; ::ClearCommError(m_hCommHandle, &dwError, NULL); if(::IsWindow(m_hNotifyWnd)) ::PostMessage(m_hNotifyWnd, ON_COM_ERROR, WPARAM(m_dwPort), LPARAM(dwError));}void CSerialPort::OnRing(){ if(::IsWindow(m_hNotifyWnd)) ::PostMessage(m_hNotifyWnd, ON_COM_RING, WPARAM(m_dwPort), LPARAM(0));}void CSerialPort::OnRLSD(){ if(::IsWindow(m_hNotifyWnd)) ::PostMessage(m_hNotifyWnd, ON_COM_RLSD, WPARAM(m_dwPort), LPARAM(0));}DWORD CSerialPort::ThreadFunc(){ if(!::SetCommMask(m_hCommHandle, m_dwMaskEvent)) { TCHAR tszBuffer[256]; _sntprintf_s(tszBuffer, 255, 255, _T("%s(%d) : COM%d Call WINAPI SetCommMask(%x, %x) Fail, thread work invalid! GetLastError() = %d;"), __FILE__, __LINE__, m_dwPort, m_hCommHandle, m_dwMaskEvent, GetLastError()); ::MessageBox(NULL, tszBuffer, _T("Class CSerialPort"), MB_OK); return 1; } COMSTAT Stat; DWORD dwError; for(DWORD dwLength, dwMask = 0; m_bRunFlag && IsOpen(); dwMask = 0) { if(!::WaitCommEvent(m_hCommHandle, &dwMask, &m_bWaitOverlapped)) { if(::GetLastError() == ERROR_IO_PENDING)////// asynchronous ::GetOverlappedResult(m_hCommHandle, &m_bWaitOverlapped, &dwLength, TRUE); else continue; } if(dwMask == 0) continue; switch(dwMask) { case EV_RXCHAR : ::ClearCommError(m_hCommHandle, &dwError, &Stat); if(Stat.cbInQue >= m_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; case EV_ERR : OnError(); break; }///case }///for return 0;}#ifdef _MTUINT APIENTRY CSerialPort::CommThreadProc(LPVOID lpPara)#elseDWORD WINAPI CSerialPort::CommThreadProc(LPVOID lpPara)#endif{ return ( (CSerialPort *)lpPara )->ThreadFunc();} TO :kyokof 你真好 能帮我解决个问题吗 我先谢谢你了 还是下拉菜单 就是代表着各种颜色 windows api 开发 大概流程:1、CreateFile 打开串行口2、SetCommState 配置串行口3、WriteFile 发送数据4、ReadFile 接收数据5、CloseHandle 关闭串行口初学者建议采用同步方式(阻塞方式),比较容易理解。这就是串行口这块的东西,看你 VC++ 基础怎么样了,基础好的话应该很快的。入门文章如下:http://www.vckbase.com/document/viewdoc/?id=1114我就是看这篇文章入门的。 求助?Direct Meida Object(DMO) 解码 wma [求助]关于DLL中使用资源的问题 登录界面想要记住用户名,不用数据库,怎么记住? 一个比较低的问题。 关于Excel的一个问题 CStatic? (100 points) VC有没有做报表的工具?哪里下栽! internet上数据库应用问题 网络程序报告socket notification sink错误??? 对话框如何隐藏? 我的VC6的控件工具栏上怎么没有PictureBox控件? DX中怎么都是3D的
晕倒个个都是
Page Not Found呀
#ifndef _SERIALPORT_H//SerialPort.h
#define _SERIALPORT_H#pragma once#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include <tchar.h>
#include "FrameDef.h"
#define NAMEBUF_SIZE 64 //存放串口名字的数组大小//送到窗口的消息 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 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 | EV_RLSDclass DLLDIR CSerialPort
{
public:
struct InnerLock
{
CSerialPort* ptr; InnerLock(CSerialPort* p) : ptr(p)
{
ptr->Lock();
}
~InnerLock()
{
ptr->Unlock();
}
}; //------------------------------Construction-----------------------------------
//第1个参数为是否在打开串口时启动监视线程, 第2个参数为IO方式 阻塞方式(0)/ 异步重叠方式(默认)
CSerialPort(BOOL bAutoBeginThread = TRUE, DWORD dwIOMode = FILE_FLAG_OVERLAPPED);
virtual ~CSerialPort(); //----------------------------------Attributes----------------------------------
inline BOOL IsOpen(); //判断串口是或打开
operator BOOL (); //判断串口是或打开
HANDLE GetHandle(); //获得串口句炳
operator HANDLE(); //获得串口句炳
const int GetPortID(); //获得串口序号
LPCTSTR GetPortName(); //获得串口全名
DCB *GetState(); //获得串口参数 DCB
BOOL SetState(DCB *pdcb = NULL); //设置串口参数 DCB
BOOL SetState(LPCTSTR lpszSetStr); //设置串口参数:波特率,停止位,等 支持设置字符串 "9600, n, 8, 1" //设置串口参数:波特率,停止位,等
BOOL SetState(DWORD dwBaudRate,
DWORD dwByteSize = 8,
DWORD dwParity = NOPARITY,
DWORD dwStopBits = ONESTOPBIT); LPCOMMTIMEOUTS GetTimeouts(void); //获得超时结构
BOOL SetTimeouts(LPCOMMTIMEOUTS lpCO); //设置超时
BOOL SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize); //设置串口的I/O缓冲区大小
void ClearInputBuffer(); //清除接受缓冲区
void ClearOutputBuffer(); //清除发送缓冲区
inline void SetWnd(HWND hWnd); //关联消息的窗口句柄
inline void SetNotifyNum(DWORD dwNum); //设定发送通知, 接受字符最小值
inline BOOL IsThreadRunning(); //线程是否运行
inline HANDLE GetThread(); //获得线程句柄
void SetMaskEvent(DWORD dwEvent = DEFAULT_COM_MASK_EVENT); //设置要监视的事件, 打开前设置有效
int GetInputSize(); //获得读缓冲区的字符数 //----------------------------------Operations----------------------------------
BOOL Open(DWORD dwPort); //打开串口 缺省 9600, n, 8, 1
BOOL Open(DWORD dwPort, DWORD dwBaudRate); //打开串口 缺省 baud_rate, n, 8, 1
BOOL Open(DWORD dwPort, LPCTSTR lpszSetStr); //打开串口, 使用类似"9600, n, 8, 1"的设置字符串设置串口
DWORD Read(LPVOID Buffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer = TRUE); //读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据
DWORD ReadString(char *szBuffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer = TRUE); //读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯
DWORD Write(LPCVOID Buffer, DWORD dwBufferLength); //写串口 可写任意数据 "abcd" or "x0x1x2"
DWORD Write(const char *szBuffer); //写串口 写ANSI C 模式字符串指针
DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength); //读串口 同步应用
DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength); //写串口 同步应用
DWORD Write(char *szBuffer, DWORD dwBufferLength, char * szFormat, ...); //写串口 szBuffer 可以输出格式字符串 包含缓冲区长度 virtual void Close(); //关闭串口 同时也关闭关联线程
void Lock(); //锁定资源
void Unlock(); BOOL SetDTR(BOOL OnOrOff); //DTR 电平控制
BOOL SetRTS(BOOL OnOrOff); //RTS 电平控制
BOOL SetBreak(BOOL OnOrOff);
BOOL BeginThread(); //辅助线程控制 建监视线程
inline BOOL SuspendThread(); //暂停监视线程
inline BOOL ResumeThread(); //恢复监视线程
BOOL EndThread(DWORD dwWaitTime = 100); //终止线程protected: volatile DWORD m_dwPort; //串口号
volatile HANDLE m_hCommHandle; //串口句柄
TCHAR m_tszCommStr[NAMEBUF_SIZE]; //保存COM1类似的字符串 DCB m_DCB; //波特率,停止位,等
COMMTIMEOUTS m_CO; //超时结构 DWORD m_dwIOMode; // 0 同步 默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步
OVERLAPPED m_readOverlapped; // 重叠I/O
OVERLAPPED m_writeOverlapped; volatile HANDLE m_hThreadHandle; //辅助线程
volatile HWND m_hNotifyWnd; // 通知窗口
volatile DWORD m_dwNotifyNum; //接受多少字节(>=m_dwNotifyNum)发送通知消息
volatile DWORD m_dwMaskEvent; //监视的事件
volatile BOOL m_bRunFlag; //线程运行循环标志
BOOL m_bAutoBeginThread; //Open() 自动 BeginThread();
OVERLAPPED m_bWaitOverlapped; //WaitCommEvent use
virtual void Init(); //初始化
virtual void Destroy(); //析构
void BindCommPort(DWORD dwPort); //绑定串口
virtual BOOL OpenCommPort(); //打开串口
virtual BOOL SetupPort(); //设置串口
//---------------------------------------threads callback-----------------------------------------------------
//线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展
virtual void OnReceive();
virtual void OnDSR();
virtual void OnCTS();
virtual void OnBreak();
virtual void OnTXEmpty();
virtual void OnError();
virtual void OnRing();
virtual void OnRLSD();
virtual DWORD ThreadFunc();private: //the function protected CSerialPort(const CSerialPort&);
CSerialPort &operator = (const CSerialPort&);
CRITICAL_SECTION _Mutex; //base function for thread
#ifdef _MT
static UINT APIENTRY CommThreadProc(LPVOID lpPara);
#else
static DWORD WINAPI CommThreadProc(LPVOID lpPara);
#endif};#endif //_SERIALPORT_H
#include "stdafx.h"
#include "SerialPort.h"CSerialPort::CSerialPort(BOOL bAutoBeginThread /*= TRUE*/,
DWORD dwIOMode /*= FILE_FLAG_OVERLAPPED*/)
: m_dwIOMode(dwIOMode), m_bAutoBeginThread(bAutoBeginThread)
{
Init();
}CSerialPort::~CSerialPort(void)
{
Close();
Destroy();
}BOOL CSerialPort::IsOpen()
{
return m_hCommHandle != INVALID_HANDLE_VALUE;
}CSerialPort::operator BOOL ()
{
return m_hCommHandle != INVALID_HANDLE_VALUE;
}HANDLE CSerialPort::GetHandle() //获得串口句炳
{
return m_hCommHandle;
}
CSerialPort::operator HANDLE() //获得串口句炳
{
return m_hCommHandle;
}const int CSerialPort::GetPortID() //获得串口序号
{
return m_dwPort;
}LPCTSTR CSerialPort::GetPortName() //获得串口全名
{
return m_tszCommStr;
}DCB* CSerialPort::GetState() //获得串口参数 DCB
{
return IsOpen() && ::GetCommState(m_hCommHandle, &m_DCB) == TRUE ? &m_DCB : NULL;
}///设置串口参数 DCB
BOOL CSerialPort::SetState(DCB *pdcb /*= NULL*/)
{
return IsOpen() ? ::SetCommState(m_hCommHandle, pdcb == NULL ? &m_DCB : pdcb) == TRUE : FALSE;
}///设置串口参数:波特率,停止位,等 支持设置字符串 "9600, n, 8, 1"
BOOL CSerialPort::SetState(LPCTSTR lpszSetStr)
{
if(IsOpen())
{
if(::GetCommState(m_hCommHandle, &m_DCB) != TRUE)
return FALSE;
if(::BuildCommDCB(lpszSetStr, &m_DCB) != TRUE)
return FALSE;
return ::SetCommState(m_hCommHandle, &m_DCB) == TRUE;
}
return FALSE;
}///设置串口参数:波特率,停止位,等
BOOL CSerialPort::SetState(DWORD dwBaudRate,
DWORD dwByteSize /*= 8*/,
DWORD dwParity /*= NOPARITY*/,
DWORD dwStopBits /*= ONESTOPBIT*/)
{
if(IsOpen())
{
if(::GetCommState(m_hCommHandle, &m_DCB) != TRUE)
return FALSE;
m_DCB.BaudRate = dwBaudRate;
m_DCB.ByteSize = (unsigned char)dwByteSize;
m_DCB.Parity = (unsigned char)dwParity;
m_DCB.StopBits = (unsigned char)dwStopBits;
return ::SetCommState(m_hCommHandle, &m_DCB) == TRUE;
}
return FALSE;
}///获得超时结构
LPCOMMTIMEOUTS CSerialPort::GetTimeouts(void)
{
return IsOpen() && ::GetCommTimeouts(m_hCommHandle, &m_CO) == TRUE ? &m_CO : NULL;
}///设置超时
BOOL CSerialPort::SetTimeouts(LPCOMMTIMEOUTS lpCO)
{
return IsOpen() ? ::SetCommTimeouts(m_hCommHandle, lpCO) == TRUE : FALSE;
}///设置串口的I/O缓冲区大小
BOOL CSerialPort::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
{
return IsOpen() ? ::SetupComm(m_hCommHandle, dwInputSize, dwOutputSize) == TRUE : FALSE;
}///清除接受缓冲区
void CSerialPort::ClearInputBuffer()
{
if(IsOpen())
::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR );
}///清除发送缓冲区
void CSerialPort::ClearOutputBuffer()
{
if(IsOpen())
::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR );
}///关联消息的窗口句柄
void CSerialPort::SetWnd(HWND hWnd)
{
assert(::IsWindow(hWnd));
m_hNotifyWnd = hWnd;
}///设定发送通知, 接受字符最小值
void CSerialPort::SetNotifyNum(DWORD dwNum)
{
m_dwNotifyNum = dwNum;
}///线程是否运行
BOOL CSerialPort::IsThreadRunning()
{
return m_hThreadHandle != NULL;
}///获得线程句柄
HANDLE CSerialPort::GetThread()
{
return m_hThreadHandle;
}///设置要监视的事件, 打开前设置有效
void CSerialPort::SetMaskEvent(DWORD dwEvent /*= DEFAULT_COM_MASK_EVENT*/)
{
m_dwMaskEvent = dwEvent;
}///获得读缓冲区的字符数
int CSerialPort::GetInputSize()
{
COMSTAT Stat;
DWORD dwError; return ::ClearCommError(m_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;
}//////----------------------------------Operations----------------------------------
///打开串口 缺省 9600, n, 8, 1
BOOL CSerialPort::Open(DWORD dwPort)
{
return Open(dwPort, 9600);
}///打开串口 缺省 baud_rate, n, 8, 1
BOOL CSerialPort::Open(DWORD dwPort, DWORD dwBaudRate)
{
if(dwPort < 1 || dwPort > 1024)
return FALSE; BindCommPort(dwPort); if(!OpenCommPort())
return FALSE; if(!SetupPort())
return FALSE; return SetState(dwBaudRate);
}///打开串口, 使用类似"9600, n, 8, 1"的设置字符串设置串口
BOOL CSerialPort::Open(DWORD dwPort, LPCTSTR lpszSetStr)
{
if(dwPort < 1 || dwPort > 1024)
return FALSE; BindCommPort(dwPort); if(!OpenCommPort())
return FALSE; if(!SetupPort())
return FALSE; return SetState(lpszSetStr);
}///读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据
DWORD CSerialPort::Read(LPVOID Buffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer /*= TRUE*/)
{
if(!IsOpen())
return 0; COMSTAT Stat;
DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, &Stat) && dwError > 0)
{
::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
} if(bOnlyGetBuffer)
dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength; unsigned long uReadLength = 0;
if(!::ReadFile(m_hCommHandle, Buffer, dwBufferLength, &uReadLength, &m_readOverlapped))
{
if(::GetLastError() == ERROR_IO_PENDING)
{
while(!::GetOverlappedResult(m_hCommHandle, &m_readOverlapped, &uReadLength, TRUE))
{
if(::GetLastError() != ERROR_IO_INCOMPLETE)
{
::ClearCommError(m_hCommHandle, &dwError, &Stat);
break;
}
}
}
else
::ClearCommError(m_hCommHandle, &dwError, &Stat);
} return uReadLength;
}///读取串口 dwBufferLength - 1 个字符到 szBuffer 返回ANSI C 模式字符串指针 适合一般字符通讯
DWORD CSerialPort::ReadString(char* szBuffer, DWORD dwBufferLength, BOOL bOnlyGetBuffer /*= TRUE*/)
{
DWORD uReadLength = Read(szBuffer, dwBufferLength - 1, bOnlyGetBuffer);
szBuffer[uReadLength] = '\0';
return uReadLength;
}///写串口 可写任意数据 "abcd" or "x0x1x2"
DWORD CSerialPort::Write(LPCVOID Buffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0; DWORD dwError; if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0)
::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); unsigned long uWriteLength = 0; if(!::WriteFile(m_hCommHandle, Buffer, dwBufferLength, &uWriteLength, &m_writeOverlapped))
if(::GetLastError() != ERROR_IO_PENDING)
uWriteLength = 0;
return uWriteLength;
}///写串口 写ANSI C 模式字符串指针
DWORD CSerialPort::Write(const char *szBuffer)
{
assert(szBuffer);
return (DWORD)Write((void *)szBuffer, strlen(szBuffer));
}///读串口 同步应用
DWORD CSerialPort::ReadSync(LPVOID Buffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0; DWORD dwError;
if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0)
{
::PurgeComm(m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
} DWORD uReadLength = 0;
::ReadFile(m_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL);
return uReadLength;
}///写串口 同步应用
DWORD CSerialPort::WriteSync(LPVOID Buffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0; DWORD dwError;
if(::ClearCommError(m_hCommHandle, &dwError, NULL) && dwError > 0)
::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); unsigned long uWriteLength = 0;
::WriteFile(m_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL);
return uWriteLength;
}///写串口 szBuffer 可以输出格式字符串 包含缓冲区长度
DWORD CSerialPort::Write(char *szBuffer, DWORD dwBufferLength, char * szFormat, ...)
{
if(!IsOpen())
return 0; va_list va;
va_start(va, szFormat);
vsnprintf_s(szBuffer, dwBufferLength, dwBufferLength, szFormat, va);
va_end(va); return Write(szBuffer);
}
///关闭串口 同时也关闭关联线程
void CSerialPort::Close()
{
if(IsOpen())
{
PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR); EndThread();
::CloseHandle(m_hCommHandle); m_hCommHandle = INVALID_HANDLE_VALUE;
}
}///锁定资源
void CSerialPort::Lock()
{
::EnterCriticalSection(&_Mutex);
}void CSerialPort::Unlock()
{
::LeaveCriticalSection(&_Mutex);
}///DTR 电平控制
BOOL CSerialPort::SetDTR(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETDTR : CLRDTR) != 0 : FALSE;
}///RTS 电平控制
BOOL CSerialPort::SetRTS(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETRTS : CLRRTS) != 0 : FALSE;
}//////
BOOL CSerialPort::SetBreak(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(m_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) != 0 : FALSE;
}///辅助线程控制 建监视线程
BOOL CSerialPort::BeginThread()
{
if(!IsThreadRunning())
{
m_bRunFlag = TRUE;
m_hThreadHandle = NULL;#ifdef _MT
unsigned int id;
m_hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, CommThreadProc, this, 0, &id);
#else
DWORD id;
m_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0, &id);
#endif return (m_hThreadHandle != NULL);
}
return FALSE;
}///暂停监视线程
BOOL CSerialPort::SuspendThread()
{
return IsThreadRunning() ? ::SuspendThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE;
}///恢复监视线程
BOOL CSerialPort::ResumeThread()
{
return IsThreadRunning() ? ::ResumeThread(m_hThreadHandle) != 0xFFFFFFFF : FALSE;
}///终止线程
BOOL CSerialPort::EndThread(DWORD dwWaitTime /*= 100*/)
{
if(IsThreadRunning())
{
m_bRunFlag = FALSE;
::SetCommMask(m_hCommHandle, 0);
::SetEvent(m_bWaitOverlapped.hEvent);
if(::WaitForSingleObject(m_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0)
if(!::TerminateThread(m_hThreadHandle, 0))
return FALSE; ::CloseHandle(m_hThreadHandle);
::ResetEvent(m_bWaitOverlapped.hEvent); m_hThreadHandle = NULL; return TRUE;
}
return FALSE;
}///初始化
void CSerialPort::Init()
{
memset(m_tszCommStr, 0, NAMEBUF_SIZE*sizeof(TCHAR));
memset(&m_DCB, 0, sizeof(m_DCB));
m_DCB.DCBlength = sizeof(m_DCB);
m_hCommHandle = INVALID_HANDLE_VALUE; memset(&m_readOverlapped, 0, sizeof(m_readOverlapped));
memset(&m_writeOverlapped, 0, sizeof(m_writeOverlapped)); m_readOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(m_readOverlapped.hEvent != NULL); m_writeOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(m_writeOverlapped.hEvent != NULL); m_hNotifyWnd = NULL;
m_dwNotifyNum = 0;
m_dwMaskEvent = DEFAULT_COM_MASK_EVENT;
m_hThreadHandle = NULL;
m_dwPort = 0; memset(&m_bWaitOverlapped, 0, sizeof(m_bWaitOverlapped));
m_bWaitOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(m_bWaitOverlapped.hEvent != NULL); ::InitializeCriticalSection(&_Mutex);
} ///析构
void CSerialPort::Destroy()
{
if(m_readOverlapped.hEvent != NULL)
CloseHandle(m_readOverlapped.hEvent); if(m_writeOverlapped.hEvent != NULL)
CloseHandle(m_writeOverlapped.hEvent); if(m_bWaitOverlapped.hEvent != NULL)
CloseHandle(m_bWaitOverlapped.hEvent); ::DeleteCriticalSection(&_Mutex);
}///绑定串口
void CSerialPort::BindCommPort(DWORD dwPort)
{
assert(dwPort >= 1 && dwPort <= 1024); TCHAR p[5];
TCHAR* lpszCom = _T("\\\\.\\COM"); m_dwPort = dwPort;
_tcscpy_s(m_tszCommStr, _tcslen(lpszCom), lpszCom);
_ltot_s(m_dwPort, p, 5, 10);
_tcscat_s(m_tszCommStr, NAMEBUF_SIZE, p);
}///打开串口
BOOL CSerialPort::OpenCommPort()
{
if(IsOpen())
Close(); m_hCommHandle = ::CreateFile(
m_tszCommStr,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | m_dwIOMode,
NULL
); if(m_bAutoBeginThread)
{
if(IsOpen() && BeginThread())
return TRUE;
else
{
Close(); ///创建线程失败
return FALSE;
}
}
return IsOpen();
}///设置串口
BOOL CSerialPort::SetupPort()
{
if(!IsOpen())
return FALSE;
if(!::SetupComm(m_hCommHandle, 4096, 4096))
return FALSE;
if(!::GetCommTimeouts(m_hCommHandle, &m_CO))
return FALSE;
m_CO.ReadIntervalTimeout = 0;
m_CO.ReadTotalTimeoutMultiplier = 1;
m_CO.ReadTotalTimeoutConstant = 1000;
m_CO.WriteTotalTimeoutMultiplier = 1;
m_CO.WriteTotalTimeoutConstant = 1000;
if(!::SetCommTimeouts(m_hCommHandle, &m_CO))
return FALSE;
if(!::PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
return FALSE; return TRUE;
} //////---------------------------------------threads callback-----------------------------------------------------
///线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展
void CSerialPort::OnReceive()///EV_RXCHAR
{
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, ON_COM_RECEIVE, WPARAM(m_dwPort), LPARAM(0));
}void CSerialPort::OnDSR()
{
if(::IsWindow(m_hNotifyWnd))
{
DWORD Status;
if(GetCommModemStatus(m_hCommHandle, &Status))
::PostMessage(m_hNotifyWnd, ON_COM_DSR, WPARAM(m_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0));
}
}void CSerialPort::OnCTS()
{
if(::IsWindow(m_hNotifyWnd))
{
DWORD Status;
if(GetCommModemStatus(m_hCommHandle, &Status))
::PostMessage(m_hNotifyWnd, ON_COM_CTS, WPARAM(m_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0));
}
}void CSerialPort::OnBreak()
{
if(::IsWindow(m_hNotifyWnd))
{
::PostMessage(m_hNotifyWnd, ON_COM_BREAK , WPARAM(m_dwPort), LPARAM(0));
}
}void CSerialPort::OnTXEmpty()
{
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(m_dwPort), LPARAM(0));
}void CSerialPort::OnError()
{
DWORD dwError;
::ClearCommError(m_hCommHandle, &dwError, NULL);
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, ON_COM_ERROR, WPARAM(m_dwPort), LPARAM(dwError));
}void CSerialPort::OnRing()
{
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, ON_COM_RING, WPARAM(m_dwPort), LPARAM(0));
}void CSerialPort::OnRLSD()
{
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, ON_COM_RLSD, WPARAM(m_dwPort), LPARAM(0));
}DWORD CSerialPort::ThreadFunc()
{
if(!::SetCommMask(m_hCommHandle, m_dwMaskEvent))
{
TCHAR tszBuffer[256];
_sntprintf_s(tszBuffer,
255,
255,
_T("%s(%d) : COM%d Call WINAPI SetCommMask(%x, %x) Fail, thread work invalid! GetLastError() = %d;"),
__FILE__,
__LINE__,
m_dwPort,
m_hCommHandle,
m_dwMaskEvent,
GetLastError());
::MessageBox(NULL, tszBuffer, _T("Class CSerialPort"), MB_OK);
return 1;
} COMSTAT Stat;
DWORD dwError; for(DWORD dwLength, dwMask = 0; m_bRunFlag && IsOpen(); dwMask = 0)
{
if(!::WaitCommEvent(m_hCommHandle, &dwMask, &m_bWaitOverlapped))
{
if(::GetLastError() == ERROR_IO_PENDING)////// asynchronous
::GetOverlappedResult(m_hCommHandle, &m_bWaitOverlapped, &dwLength, TRUE);
else
continue;
} if(dwMask == 0)
continue; switch(dwMask)
{
case EV_RXCHAR :
::ClearCommError(m_hCommHandle, &dwError, &Stat);
if(Stat.cbInQue >= m_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; case EV_ERR :
OnError();
break; }///case
}///for
return 0;
}#ifdef _MT
UINT APIENTRY CSerialPort::CommThreadProc(LPVOID lpPara)
#else
DWORD WINAPI CSerialPort::CommThreadProc(LPVOID lpPara)
#endif
{
return ( (CSerialPort *)lpPara )->ThreadFunc();
}
你真好 能帮我解决个问题吗 我先谢谢你了
就是代表着各种颜色
windows api 开发
大概流程:1、CreateFile 打开串行口2、SetCommState 配置串行口3、WriteFile 发送数据4、ReadFile 接收数据5、CloseHandle 关闭串行口
初学者建议采用同步方式(阻塞方式),比较容易理解。
这就是串行口这块的东西,看你 VC++ 基础怎么样了,基础好的话应该很快的。
入门文章如下:http://www.vckbase.com/document/viewdoc/?id=1114
我就是看这篇文章入门的。