• 同步串口通信代码


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

    头文件: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 }
  • 相关阅读:
    Win7下IE 8内存保护可能导致ActiveX无法安装的问题及其解决方法
    为Windows Server 2000开发和部署ASP.NET 3.5的应用程序
    MOSS 2010:如何为列表设计Infopath表单用于编辑和显示
    Windows Live is designed for you, but maybe not for your browser
    Meet the new WSS SharePoint Foundation 2010
    MOSS 2010: Visual Studio 2010开发体验(3)——调试代码
    MOSS 2010:Visual Studio 2010开发体验(10)——列表开发之内容类型
    MOSS 2010:谁动了我的“共享服务”
    MOSS 2010:通过SharePoint Designer定制列表项的条件格式
    如何访问嵌套母版页中的控件
  • 原文地址:https://www.cnblogs.com/HPAHPA/p/8337693.html
Copyright © 2020-2023  润新知