32单片机+W5500实现FTP传输多个COMTRADE文件的详细设计。

本文详细介绍了GD32+W5500实现FTP传输多个COMTRADE文件的设计。基于TCP协议,FTP通信需两个socket,W5500做客户端与服务器通信,采用主动模式。阐述了单个文件交互流程,传输多文件采用循环上传,还提醒传输完成后用discon命令,最后附有相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GD32+W5500实现FTP传输多个COMTRADE文件的详细设计。

1、使用W5500实现FTP是基于TCP协议来实现的;
2、FTP通信时,需要两个socket,1个用于走控制数据,一个用于走数据;
3、FTP通信时,W5500做客户端,与FTP服务器通信,FTP服务器支持主动模式与被动模式,主动模式为W5500告诉FTP服务器ip地址和端口号,FTP服务器用新的socket做客户端连接W5500的服务器socket,目前采用主动模式;
4、单个文件交互流程:(红色为命令socket传输内容,绿色为数据socket传输内容)
W5500发起对服务器的连接
输入用户名、密码
使用PORT $ip $端口告诉FTP服务器ip地址和端口
通过STOR命令传输文件名
传输文件
使用QUIT命令退出传输
发送discon命令断开连接

5、传输多个文件时我采用的方法是循环上传单个文件,也就是
建立连接
登录
通知FTP服务器为主动模式
文件名
文件
退出
Discon

6、注意,传输完成QUIT后要给socket发discon命令,而不是close命令,这个地方一定注意。

附有新的comtrade故障录波文件产生时,即apiGetRelaymainTranFlag()不为0,数据开始传输的代码:

/*************************************************************************
* 
*   Copyright (C), 1999-2004, wisdom. Co., Ltd.
* 
*   文件名称: appEthernet.c
*   软件模块: <APP>
*   版 本 号: 1.0
*   生成日期: 2023-11-30
*   作    者: Ben
*   功    能: <以太网通信模块>
* 
*************************************************************************/

#include "apiInclude.h"
#include "appInclude.h"

/* FTP Responses */
#define R_150			150		/* File status ok; opening data conn */
#define R_200			200		/* 'Generic' command ok */
#define R_220			220		/* Service ready for new user. */
#define R_221 			221 	/* 服务正在关闭 */
#define R_225  			225 	/* 数据连接打开 */
#define R_226			226		/* Closing data connection.  File transfer/abort successful */
#define R_227			227		/* Entering passive mode (h1,h2,h3,h4,p1,p2) */
#define R_230			230		/* User logged in, proceed */
#define R_250 			250  	/* 请求文件操作已完成 */
#define R_257 			257 	/* 路径创建成功 */
#define R_331			331		/* User name okay, need password. */

/* 传输数据类型 */
#define TransferAscii		'A'
#define TransferBinary		'I'

/* FTP客户端状态定义 */
#define FTP_CLIENT_STATE_IDLE			0		/* 空闲 */
#define FTP_CLIENT_STATE_LOGIN			1		/* 登录 */
#define FTP_CLIENT_STATE_LINK			2		/* FTP服务器发起对W5500server连接 */
#define FTP_CLIENT_STATE_CFG_DATA		3		/* 传CFG数据内容 */
#define FTP_CLIENT_STATE_DATA_DATA		4		/* 传DAT数据内容 */
#define FTP_CLIENT_STATE_TRAN_OK		5		/* 传输完成 */
#define FTP_CLIENT_STATE_TRAN_DONE		6		/* 传输流程结束 */

static CHAR rxbuff[2048];		/* 数据接收区 */
static CHAR szText[200];		/* 字符串缓冲区 */

/* FTP传输控制结构 */
typedef struct TFTPTranCtrl
{	
	BYTE byCFGOffset;
	BYTE byCtrlSockState;
	WORD wDATOffset;
}TFTPTranCtrl;

static TFTPTranCtrl s_FTPTranCtrl;	/* FTP传输控制 */

/* 文件名,cfg,data数据结构 */
static TCOMTRADE* s_FTPCOMTRADENameFile;
static TCOMTRADECFG* s_FTPCOMTRADEFILECFGbuf;
static TCOMTRADEDAT* s_FTPCOMTRADEDAFILETRead;		/* DAT文件数据结构 */	

/* 
[DISTURB_NUMBER_CYCLE * (DISTURB_PRE_NUMBER + DISTURB_AFTER_NUMBER)]

*/
/* FTP服务器回复报文处理 */
static void _FTPServerResponse(CHAR * buf);

/* 传输cfg文件 */
static void _FTPTranCFGFile(void);

/* 传输dat文件 */
static void _FTPTranDATFile(void);

extern BYTE byServerType;

/* FTP服务器回复报文处理 */
static void _FTPServerResponse(CHAR * buf)
{
	WORD Responses;
	BYTE dat[30] = {0,};
 	memset(dat, 0, 30);
	Responses = (buf[0] - '0') * 100 + (buf[1] - '0' ) * 10 + (buf[2] - '0');

	switch(Responses)
	{
		/* Service ready for new user. */
		case R_220:
			
			if (byServerType == 0)
			{
				sprintf(szText, "USER %s\r\n", "W5500");
			}

			else 
			{
				sprintf(szText, "USER %s\r\n", "ubuntu");
			}
			
			Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
			break;

		/* User name okay, need password. */
		case R_331:
			
			if (byServerType == 0)
			{
				sprintf(szText, "PASS %s\r\n", "123456");
			}

			else 
			{
				sprintf(szText, "PASS %s\r\n", "ubuntu");
			}

			Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_LOGIN;
			break;

		/* User logged in, proceed */
		case R_230:	
//@			sprintf(szText, "TYPE %c\r\n", "TransferAscii");
//@			Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
			
			break;
			
		case R_200:

			break;
			
		case R_150:

			break;

		case R_226:
			break;

		case R_227:

			break;

		default:
//			Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE);	/* 关闭socket */
//			Write_W5500_SOCK_1Byte(0, Sn_IR, 0xFF);
//			TW55001State.time = hwGetSystemCount();
			break;
	}
}

/* FTP传输任务初始化 */
BOOL appFTPInit(void)
{	
	DWORD dwSize;

	/* 申请缓冲区 */
 	dwSize = sizeof(TCOMTRADE);
	s_FTPCOMTRADENameFile = (TCOMTRADE*)hwMalloc(dwSize, HW_MEM_MALLOC_NORMAL);

	dwSize = sizeof(TCOMTRADECFG);
	s_FTPCOMTRADEFILECFGbuf = (TCOMTRADECFG*)hwMalloc(dwSize, HW_MEM_MALLOC_NORMAL);
	
	dwSize = (sizeof(TCOMTRADEDAT) * (DISTURB_NUMBER_CYCLE * (DISTURB_PRE_NUMBER + DISTURB_AFTER_NUMBER)));
	s_FTPCOMTRADEDAFILETRead = (TCOMTRADEDAT*)hwMalloc(dwSize, HW_MEM_MALLOC_NORMAL);

	/* 控制结构初始化 */
	s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_IDLE;
	s_FTPTranCtrl.byCFGOffset = 0;
	s_FTPTranCtrl.wDATOffset = 0;
    
    return TRUE;
}

/* 传输cfg文件 */
static void _FTPTranCFGFile(void)
{
	switch (s_FTPTranCtrl.byCFGOffset)
	{
		case 0:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pFirstLine);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 1;
			break;
	
		case 1:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pSecondLine);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 2;
			break;
	
		case 2:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pUA);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 3;
			break;
	
		case 3:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pUB);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 4;
			break;
	
		case 4:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pUC);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 5;
			break;
	
		case 5:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pIA);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 6;
			break;
	
		case 6:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pIB);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 7;
			break;
	
		case 7:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pIC);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 8;
			break;
	
		case 8:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pFrequency);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 9;
			break;
	
		case 9:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pnrates);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 10;
			break;
	
		case 10:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pSampleRate);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 11;
			break;
	
		case 11:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pSampleTime);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 12;
			break;
	
		case 12:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pTriggerTime);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 13;
			break;
	
		case 13:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->pft);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));
			s_FTPTranCtrl.byCFGOffset = 14;
			break;
	
		case 14:
			strcpy(szText, s_FTPCOMTRADEFILECFGbuf->ptimemult);
			strcat(szText, "\r\n");
			Write_SOCK_Data_Buffer(1, (BYTE*)szText, strlen(szText));

			break;
	
		default:
			s_FTPTranCtrl.byCFGOffset = 0;
			break;
	}
}

/* 传输dat文件 */
static void _FTPTranDATFile(void)
{
	BYTE byDatFile[20];
	DWORD i;

	memset(byDatFile, 0, sizeof(byDatFile));
	
	if (s_FTPTranCtrl.wDATOffset >= (DISTURB_NUMBER_CYCLE * (DISTURB_PRE_NUMBER + DISTURB_AFTER_NUMBER)))
		return;
	
	byDatFile[0] =  (LLBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].n));
	byDatFile[1] =  (LHBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].n));
	byDatFile[2] =  (HLBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].n));
	byDatFile[3] =  (HHBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].n));
	byDatFile[4] =  (LLBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].timetamp));
	byDatFile[5] =  (LHBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].timetamp));
	byDatFile[6] =  (HLBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].timetamp));
	byDatFile[7] =  (HHBYTE(s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].timetamp));

	for (i = 0; i < 12; i++)
		byDatFile[8 + i] =  s_FTPCOMTRADEDAFILETRead[s_FTPTranCtrl.wDATOffset].DAT[i];

	s_FTPTranCtrl.wDATOffset++;
	Write_SOCK_Data_Buffer(1, byDatFile, 20);

}


/* TCP/IP任务 FTP任务 
 * 本机ip地址:192.168.1.199  
 * socket0做客户端,端口号5000,远端ip:192.168.1.60,端口号6000
 * socket1做服务器,端口号8888
 */
BOOL appFTPTask(void* pData)
{
	WORD size;

	/* 1路以太网处理 */
	/* 若出现断线事件,快速相应 */
	if ((Read_W5500_1Byte(PHYCFGR) & LINK) == 0)
	{
		Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE);	/* 关闭socket */
		Write_W5500_SOCK_1Byte(0, Sn_IR, 0xFF);
		TW55001State.time = hwGetSystemCount();

		Write_W5500_SOCK_1Byte(1, Sn_CR, CLOSE);	/* 关闭socket */
		Write_W5500_SOCK_1Byte(1, Sn_IR, 0xFF);
		TW55002State.time = hwGetSystemCount();

		W5500_Initialization(); 
	}

	/* 网线连接状态 */
	else
	{	
		/* ctrl socket 做客户端 */
		switch (Read_W5500_SOCK_1Byte(0, Sn_SR))
		{	
			case SOCK_ESTABLISHED:

				/* 设置服务器为主动模式 */
				if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_LOGIN)
				{
					sprintf(szText, "PORT %d,%d,%d,%d,%d,%d\r\n", 192,168,1,199, S1_Port[0], S1_Port[1]);
					Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
					s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_LINK;
				}

				/* 文件名 */
				else if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_LINK)
				{	
					if (apiGetRelaymainTranFlag() & (0x01 << CFG_FILE))
					{	
						apiGetCOMTRADENameFile(0, s_FTPCOMTRADENameFile);
						sprintf(szText, "STOR ./%s.cfg\r\n", s_FTPCOMTRADENameFile->chName);
						Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
						apiGetCOMTRADECFGFile(0, s_FTPCOMTRADEFILECFGbuf);
						s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_CFG_DATA;
					}

					else if (apiGetRelaymainTranFlag() & (0x01 << DAT_FILE))
					{
						sprintf(szText, "STOR ./%s.dat\r\n", s_FTPCOMTRADENameFile->chName);
						Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
						apiGetCOMTRADEDATFile(0, s_FTPCOMTRADEDAFILETRead);
						s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_DATA_DATA;
					}
				}

				/* 传输完成 */
				else if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_TRAN_OK)
				{
                    sprintf(szText, "QUIT\r\n");
					Write_SOCK_Data_Buffer(0, (BYTE*)szText, strlen(szText));
					s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_TRAN_DONE;
				}

				/* 传输流程结束 */
				else if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_TRAN_DONE)
				{
					Write_W5500_SOCK_1Byte(0, Sn_CR, DISCON);
					Write_W5500_SOCK_1Byte(1, Sn_CR, DISCON);	
				}
				
				/* 接收数据查询 */
				W5500_Interrupt_Process();	
				
				/* FTP服务器返回命令数据解析 */
				if((S0_Data & S_RECEIVE) == S_RECEIVE)
				{
					S0_Data &= ~S_RECEIVE;
					size = Read_SOCK_Data_Buffer(0, (BYTE*)rxbuff);
					_FTPServerResponse(rxbuff);
				
					TW55001State.time = hwGetSystemCount();
				}
				
				/* 超过OVERTIME未传输完毕或无响应 */
				if (hwGetSystemCount() - TW55001State.time >= W5500_OVERTIME_TRAN)
				{
					Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE);
					TW55001State.time = hwGetSystemCount();
				}

				break;

			case SOCK_CLOSE_WAIT:
				Write_W5500_SOCK_1Byte(0, Sn_CR, DISCON);
				break;

			case SOCK_CLOSED:
				if (apiGetRelaymainTranFlag())
				{	
					Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE);	/* 关闭socket */
					Write_W5500_SOCK_1Byte(0, Sn_IR, 0xFF);
					Write_W5500_SOCK_1Byte(0, Sn_MR, MR_TCP);	/* 设置socket为TCP模式 */
					Write_W5500_SOCK_1Byte(0, Sn_KPALVTR, 2);	/* 设置keepalive为2*5=10秒 */
					Socket_Init(0); 							/* 配置端口号 */
					Write_W5500_SOCK_1Byte(0, Sn_CR, OPEN); 	/* 打开Socket */
					hwDelayTime(1000);
					hwDelayTime(1000);
					Write_W5500_SOCK_1Byte(0, Sn_CR, CONNECT);	/* 做客户端发起连接 */
					TW55001State.time = hwGetSystemCount();   
					s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_IDLE;
				}

				break;
				
			default:
				if (hwGetSystemCount() - TW55001State.time >= W5500_OVERTIME)
					Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE);
				
				break;
		}

		/* data socket 做服务器 */
		switch (Read_W5500_SOCK_1Byte(1, Sn_SR))
		{
			case SOCK_INIT:
				Write_W5500_SOCK_1Byte(1, Sn_CR, LISTEN);
				TW55002State.time = hwGetSystemCount();
				break;

			case SOCK_LISTEN:
				/* 超过OVERTIME无连接 */
				if (hwGetSystemCount() - TW55002State.time >= W5500_OVERTIME)
				{
					TW55002State.time = hwGetSystemCount();
					Write_W5500_SOCK_1Byte(1, Sn_CR, CLOSE);
				}
				break;

			case SOCK_ESTABLISHED:

				/* 数据接收查询 */
				W5500_Interrupt_Process_Socket1();	

				/* 数据接收处理 */
				if ((S1_Data & S_RECEIVE) == S_RECEIVE)
				{
					S1_Data &= ~S_RECEIVE;
					size = Read_SOCK_Data_Buffer(1, (BYTE*)rxbuff);

					TW55002State.time = hwGetSystemCount();
				}

				/* 传CFG文件 */
				if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_CFG_DATA)
				{
					_FTPTranCFGFile();
					TW55002State.time = hwGetSystemCount();

					/* CFG文件传输完成 */
					if (s_FTPTranCtrl.byCFGOffset == 14)
					{
						s_FTPTranCtrl.byCFGOffset = 0;
						s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_TRAN_OK;						
						apiSetRealymainTranFlag(CFG_FILE, FALSE);
					}
					
				}

				/* 传DATA文件 */
				else if (s_FTPTranCtrl.byCtrlSockState == FTP_CLIENT_STATE_DATA_DATA)
				{
					_FTPTranDATFile();
					TW55002State.time = hwGetSystemCount();

					if (s_FTPTranCtrl.wDATOffset == (DISTURB_NUMBER_CYCLE * (DISTURB_PRE_NUMBER + DISTURB_AFTER_NUMBER)))
					{
						s_FTPTranCtrl.wDATOffset = 0;
						apiSetRealymainTranFlag(DAT_FILE, FALSE);
					    s_FTPTranCtrl.byCtrlSockState = FTP_CLIENT_STATE_TRAN_OK;						
					}
				}
			
				/* 超过OVERTIME没传完 */
				if (hwGetSystemCount() - TW55002State.time >= W5500_OVERTIME_TRAN)
				{
					Write_W5500_SOCK_1Byte(1, Sn_CR, CLOSE);
					TW55002State.time = hwGetSystemCount();
				}
			break;

			case SOCK_CLOSE_WAIT:
				Write_W5500_SOCK_1Byte(1, Sn_CR, DISCON);
				break;

			case SOCK_CLOSED:
				if (apiGetRelaymainTranFlag())
				{
					Write_W5500_SOCK_1Byte(1, Sn_CR, CLOSE);	/* 关闭socket */
					Write_W5500_SOCK_1Byte(1, Sn_IR, 0xFF);
					Write_W5500_SOCK_1Byte(1, Sn_MR, MR_TCP);	/* 设置socket为TCP模式 */
					Write_W5500_SOCK_1Byte(1, Sn_KPALVTR, 2);	/* 设置keepalive为2*5=10秒 */
					Socket_Init(1); 							/* 配置端口号 */
					Write_W5500_SOCK_1Byte(1, Sn_CR, OPEN); 	/* 打开Socket */
					hwDelayTime(1000);
					hwDelayTime(1000);	 
					TW55002State.time = hwGetSystemCount();
				}
				
				break;
			
			default:
				if (hwGetSystemCount() - TW55002State.time >= W5500_OVERTIME)
					Write_W5500_SOCK_1Byte(1, Sn_CR, CLOSE);
				break;
		}
	}
	
	return TRUE;
}


/*************************************************************************
* 改动历史纪录:
Revision 1.0, 2023-11-30, Ben
describe: 初始创建.
*************************************************************************/


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值