同步串口通信代码

最近做了一个串口通信相关的项目。主要涉及到同步串口通信。把代码保存下来以便以后使用。同时也能和大家一起共享,希望对大家有所帮助.

头文件: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 }
原文地址:https://www.cnblogs.com/HPAHPA/p/8337693.html