最近做了一个串口通信相关的项目。主要涉及到同步串口通信。把代码保存下来以便以后使用。同时也能和大家一起共享,希望对大家有所帮助.
头文件:SerialPort.h
1 #pragma once 2 3 #include <Windows.h> 4 #include "DataTypes.h" 5 6 7 #define COM_BUFFER_LENGTH 409600 8 9 class CSerialPort 10 { 11 public: 12 CSerialPort(void); 13 ~CSerialPort(void); 14 public: 15 bool InitPort(UINT nPortNo=1,UINT baud=CBR_115200,char parity='N',UINT databits=8,UINT stopbits=1,DWORD dwCommEvents=EV_RXCHAR); 16 bool WriteData(char* pData,int length);//向串口中写入数据 17 UINT GetBytesInCom();//获取串口缓冲区中的字节数 18 bool ReadChar(char &cRecved);//从串口缓冲区读取一个字节的数据 19 public: 20 bool OpenPort(UINT portNo);//打开串口 21 void ClosePort();//关闭串口 22 bool ReadData(char* pData); 23 char* m_data; 24 public: 25 HANDLE m_hCom;//串口句柄 26 CRITICAL_SECTION m_cs; 27 };
实现文件:SerialPort.cpp
1 #include "StdAfx.h" 2 #include "SerialPort.h" 3 #include<iostream> 4 #include <process.h> 5 6 UINT const SLEEP_TIMEINTERVAL=5;//串口无数据时,休眠,单位是s 7 8 CSerialPort::CSerialPort(void) 9 { 10 m_hCom=INVALID_HANDLE_VALUE; 11 m_data=new char[COM_BUFFER_LENGTH]; 12 memset(m_data,0,COM_BUFFER_LENGTH); 13 InitializeCriticalSection(&m_cs); 14 } 15 16 CSerialPort::~CSerialPort(void) 17 { 18 if (m_hCom!=INVALID_HANDLE_VALUE) 19 { 20 CloseHandle(m_hCom); 21 } 22 if (m_data!=NULL) 23 { 24 delete[] m_data; 25 } 26 DeleteCriticalSection(&m_cs); 27 } 28 29 bool CSerialPort::InitPort(UINT nPortNo,UINT baud,char parity,UINT databits,UINT stopbits,DWORD dwCommEvents) 30 { 31 char szDCBparam[50]; 32 sprintf_s(szDCBparam,"baud=%d parity=%c data=%d stop=%d",CBR_115200,parity,databits,stopbits); 33 34 if (OpenPort(nPortNo)==false) 35 { 36 return false; 37 } 38 39 EnterCriticalSection(&m_cs); 40 41 BOOL bIsSuccess=TRUE; 42 43 if (bIsSuccess) 44 { 45 bIsSuccess=SetupComm(m_hCom,COM_BUFFER_LENGTH,COM_BUFFER_LENGTH);//输入输出缓冲区设置为4k 46 } 47 48 //设置串口超时时间。全为0,则不使用串口超时设置,超时 49 COMMTIMEOUTS comTms; 50 comTms.ReadIntervalTimeout=MAXWORD; 51 comTms.ReadTotalTimeoutConstant=1000; 52 comTms.ReadTotalTimeoutMultiplier=1000; 53 comTms.WriteTotalTimeoutConstant=1000; 54 comTms.WriteTotalTimeoutMultiplier=1000; 55 if (bIsSuccess) 56 { 57 bIsSuccess=SetCommTimeouts(m_hCom,&comTms); 58 } 59 60 //设置DCB结构 61 DCB dcb; 62 if (bIsSuccess) 63 { 64 bIsSuccess=GetCommState(m_hCom,&dcb); 65 dcb.BaudRate=128000; 66 dcb.ByteSize=8; 67 dcb.Parity=NOPARITY; 68 dcb.StopBits=stopbits; 69 } 70 71 if (bIsSuccess) 72 { 73 //使用dcb参数配置串口状态 74 bIsSuccess=SetCommState(m_hCom,&dcb); 75 } 76 77 //清空串口缓冲区 78 PurgeComm(m_hCom,PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR); 79 LeaveCriticalSection(&m_cs); 80 81 return (bIsSuccess==TRUE); 82 } 83 84 85 bool CSerialPort::OpenPort(UINT portNo) 86 { 87 EnterCriticalSection(&m_cs); 88 char szPort[50]; 89 sprintf_s(szPort,"COM%d",portNo); 90 91 m_hCom=CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); 92 if (m_hCom==INVALID_HANDLE_VALUE) 93 { 94 LeaveCriticalSection(&m_cs); 95 return false; 96 } 97 LeaveCriticalSection(&m_cs); 98 return true; 99 } 100 101 void CSerialPort::ClosePort() 102 { 103 if (m_hCom!=INVALID_HANDLE_VALUE) 104 { 105 CloseHandle(m_hCom); 106 m_hCom=INVALID_HANDLE_VALUE; 107 } 108 } 109 110 bool CSerialPort::WriteData(char* pData,int length) 111 { 112 BOOL bResult=TRUE; 113 DWORD bytesToSend=0; 114 if (m_hCom==INVALID_HANDLE_VALUE) 115 { 116 return false; 117 } 118 EnterCriticalSection(&m_cs); 119 120 bResult=WriteFile(m_hCom,pData,(unsigned int)length,&bytesToSend,NULL); 121 if (bResult==FALSE) 122 { 123 DWORD dwErr=GetLastError(); 124 PurgeComm(m_hCom,PURGE_TXABORT|PURGE_TXCLEAR); 125 LeaveCriticalSection(&m_cs); 126 return false; 127 } 128 LeaveCriticalSection(&m_cs); 129 return true; 130 } 131 132 133 bool CSerialPort::ReadData(char* pData) 134 { 135 DWORD bytes=0; 136 DWORD err=0; 137 COMSTAT cmt={0}; 138 DWORD readSize=0; 139 bool bResult=false; 140 int bufferLen=COM_BUFFER_LENGTH; 141 int offset=0; 142 143 //轮询读取串口数据 144 while (true) 145 { 146 //设置读取1个字节数据,当缓存中有数据到达时则会立即返回,否则直到超时 147 bResult=ReadFile(m_hCom,m_data+offset,1,&readSize,NULL); 148 if (bResult==false||readSize==0) 149 { 150 break; 151 } 152 offset+=readSize; 153 154 //若有数据到达,则bResult为true,同时readsize等于1 155 if (bResult==true&&readSize==1) 156 { 157 int readLen=0; 158 ClearCommError(m_hCom,&err,&cmt); 159 readLen=((int)cmt.cbInQue>bufferLen) ? bufferLen : cmt.cbInQue; 160 if (readLen>0) 161 { 162 bResult=ReadFile(m_hCom,m_data+offset,readLen,&readSize,NULL); 163 if (bResult==false||readSize<COM_BUFFER_LENGTH) 164 { 165 break; 166 } 167 offset+=readSize; 168 PurgeComm(m_hCom,PURGE_RXABORT|PURGE_RXCLEAR); 169 } 170 } 171 } 172 memcpy(pData,m_data,COM_BUFFER_LENGTH); 173 return true; 174 }