首页 安川运动控制 正文

回复

上位机(工控机)与MP2300S的通讯

安川运动控制 浏览:2508 回复:4 收藏

橙汁咖啡  2016-09-21 14:05

做的一个产品是随动控制的,要求MP控制4个轴,总线控制,需要4个电机每时每刻根据上位机发送来的数据转动到相应的位置,现在就是想搞明白上位机与MP的通讯软件,也就是编程的问题,安川给的例子看不懂啊

#include<stdio.h>

#include<winsock.h>

#include<winioctl.h>


int sd; /*Socket Discripter*/

struct sockaddr_in my;

struct sockaddr_in dst;


#define MY_IP 0xC0A80102

#define MY_PORT 10000


#define DST_IP 0xCA80101

#define DST_PORT 10001


char sbuf[2048];

char rbuf[2048];


void main_tcp(void);

void mk_cmd_data(void);

int chk_rsp_data(int);


void main_tcp(void)

{

WSADATA wsadata;

int rc, slen, rlen;


//声明使用Winsock.dll(始终需要首先执行该声明。)

rc = WSAStartup(0x0101, &wsadata);

if (rc != 0)

{

exit(0);

}


//将sockaddr 结构(IP地址、端口号等)清零。

memset((char *)&my, 0, sizeof(struct sockaddr));

memset((char *)&dst, 0, sizeof(struct sockaddr));


//声明本地IP地址和端口号

my.sin_family = AF_INET;

my.sin_addr.s_addr = htonl(MY_IP);

my.sin_port = htons(MY_PORT);


//声明远程IP地址和端口号

dst.sin_family = AF_INET;

dst.sin_addr.s_addr = htonl(MY_IP);

dst.sin_port = htons(MY_PORT);


//生成TCP套接字。

sd = socket(AF_INET, SOCK_STREAM, 0);

if (sd <= 0)

{

printf("Error:Socket !!\n");

exit(0);

}


//执行绑定来分配本地端口编号。

rc = bind(sd, (struct sockaddr *)&my, sizeof(struct sockaddr_in));

if (rc == -1)

{

closesocket(sd);

printf("Error:bind!!\n");

exit(0);

}


//建立连接。

rc = connect(sd, (struct sockaddr *)&dst, sizeof(struct sockaddr_in));

if (rc == -1)

{

closesocket(sd);

printf("Error: Connect !!\n");

exit(0);

}


//在建立连接后准备命令数据。

mk_cmd_data();


//重复发送命令和接收响应。

while (1)

{

//发送命令数据。

//如果主控制器无法发送数据,此处理将不会结束。

slen = send(sd, &sbuf[0], 22, 0);//发送命令(22个字节)。

if (slen != 22)//如果发送处理完成,则会返回发送的字节数(22)。

{

closesocket(sd);

printf("Error:send !! -> %d\n", slen);

exit(0);

}

//接收响应数据。

//如果子控制器没有发送响应数据,此处理不会结束。

rlen = recv(sd, &rbuf[0], sizeof(rbuf), 0);//从远程站接收响应数据。

if (rlen <= 0)//如果接收数据期间出现错误,则将返回0或更小的数值。

{

closesocket(sd);

printf("Error : Recv !! -> %d\n", rlen);

exit(0);

}


//检查响应数据。

rc = chk_rsp_data(rlen);

if (rc != 0)//接收数据中存在错误

{

closesocket(sd);

exit(0);

}

sbuf[1] ++;//218标题的序号递增。

printf("Hit Any Key !!\n");

}

}


//准备扩展MEMOBUS协议命令,读出保持寄存器内容(SFC = 09)。


void mk_cmd_data(void)

{

//准备218标题。

//设定数据类型。

sbuf[0] = 0x11;//扩展MEMOBUS(参考命令)


//设定序号(每次发送数据时序号都会递增)

sbuf[1] = 0x00;


//设定目标通道编号。

sbuf[2] = 0x00;//由于未指定PLC的通道,因此通道编号可以固定为0。


//设定目标通道编号。

sbuf[3] = 0x00;//由于个人计算机无通道编号,请务必将其设为0。


sbuf[4] = 0x00;//保留。

sbuf[5] = 0x00;//保留。


//设定所有的数据项目数(从218标题至MEMOBUS数据结尾)。

sbuf[6] = 0x16;//L(22个字节 = 218标题(12个字节)+MEMBOUS数据(10个字节)

sbuf[7] = 0x00;// H


sbuf[8] = 0x00;//保留

sbuf[9] = 0x00;//保留

sbuf[10] = 0x00;//保留

sbuf[11] = 0x00;//保留


//准备MEMBOUS数据。

//长度:从MFC追数据结尾

sbuf[12] = 0x08; //MEMBOUS数据长度(L)

sbuf[13] = 0x00; //MEMBOUS数据长度(H)


//MFC固定为0x20

sbuf[14] = 0x20;


//SFC为0x09(读出保持寄存器内容(扩展))

sbuf[15] = 0x09;


//设定CPU编号。

sbuf[16] = 0x10; //远程CPU编号:CPU1.多个CPU:1—4本地CPU编号:始终为0.


sbuf[17] = 0x00; //备用,始终为0


//设定参考编号。

sbuf[18] = 0x00; //Adr(L)首位地址:MW0

sbuf[19] = 0x00; //Adr(H)


//设定寄存器数

sbuf[20] = 0x0A; //从DataNum(L)首位地址开始读取10个字。

sbuf[21] = 0x00; //DataNum(H)

}


//检查响应数据。

int chk_rsp_data(int rlen)

{

int rc;

rc = 0;

//检查数据总长度。

if (rlen != 40)//10字节读出时为40个字节响应

//((218标题(12字节)+MEMBOUS数据(28个字节))

{

rc = -1;

return(rc);

}

//检查数据包类型。

if (sbuf[1] != 0x19)//非MEMBOUS响应

{

rc = -2;

return (rc);

}


//检查序号。

if (sbuf[1] != rbuf[1])//与命令序号不一致。

{

rc = -3;

return(rc);

}


//检查信息中的总数据长度。

if ((sbuf[6] != 0x28) && (rbuf[7] != 0x00))//40个字节 = 218标题(12个字节) +MEMBOUS数据(28个字节)

{

rc = -4;

return(rc);

}


//检查MEMBOUS数据长度。

if ((rbuf[12] != 0x1A) || (rbuf[13] != 0x00))//26个字节

{

rc = -5;

return(rc);

}


//检查MFC。

if (rbuf[14] != 0x20)//MFC固定为0x20。

{

rc = -6;

return(rc);

}


//检查SFC

if (rbuf[14] != 0x20)//SFC为0x09(读出保持寄存器内容)。

{

rc = -7;

return(rc);

}


//检查寄存器数。

if ((rbuf[18] != 0x0A) || (rbuf[19] != 0x00))//不是10字。

{

rc = -8;

return(rc);

}


//读出寄存器数据rbuf[20]以及之后的数据。

return(rc);

}


我知道了