上位机数据通讯

来源:互联网 发布:淘宝汽车贴膜 编辑:程序博客网 时间:2024/06/09 19:11


1、应用背景

上位机处理过后的数据结果,经常需要传给下位机,交由执行部件处理。上下位机根据通讯方式种类比较多,

经常用到的是串口通讯和网口通讯。传输方式可以根据实际情况,任意选取,这就需要上位机兼容这些通讯

方式。再则,就是需要提供数据任意加载的功能,用户根据需要可以通过设置选择自己所需要的某部分数据

或者是完整的数据来发送。


2、数据加载

图像处理由独立线程单独完成,以免造成主线程卡顿。处理结果通过自定义消息,发送给相应的响应执行函数。

1)自定义消息

#ifndef WM_DATA_SEND 

#define WM_DATA_SEND WM_USER+1

#endif

2)消息发送

GetDlgRun()->SendMessage(WM_DATA_SEND,

WPARAM(CDlgToolParamMatchGeoMatch*)(it->second.m_pDlgToolParam))->GetShapeModelResult()),

(LPARAM)&(it->second.enToolType));

3)消息响应和消息响应函数

BEGIN_MESSAGE_MAP(CDlgRun, CDialogEx)

ON_MESSAGE(WM_DATA_SEND,&CDlgRun::OnDataSend)

END_MESSAGE_MAP()

afx_msg LRESULT CDlgRun::OnDataSend(WPARAM wParam, LPARAM lParam)

4)数据选择加载

数据处理结果由参数wParam和lParam传递过来,再根据选择记录,有选择的加载到

传输缓冲m_DataSendBuf中。


3、通讯方式选择

1)方式选择

提供用户多种通讯选择方式,比如常用的串口、网络、外部端子和PLC链接等。

2)串口设置

提供波特率选择设定,停止位的选择设定等。

3)网络设置

提供IP地址设定,端口号设定等。


4、串口驱动

MFC串口通讯的两种方法:

1)基于Active控件的方式(MSComm)

插入控件到对话框中,并为拖入对话框的MSComm添加变量m_mscomm,

添加消息响应函数OnComm( ),用做数据接收。

//串口参数设置

if(m_mscomm.get_PortOpen()) //如果串口是打开的,则关闭串口

{

m_mscomm.put_PortOpen(FALSE);

}

m_mscomm.put_CommPort(1); //选择COM1

//选择波特率

DWORD baudrate;

switch(m_CombolBaudrate.GetCurSel())

{

case 0:

baudrate = 115200;

break;

case 1:

baudrate = 9600;

break;

}

CString setting;

setting.Format(_T("%d,n,8,1"),baudrate );

m_mscomm.put_Setting(setting);

//数据发送

CString m_send = _T("你想要发送的数据");  

m_ctrlComm.SetOutput(COleVariant(m_send )); 

2)基于win32 API的串口读写

采用win32的api函数,显得更加通用。

//串口设置

HANDLE hCom;

hCom =  CreateFile(comName,//COM口

 GENERIC_READ|GENERIC_WRITE, //允许读和写

0, //独占方式

NULL,

OPEN_EXISTING,

0,

NULL);

if(hCom == (HANDLE )-1)

{

return NULL;

}


5、网口驱动

1)网络参数设置

//获取IP地址

CString CStrAddr;

BYTE f0,f1,f2,f3;

UpdateDate(TRUE);

m_CIPAddressCtrlIP.GetAddress(f0,f1,f2,f3);

CStrAddr.Format(_T("%d%s%d%s%d%s%d"),f0,".",f1,".",f2,".",f3);

//CString 转成char *

int len =  CStrAddr.GetLength();

char *ip = new char[len+1];

memset(ip,0,len+1);

WideCharToMultiByte(CP_OEMCP,NULL,(LPCWSTR)CSTRAddr,-1,NULL,0,NULL,FALSE);

WideCharToMultiByte(CP_OEMCP,NULL,(LPCWSTR)CSTRAddr,-1,(LPSTR)ip,len,NULL,FALSE);

ip[len]='\0';

//CString 转成 int

CString  cs;

m_CEditPort.GetWindowTest(cs);

m_iPort  = atoi((_bstr_t)cs);

m_IPAddress.sin_family = AF_INET;

m_IPAddress.sin_port = htons(m_iPort);

m_IPAddress.sin_addr.S_un.S_addr= inet_addr(ip);

delete[] ip;


2)网络连接

WORD wVersionRequested;

WSADATA wsaData;

if(WSAStartup(wVersionRequested, &wsaData )!=0){return 0;}

addrSrv.sin_family=AF_INET;

addrSrv.sin_port=htons(Port);

addrSrv.sin_addr.S_u.S_addr=htonl(INADDR_ANY);

if(*Socket)

{

closesocket(*Socket);

*Socket=NULL;

}

*Socket = socket(AF_INET,SOCK_DGRAM,0);

error = bind(*Socket, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

if(SOCKET_ERROR == error)return 0;

else

{

setsockopt(*Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRevBuf);

if(ioctlsocket(*Socket,FIONBIO,&flag)!=0)

{

closesocket(*Socket);

return 0;

}

}


3)数据发送

先将CString DataSendBuf转成char *类型,再调用发送函数

sendto(m_Socket,pDataSendBuf,len,0,(SOCKADDR*)&(m_IPAddress),sizeof(SOCKADDR));


6、结束

以上只实现了两种常用的通讯方式,其他通讯方式可以根据实际需求做相应添加,提高软件兼容性。

0 0