做的一个产品是随动控制的,要求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);
}