⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 工业控制--串口通讯方法.txt

📁 RS-232-C端口实时监控软件的设计实现 多线程技术在VC++串口通信程序中的应用研究 用VC6实现串行通信的三种方法 在基于单文档程序中应用MSCOMM串口通讯控件
💻 TXT
字号:
工业控制--串口通讯方法(WINAPI实现)

介绍 
介绍工业控制领域利用串口和外围设备进行通讯。 

正文 
前言: 
  总所周之,利用串口进行数据通讯在在通讯通讯领域重占有着重要的地位。利用RS232-RS485进行数据信号的采集和传递是VC编程的又一大热点。串口通讯在通讯软件重有着十分广泛的应用。如电话、传真、视频和各种控制等。在各种开发工具中间,VC由于功能强大和灵活,同时也得到了Microsoft的最大支持,所以在一般进行涉及硬件操作的通讯编程重,大都推荐使用VC作为开发工具。然而工业控制串口通讯这个又不同于一般的串口通讯程序,因为控制外围设备传送的大都是十六进制数据(BYTE类型),所以,为了提高程序的运行稳定性,我们在编写程序进行通讯时可以不考虑传送BYTE类型数据的工作。 
  串口通讯目前流行的方法大概有两种:一是利用Microsoft提供的CMSCOMM控件进行通讯,不过现在很多程序员都觉应该放弃这种方式。二是利用WINAPI函数进行编程,这种编程的难度最高,要求你要掌握很多的API函数。三是利用现在网络上面提供的一些串口通讯控件进行编写,比如CSerial类等。 

程序实现: 
  我在经过许多的项目的开发和实践中发现,采用WIN API函数进行串口的开发能够给程序员很大的控件,并且程序运也很稳定。所以我将与串口接触的函数进行封装,然后在各个工程中进行调用,效果还是比较好的,现将各个函数和调用方法列举出来,希望对各位有所帮助。 
  一、设置串口相关工作 

#define    MAXBLOCK 2048 
#define    XON 0x11 
#define    XOFF 0x13 
BOOL SetCom(HANDLE &m_hCom, const char *m_sPort, int BaudRate, int Databit, CString parity, CString stopbit) 
{ 
  COMMTIMEOUTS TimeOuts;                ///串口输出时间 超时设置 
  DCB dcb;                       ///与端口匹配的设备   
  m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, 
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
    NULL); // 以重叠方式打开串口 
  if(m_hCom==INVALID_HANDLE_VALUE) 
  {  
    AfxMessageBox("设置串口部分,串口打开失败");  /////重叠方式 异步通信(INVALID_HANDLE_VALUE)函数失败。 
    return FALSE; 
  }   
  SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);       //设置缓冲区 
  memset(&TimeOuts,0,sizeof(TimeOuts));   
  TimeOuts.ReadIntervalTimeout=MAXDWORD;      // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作 
  TimeOuts.ReadTotalTimeoutMultiplier=0;      //读时间系数 
  TimeOuts.ReadTotalTimeoutConstant=0;      //读时间常量  
  TimeOuts.WriteTotalTimeoutMultiplier=50;    //总超时=时间系数*要求读/写的字符数+时间常量 
  TimeOuts.WriteTotalTimeoutConstant=2000;    //设置写超时以指定WriteComm成员函数中的                        
  SetCommTimeouts(m_hCom, &TimeOuts);      //GetOverlappedResult函数的等待时间*/ 
  if(!GetCommState(m_hCom, &dcb))        ////串口打开方式、端口、波特率 与端口匹配的设备 
  { 
    AfxMessageBox("GetCommState Failed"); 
    return FALSE; 
  } 
   
  dcb.fParity=TRUE;             //允许奇偶校验     
  dcb.fBinary=TRUE; 
  if(parity=="NONE") 
    dcb.Parity=NOPARITY; 
  if(parity=="ODD") 
    dcb.Parity=ODDPARITY; 
  if(parity=="EVEN") 
    dcb.Parity=EVENPARITY; 
  if(stopbit=="1")//设置波特率 
    dcb.StopBits=ONESTOPBIT; 
  //if(stopbit=="0")//设置波特率 
  //  dcb.StopBits=NONESTOPBIT; 
  if(stopbit=="2")//设置波特率 
    dcb.StopBits=TWOSTOPBITS;               
  BOOL m_bEcho=FALSE;            /// 
  int m_nFlowCtrl=0; 
  BOOL m_bNewLine=FALSE;           /// 
  dcb.BaudRate=BaudRate;           // 波特率 
  dcb.ByteSize=Databit;           // 每字节位数   
  // 硬件流控制设置 
  dcb.fOutxCtsFlow=m_nFlowCtrl==1; 
  dcb.fRtsControl=m_nFlowCtrl==1  ?RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;   
  // XON/XOFF流控制设置(软件流控制!) 
  dcb.fInX=dcb.fOutX=m_nFlowCtrl==2; 
  dcb.XonChar=XON; 
  dcb.XoffChar=XOFF; 
  dcb.XonLim=50; 
  dcb.XoffLim=50;   
  if(SetCommState(m_hCom, &dcb))   
    return TRUE;     ////com的通讯口设置   
  else 
  { 
    AfxMessageBox("串口已打开,设置失败"); 
    return FALSE; 
  } 
} 

二、读串口操作: 
int ReadCom(HANDLE hComm, BYTE inbuff[], DWORD &nBytesRead, int ReadTime) 
{ 
  DWORD lrc;                 ///纵向冗余校验 
  DWORD endtime;              /////////jiesuo 
  static OVERLAPPED ol; 
  int ReadNumber=0;   
  int numCount=0 ;               //控制读取的数目 
  DWORD dwErrorMask,nToRead;  
  COMSTAT comstat;   
  ol.Offset=0;              ///相对文件开始的字节偏移量 
  ol.OffsetHigh=0;            ///开始传送数据的字节偏移量的高位字,管道和通信时调用进程可忽略。 
  ol.hEvent=NULL;             ///标识事件,数据传送完成时设为信号状态 
  ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);   
  endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒) 
  for(int i=0;i<2000;i++) 
    inbuff[i]=0;   
  Sleep(ReadTime); 
  ClearCommError(hComm,&dwErrorMask,&comstat); 
  nToRead=min(2000,comstat.cbInQue);  
  if(int(nToRead)<2) 
    goto Loop; 
  if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,&ol)) 
  {   
    if((lrc=GetLastError())==ERROR_IO_PENDING) 
    { 
      /////////////////// 
      endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒) 
      while(!GetOverlappedResult(hComm,&ol,&nBytesRead,FALSE))//该函数取回重叠操作的结果 
      { 
        if(GetTickCount()>endtime) 
          break; 
      }   
    }     
  } 
  return 1;   
Loop: return 0; 
} 

三、写串口命令 
int WriteCom(HANDLE hComm, BYTE Outbuff[], int size, int bWrite[]) 
{ 
  DWORD nBytesWrite,endtime,lrc; 
  static OVERLAPPED ol; 
  DWORD dwErrorMask,dwError; 
  COMSTAT comstat; 
  ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); 
  ol.Offset=0;        
  ol.OffsetHigh=0; 
  ol.hEvent=NULL;        ///标识事件,数据传送完成时,将它设为信号状态 
  ClearCommError(hComm,&dwErrorMask,&comstat); 
  if(!WriteFile(hComm,Outbuff,size,&nBytesWrite,&ol)) 
  { 
    if((lrc=GetLastError())==ERROR_IO_PENDING) 
    { 
      endtime=GetTickCount()+1000; 
      while(!GetOverlappedResult(hComm,&ol,&nBytesWrite,FALSE)) 
      {  
        dwError=GetLastError(); 
        if(GetTickCount()>endtime) 
        {   
          AfxMessageBox("写串口时间过长,目前串口发送缓冲区中的数据数目为空"); 
          break; 
        } 
        if(dwError=ERROR_IO_INCOMPLETE) 
          continue;     //未完全读完时的正常返回结果 
        else 
        { 
          //  发生错误,尝试恢复! 
          ClearCommError(hComm,&dwError,&comstat); 
          break; 
        } 
      } 
    }    
  }   
  FlushFileBuffers(hComm); 
  PurgeComm(hComm,PURGE_TXCLEAR);         
  bWrite=0; 
  return 1; 
} 

四、调用方法很简单,只需要将你的串口参数进行简单的设置就可以了。比如: 
BOOL Main_OpenCom()//设置COM 
{ 
  int Boundrate=9600;//波特率 
  CString StopBits="1";//停止位 
  int DataBits=8;//数据位 
  CString Parity="ODD";//奇偶校验 
  CString m_Port="COM1"; 
  return SetCom(m_hCom1,m_Port,Boundrate,DataBits,Parity,StopBits); 
} 

void Main() 
{ 
int SIZE; 
  DWORD BytestoRead=52*Count+6;//要11个字节 
  int BWRITE[2];   
  int ReadTime=2000; 
  BYTE Outbuff[12]={0xff,0x00,0xea,0xff,0xea,0xff,0,0,0,0,0,0}; 
  SIZE=sizeof(Outbuff); 
  WriteCom(m_hCom,Outbuff,SIZE,BWRITE); 
  ReadCom(m_hCom,m_Inbuff,BytestoRead,ReadTime); 
     //进行湘阴的解包处理 
} 

有了上面的函数的封装,相信大家编程应该能够方便快捷一些吧。 
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -