Win API 串口的Modbus 通讯 VS2005

最初以VB做串口与PLC通信的程序,发现有些问题,就改为C ,问题果然解决。下面的是主要实现代码,部分变量声明得自己在头文件中声明。

程序与施耐德PLC连接通信,运行良好。

以异步读写方式打开COM3

void CMscommDlg::OnBnClickedBitOpen()
{
    DWORD  dwError;
   hCom=CreateFile(_T("COM3"),GENERIC_READ |GENERIC_WRITE, 0, NULL,

   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
  if(hCom==(HANDLE)0XFFFFFFFF)
 {
   MessageBox("串口打开失败");
   return;
  }
  MScommOpen=true;

  DCB dcb;
  dcb.DCBlength=sizeof(dcb);
  GetCommState(hCom,&dcb);
  dcb.BaudRate = 19200; //波特率为9600
  dcb.ByteSize =8; //数据位数为8位
  dcb.Parity = NOPARITY; //偶校验
  dcb.StopBits = 2; //两个停止位
  dcb.fBinary = TRUE;
  dcb.fParity = TRUE; 

  if (!SetCommState(hCom,&dcb))
  {
   MessageBox(_T("串口设置出错!"));
  }
  SetupComm(hCom, 1024, 1024);
  PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT |PURGE_TXCLEAR |

                                   PURGE_RXCLEAR);

  COMMTIMEOUTS to;
  memset(&to, 0,sizeof(to));
  to.ReadIntervalTimeout = 10;
  SetCommTimeouts(hCom,&to);
  SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY);//设置串口监听事件
}

 

///创建读写线程///
void CMscommDlg::OnBnClickedBitRece()
{
 RECVPARAM *pRecvParam=newRECVPARAM; //创建结构体,以向线程函数传输多个参数
 pRecvParam->m_com=hCom;                                 //串口标识
 pRecvParam->hwnd=m_hWnd;                                //窗体句柄

);

//创建写数据线程

 hThread1=CreateThread(NULL,10000,FunPro1,(LPVOID)pRecvParam,0,NULL);

//创建读数据线程

 hThread2=CreateThread(NULL,10000,FunPro2,(LPVOID)pRecvParam,0,NULL);
 CloseHandle(hThread1);// 关闭线程句柄
 CloseHandle(hThread2);//关闭线程句柄
}

/线程1写数据

//线程交替实现向站1的0号寄存器写入值0和100,每写入完成,读取该数据

DWORD WINAPI FunPro1(LPVOID lpParameter)
{
 
   HANDLEhCom=((RECVPARAM*)lpParameter)->m_com;
   HWND  hwnd=((RECVPARAM*)lpParameter)->hwnd;
    HANDLEhMutex=((RECVPARAM*)lpParameter)->Mutex;

   bool Sign=true;
    intData=100;
  DWORD   CRC;

   unsigned charlpOutBuffer[8];

   while(1)
   {
      Sleep(100);
      lpOutBuffer[0]=1;   //站
      lpOutBuffer[2]=0;  //寄存器高地址
      lpOutBuffer[3]=0;  //寄存器底地址

      if(Sign)
     {
       lpOutBuffer[1]=3;  //读操作
       lpOutBuffer[4]=0;  //字节高位
       lpOutBuffer[5]=1;  //字节地位
        Sign=false;
    }
    else
    {
     if(Data==100)
        Data=0;
    else
       Data=100;
     lpOutBuffer[1]=6;    //写操作
     lpOutBuffer[4]=0;    //字节高位
     lpOutBuffer[5]=Data;  //字节地位
      Sign=true;
    }

   CRC=GetCheckCode(lpOutBuffer, 6); //校验
   lpOutBuffer[6]=(char)CRC;
   lpOutBuffer[7]=CRC>>8;

    DWORDdwNumberWrite;
    BOOL bWriteStat;
   OVERLAPPED  m_OverlappedWrite;
     memset(&m_OverlappedWrite, 0, sizeof( OVERLAPPED ));
      m_OverlappedWrite.hEvent= CreateEvent( NULL, TRUE, FALSE, NULL );
      bWriteStat = WriteFile(hCom, (LPSTR) lpOutBuffer, 8,&dwNumberWrite,

                                                         &m_OverlappedWrite );

      if( !bWriteStat && ( GetLastError()== ERROR_IO_PENDING ) )
           if( WaitForSingleObject(m_OverlappedWrite.hEvent, 1000 ) )
                   dwNumberWrite = 0;
           else
                   GetOverlappedResult( hCom,&m_OverlappedWrite, &dwNumberWrite,FALSE );
      if (dwNumberWrite == 0)
              AfxMessageBox("写操作失败");
    }
  return 0;
}

 

///线程2:监视串口

DWORD WINAPI FunPro2(LPVOID lpParameter)
{
   LPDWORD       lpEvtMask;
   LPOVERLAPPED  lpOverlapped;
    charSendBuf[1024];
    HANDLE hCom=((RECVPARAM*)lpParameter)->m_com;
    HWND  hwnd=((RECVPARAM*)lpParameter)->hwnd;
    HANDLEhMutex=((RECVPARAM*)lpParameter)->Mutex;

    while(1)

     { 
         OVERLAPPED m_osRead;
         DWORD dwMask,dwTrans,dwError=0,err;
         memset(&m_osRead,0,sizeof(OVERLAPPED));
         m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
         if(!WaitCommEvent(hCom,&dwMask,&m_osRead))   //判断异步操作是否完成
       {
             if(GetLastError()==ERROR_IO_PENDING)  //若异步操作正在进行,判断是否是读写事件
                 {
                  GetOverlappedResult(hCom,&m_osRead,&dwTrans,true); //等待事件发生
                    if(EV_RXCHAR==dwMask)                                                      //判读是否是读事件发生
                       ::PostMessage(hwnd,WM_READDATA,0,(LPARAM)data);//串口有数据,通知窗口
                    }
          }
   }
  return 0;
}

 

//窗口消息响应函数,读取串口数据///

LRESULT CMscommDlg::OnReadData(WPARAM wParam,LPARAMlParam)
{
    unsigned  char lpOutBuffer[1024];
     DWORD dwBytesRead=1024;
     COMSTAT ComStat;
     DWORD dwErrorFlags;
     OVERLAPPED m_osRead;
    int Data ;
     CString Temp;
     CString Str;

     memset(&m_osRead,0,sizeof(OVERLAPPED));
    m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); 
    ClearCommError(hCom,&dwErrorFlags,&ComStat);
     dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
     if(dwBytesRead)
     {  
        BOOL bReadStatus;
       bReadStatus=ReadFile(hCom,lpOutBuffer,dwBytesRead,&dwBytesRead,&m_osRead);
       if(!bReadStatus)
          if(GetLastError()==ERROR_IO_PENDING)
             WaitForSingleObject(m_osRead.hEvent,2000);
   }


   PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|

                                       PURGE_RXCLEAR); //清空缓冲区;
  if(dwBytesRead==lpOutBuffer[2]+5) 
   {
    Str="";
    for(int i=3;i<dwBytesRead-2;i+=2)
    {
      Data=256*lpOutBuffer[i]+lpOutBuffer[i+1];
   Temp.Format("%d",Data);
   Str+=Temp;
   Str+="  ";
    }
    GetDlgItemText(IDC_EDIT_RECE,Temp);
       Str+=_T("\r\n");
       Str+=Temp;
       SetDlgItemText(IDC_EDIT_RECE,Str);
   }
    return0;

}

//CRC校验//

WORD GetCheckCode(const unsigned char * pSendBuf, intnEnd)//获得校验码

{ 

 WORD wCrc = WORD(0xFFFF);
      for(int i=0; i<nEnd; i++)
      {
          wCrc ^= WORD(BYTE(pSendBuf[i]));
           for(int j=0; j<8; j++)
             {
               if(wCrc & 1)
                  {
                     wCrc >>= 1;
                     wCrc ^= 0xA001;
                    }

                 else
 

                   {
      

wCrc >>= 1;

                    }
               }
      }

      return wCrc;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值