关于NUCLEO-F207ZG开发板通过STM32CubeMx配置(五)配置FreeRTOS+Lwip使用socketAPI进行tcp连接测试

目录

前言

一、详细步骤

1.配置UART打印调试信息

        1.1.配置UART5

        1.2.查看串口的引脚配置

        1.3.  UART5 NVIC Settings

        1.4.配置完成进行PING测试

2.写程序代码前的准备工作

         2.1. 在usart.c这个文件中重定向一下printf()这个函数的输出。

         2.2.在usart.c加上头文件”stdio.h”

         2.3.在main.h在头文件处加上”stdio.h”

           2.4.测试一下串口输出效果

3.在FreeRTOS任务1(Task1)中编写客户端代码,运行连接程序

        3.1.代码编写

        3.2.测试连接

3.在FreeRTOS任务2(Task2)中编写服务器端代码,运行连接程序

        3.1.代码编写

        3.2.测试连接

4.结束

总结



前言

        因为工作关系需要用到STM32F207ZGTx的芯片,所以公司购买了基于STM32F207ZGT6U芯片的ST开发板NUCLEO-F207ZG。而且要求使用FeeRTOS+Lwip的环境,来进行软件开发,主要目的是通过此环境,运行一个软件下载程序,此程序用到了lwip库封装的socket套接字函数库,通过Tcp请求服务器下载文件包。因为我自己第一次正式做一个关于STM32的程序项目,之前只是在学校学习和了解一些基础,认识比较浅显,所以写下本文来加深自己的学习和了解,并且总计经验分享出来,有问题可以共同探讨。

        本文内容:使用STM32CubeMx配置FreeRTOS和Lwip的例子在上一章已经讲过了就不重复列出来了,这里这里主要讲配置UART串口打印调试信息和使用Lwip库中socket套接字做tcp连接测试的例子和流程。

        配置软件:STM32CubeMx 6.2.1

        开发板:NUCLEO-F207ZG

        配置环境:FreeRTOS+Lwip

        编译软件:keil  5.27


一、详细步骤

1.配置UART打印调试信息

        1.1.配置UART5

                配置UART5作为打印信息的串口,默认波特率115200/bps,其他也是默认配置,如果有需要其他波特率可以根据自己需求修改。

        1.2.查看串口的引脚配置

                可以看到选择UART5后,CubeMx软件已经将串口的引脚配置完成了,我们只需要根据引脚进行接线即可。    

        1.3.  UART5 NVIC Settings

                NVIC Settings这里我没有开启中断,当然可以根据自己的需要开启。

        1.4.配置完成进行PING测试

                串口配置已经完成,生成后续时钟配置按照上一章的进行即可,接下来写代码。在写代码之前注意ping一下自己配置的ip,保证网卡驱动配置正确。

2.写程序代码前的准备工作

         2.1. 在usart.c这个文件中重定向一下printf()这个函数的输出。

                 代码:

/* USER CODE BEGIN 1 */
//这个变量是其他.c文件定义的
 //extern UART_HandleTypeDef huart1;
 uint8_t ch;
 uint8_t ch_r;
 //重写这个函数,重定向printf函数到串口,意思就是说printf直接输出到串口,其默认输出到控制台的
 /*fputc*/
int fputc(int c, FILE * f)
{
    ch=c;
     HAL_UART_Transmit(&huart5,&ch,1,1000);//发送串口
     return c;
 }
 
 //重定向scanf函数到串口 意思就是说接受串口发过来的数据,其默认是接受控制台的数据
 /*fgetc*/
 int fgetc(FILE * F)    
 {
     HAL_UART_Receive(&huart5,&ch_r,1,0xffff);//接收
     return ch_r;
 }
/* USER CODE END 1 */

         2.2.在usart.c加上头文件”stdio.h”

         2.3.在main.h在头文件处加上”stdio.h”

                        找到main.h在头文件处加上”stdio.h”,这样其他包含main.h的源文件都能够使用printf()打印调试信息,不然你使用printf()就需要在使用的源文件中声明stdio.h。

           2.4.测试一下串口输出效果

                        重定义准备完成,测试一下串口输出效果。在freertos.c的任务1函数,StartTask1(void const * argument)的for循环中运行调试信息,下载到开发板中,运行程序,打开串口调试软件,这里我的端口为COM7,所以选择com7,波特率115200bps,打开串口可以看到输出的信息,说明整个流程是成功的。

                        代码:

void StartTask1(void const * argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN StartTask1 */
  /* Infinite loop */
  for(;;)
  {
	printf("这是task1 打印调试信息!\r\n");
    osDelay(1000); //1s循环一次
  }
  /* USER CODE END StartTask1 */
}

3.在FreeRTOS任务1(Task1)中编写客户端代码,运行连接程序

        3.1.代码编写

                前期准备工作完成,接下来就是进行tcp编程了,先进行客户端代码的编写。

                代码:

void StartTask1(void const * argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN StartTask1 */
  /* Infinite loop */
  //tcp client 连接测试
	int iResult = 0;
	
	struct sockaddr_in conn_addr;				//连接地址
	int conn_fd;								//服务器的 socked 
//	int sock_conn;								// 请求的 socked 
//	socklen_t addr_len;							// 地址长度 
//	int err;
	printf("come StartTask1\r\n");
	


	conn_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	conn_addr.sin_family = AF_INET;
	conn_addr.sin_port = htons(28884);
	conn_addr.sin_addr.s_addr = inet_addr("192.168.0.64");

	if( connect(conn_fd, (struct sockaddr *)&conn_addr, sizeof(struct sockaddr_in)) == -1)
	{
			printf("connect error\n");
	}
	printf("connect successful!conn_fd=%d\r\n",conn_fd);
	
	unsigned char bTmpSendBuf[]="hello server!This is NUCLEO-F207ZGT6U connect!";
	  for(;;)
	  {
			write(conn_fd,bTmpSendBuf,sizeof(bTmpSendBuf));
			if(iResult>0)
			{
				printf("write successful Size=%d\r\n",iResult);
			}
		osDelay(1000);
	  }
  /* USER CODE END StartTask1 */
}

        3.2.测试连接

                创建一个tcp服务器端,接收NUCLEO-F207ZG开发板客户端的连接,我这里服务器端配置的ip是”192.168.0.64”,端口28884,可以看到客户端成功连接上服务器端

3.在FreeRTOS任务2(Task2)中编写服务器端代码,运行连接程序

        3.1.代码编写

                代码:

/* USER CODE END Header_StartTask2 */
void StartTask2(void const * argument)
{
  /* USER CODE BEGIN StartTask2 */
  /* Infinite loop */
 char data_buffer[512];
  /* Infinite loop */
	struct sockaddr_in server_addr;				//服务器地址
	struct sockaddr_in conn_addr;				//连接地址
	int sock_fd;								//服务器的 socked 
	int sock_conn;								// 请求的 socked 
	socklen_t addr_len;							// 地址长度 
	int err;
	printf("come StartTask2\r\n");
	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);		//建立一个新的socket连接	
	if(sock_fd<0)
	{
		printf("create sock_fd failed! sock_fd=%d\r\n",sock_fd);
	}
	printf("create sock_fd successful! sock_fd=%d\r\n",sock_fd);
	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(18885);					//使用指定端口号
	err = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));	//建立绑定
	if (err < 0)															    //如果绑定失败则关闭套接字
	{
		printf("bind socket failed!\r\n");
		closesocket(sock_fd); 												//关闭套接字
	}
	while(1)
	{		
		err = listen(sock_fd, 1);									//监听连接请求    1:ACCEPT队列的大小
		if (err < 0) 												//如果监听失败则关闭套接字
		{
			printf("listen socketFd failed!socketFd=%d\r\n",sock_fd);
			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代表连接故障,此时关闭套接字
		{
			printf("accept socketFd failed!socketFd=%d\r\n",sock_fd);
			closesocket(sock_fd);
		}
		while (1) 
		{
			memset(data_buffer, 0, sizeof(data_buffer));			//清空接收Buff
			int length = recv(sock_conn, (unsigned int *)data_buffer, 100, 0);	//将收到的数据放到接收Buff 100为可以接收的数据长度
			if(length > 0)
			{
				printf("recv buf data! size=%d\r\n",length);
				send(sock_conn, data_buffer,length, 1);	//回复客户端
				printf("[StartTask2] Send bufSize=%d\r\n",length);
			}
			else
			{
				printf("Recv error Data!\r\n");
				closesocket(sock_conn);
				break;
			}
			osDelay(1);
		}
		osDelay(1);
	}
  /* USER CODE END StartTask2 */
}

        3.2.测试连接

                (一)、创建客户端,这里目的服务器ip是开发板的ip192.168.0.179,端口:18885,ping一下测试是否能够连接,如果能够ping通,说明可以连接

                (二)、选择打开tcp,发送数据,可以看到串口打印了调试信息,NUCLEO-F207ZG服务器端接收到数据后完整返回给了客户端。这里表示整个流程成功。

4.结束



总结

  1. 通过以上测试我们就能够完整的掌握整个NUCLEO-F207ZG开发板配置FreeRTOS+LWIP然后进行tcp连接的一个完整流程了。
  2. 注意串口软件的波特率需要与配置串口的波特率一致。
  3. 在连接是需要多注意一下是否能够ping通,在运行程序连接。

版权声明:本文为CSDN博主「YanHuo_215」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/YanHuo_215/article/details/121612329

生成海报
点赞 0

YanHuo_215

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里