基于STM32CUBE的LWIP+FREERTOS+Socket构成的TCP服务器

本实验基于STM32F767制作

一、实验目的

本实验主要目的是通过Socket网络编程方法完成通过以太网控制两个LED的亮灭的,同理可用到继电器上控制其它高电压设备。

二、实验步骤

1.首先先生成一个带有LWIP和FreeRTOS的项目,并将网络ping通,如果不会的参照我第一篇文章STM32cubeMX将STM32F767+LAN8720+LwIP+FreeRTOS的以太网实现

2.先对项目进行编译,确认项目无误后新建一个名叫socketserver.c的文件,将以下代码附到文件中,代码内容讲解我已附在代码后

#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/sys.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>								//包含需要的所有头文件,(实现socket和标准输入输出)
#include "gpio.h"								//LED灯的使能
#define	SERVER_PORT			50000				//配置服务器端口号,最好设为2000以后,之前的端口部分在其它通信协议中被默认使用

uint8_t data_buffer[100];						//定义接收到的数据Buff大小为100
char tcp_server_recvbuf[300];					//定义数据处理Buff大小为300(为100也无所谓,只要大于等于100就好)

static void tcp_server_thread(void *p_arg)		//定义TCP服务器线程
{
	struct sockaddr_in server_addr;				//服务器地址
	struct sockaddr_in conn_addr;				//连接地址
	int sock_fd;								//服务器的 socked 
	int sock_conn;								// 请求的 socked 
	socklen_t addr_len;							// 地址长度 
	int err;
	int length;
	int num;
//	int count = 0;
	
	
	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);		//建立一个新的socket连接	
	memset(&server_addr, 0, sizeof(server_addr));				//将服务器地址清空
	server_addr.sin_family = AF_INET;							//地址家族
	server_addr.sin_addr.s_addr =htonl(INADDR_ANY);				//注意转化为网络字节序
	server_addr.sin_port = htons(SERVER_PORT);					//使用SERVER_PORT指定为程序头设定的端口号
	
	err = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));	//建立绑定
	if (err < 0)															    //如果绑定失败则关闭套接字
	{
			closesocket(sock_fd); 												//关闭套接字
	}
	
	err = listen(sock_fd, 1);									//监听连接请求
	if (err < 0) 												//如果监听失败则关闭套接字
	{
			closesocket(sock_fd); 								//关闭套接字
	}
		addr_len = sizeof(struct sockaddr_in);					//将链接地址赋值给addr_len
	
		sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len);	//对监听到的请求进行连接,状态赋值给sock_conn
	
		if(sock_conn<0)											//状态小于0代表连接故障,此时关闭套接字
		{
			closesocket(sock_fd);
		}
		else send(sock_conn, "connect success!\n\r", 20, 0);	//连接成功则发送“connect success!”给客户端
	
	while (1) 
	{
		memset(data_buffer, 0, sizeof(data_buffer));			//清空接收Buff
		
		length = recv(sock_conn, (unsigned int *)data_buffer, 100, 0);	//将收到的数据放到接收Buff
		
		for(num=0;num<100;num++)								//接收Buff的数据转移到数据处理Buff,防止之后数据混乱		
		{
			tcp_server_recvbuf[num]=data_buffer[num];
		}
		
		if(tcp_server_recvbuf[2]=='L'&tcp_server_recvbuf[3]=='E'&tcp_server_recvbuf[4]=='D'&
									tcp_server_recvbuf[5]=='1'&tcp_server_recvbuf[6]=='O'&tcp_server_recvbuf[7]=='N')
									//判断收到的数据是否为LED1ON
								{
								HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_0, GPIO_PIN_RESET);		//打开LED1
								send(sock_conn, "LED1已打开\n",strlen("LED1已打开\n"), 1);	//回复客户端LED1已打开

								}
								
								if(tcp_server_recvbuf[2]=='L'&tcp_server_recvbuf[3]=='E'&tcp_server_recvbuf[4]=='D'&
									tcp_server_recvbuf[5]=='1'&tcp_server_recvbuf[6]=='O'&tcp_server_recvbuf[7]=='F'&tcp_server_recvbuf[8]=='F')
									//判断收到的数据是否为LED1OFF
								{
								HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_0, GPIO_PIN_SET);		//关闭LED1
								send(sock_conn, "LED1已关闭\n",strlen("LED1已关闭\n"), 1);	//回复客户端LED1已关闭
								}
								/*LED0使用指令*/
								if(tcp_server_recvbuf[0]=='L'&tcp_server_recvbuf[1]=='E'&tcp_server_recvbuf[2]=='D'&
									tcp_server_recvbuf[3]=='0'&tcp_server_recvbuf[4]=='O'&tcp_server_recvbuf[5]=='N')	
									//判断收到的数据是否为LED0ON
								{
								HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_1, GPIO_PIN_RESET);		//打开LED0
								send(sock_conn, "LED0已打开\n",strlen("LED0已打开\n"), 1);	//回复客户端LED0已打开
								}
								
								if(tcp_server_recvbuf[2]=='L'&tcp_server_recvbuf[3]=='E'&tcp_server_recvbuf[4]=='D'&
									tcp_server_recvbuf[5]=='0'&tcp_server_recvbuf[6]=='O'&tcp_server_recvbuf[7]=='F'&tcp_server_recvbuf[8]=='F')
									//判断收到的数据是否为LED0OFF
								{
								HAL_GPIO_WritePin(GPIOB,  GPIO_PIN_1, GPIO_PIN_SET);		//关闭LED0
								send(sock_conn, "LED0已关闭\n",strlen("LED0已关闭\n"), 1);	//回复客户端LED0已关闭
								}
	}
}

void tcp_server_init(void)	//TCP服务器初始化
{
	sys_thread_new("tcp_server_thread",  tcp_server_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO - 1);
		//进入TCP服务器线程
}

将上述文件包含在生成的项目中,打开项目,文件列表中找到Application/User/freertos.c,在该文件下生成的TCP任务中写上tcp_server_init();
如图所示
在这里插入图片描述
编译工程之后下载到开发板,设置好PC机的IP地址等连接测试

三、实验结果

打开网络调试助手,对STM32进行连接,连接成功会提示connect success!
输入LED0ON发送后会返回LED0已打开,
在这里插入图片描述
开发板如图,DS0已亮
DS0已亮
接下来就不给大家赘述了,以上就是该实验的全部过程,感谢采纳。
本文作者为CSDN的ASWaterbenben写博不易,转载的时候请附上来源,谢谢大佬。

发布了20 篇原创文章 · 获赞 53 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ASWaterbenben/article/details/89922859
今日推荐