最初以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;
- }