野火挑战者V2开发板CubeMX+LWIP+FreeRTOS+TCP_Server+TCP_Client实现
首先说一下开发环境:MDK5版本为5.26.2.0,CubeMX版本为6.6.1,FreeRTOS API选择的是 CMSIS v1,LWIP版本为2.1.2。单片机型号为STM32F429IGT6,以太网芯片为LAN8720A。
接下来开始进入正题,首先是基础的时钟、GPIO、LWIP方面的配置,具体流程如下:
1、时钟选择外部高速时钟(25M),系统时钟180M,SYS设置界面的Timebase Source项应当设置为SysTick以外的任何一项,因为SysTick将作为FreeRTOS系统的时钟源。
2、设置LED引脚PH10。
3、选择一组串口作为日志输出串口,打开串口,允许中断
4、配置ETH:
选择RMII连接方式。
勾上Ethernet global interrupt中断
修改ETH_TXD0、ETH_TXD1引脚为PG13 PG14
修改PHY引脚为 LAN8742A_PHY_ADDRESS 控制。
打开LWIP功能,关闭LWIP_DHCH,设置静态IP、子网掩码、网关。
进入Platform Settings页面选择网络芯片为LAN_8742A。
进入Key Options页面使能LWIP_NETIF_STATUS_CALLBACK。
在完成基础工程的配置以后再进入FreeRTOS的配置。进入FreeRTOS选项卡后选择CMSIS v1。相关设置直接默认,不需要改。直接进入Tasks and Queues选项卡设置任务。进入时会有一个默认任务,LWIP任务会自动加入该任务栈。双击该任务行任意位置,在弹出的界面中将Stack Size (Words)项的值改为256(更大也行),该项是设置该任务的内存大小,随后点击OK保存。为了测试方便我还创建了个Task2,任务名为LED_Task,其余默认,,随后点击OK保存。
最后 设置工程名称和保存地址,生成工程,打开工程进行如下操作:
5、首先修改MDK5的一些设置,最重要的是把这个 Use MicroLIB 勾上,不勾跑不起来:
6、全局搜索“LAN8742A_PHY_ADDRESS ”宏定义,将其的值改为0,或者main函数开头添加以下语句:
#ifdef LAN8742A_PHY_ADDRESS #undef LAN8742A_PHY_ADDRESS#define LAN8742A_PHY_ADDRESS 0U#endif
7、如有需要可以添加串口重定向:
首先加入头文件:#include "stdio.h"
随后在工程任意位置加入以下代码:
int fputc(int ch, FILE *f)
{//具体哪个串口可以更改huart1为其它串口HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0x0f);return ch;
}
8、如果需要,可以在添加LWIP日志管理代码,粘贴于lwipopts.h中
#define LWIP_DEBUG 1
#if LWIP_DEBUG
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
/* USER CODE BEGIN 1 */
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF
//#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_WARNING
//#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_SERIOUS
//#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_SEVERE#define ETHARP_DEBUG LWIP_DBG_ON
#define NETIF_DEBUG LWIP_DBG_ON
#define PBUF_DEBUG LWIP_DBG_ON
#define API_LIB_DEBUG LWIP_DBG_ON
#define API_MSG_DEBUG LWIP_DBG_ON
#define SOCKETS_DEBUG LWIP_DBG_ON
#define ICMP_DEBUG LWIP_DBG_ON
#define IGMP_DEBUG LWIP_DBG_ON
#define INET_DEBUG LWIP_DBG_ON
#define IP_DEBUG LWIP_DBG_ON
#define IP_REASS_DEBUG LWIP_DBG_ON
#define RAW_DEBUG LWIP_DBG_ON
#define MEM_DEBUG LWIP_DBG_ON
#define MEMP_DEBUG LWIP_DBG_ON
#define SYS_DEBUG LWIP_DBG_ON
#define TCP_DEBUG LWIP_DBG_ON
#define TCP_INPUT_DEBUG LWIP_DBG_ON
#define TCP_FR_DEBUG LWIP_DBG_ON
#define TCP_RTO_DEBUG LWIP_DBG_ON
#define TCP_CWND_DEBUG LWIP_DBG_ON
#define TCP_WND_DEBUG LWIP_DBG_ON
#define TCP_OUTPUT_DEBUG LWIP_DBG_ON
#define TCP_RST_DEBUG LWIP_DBG_ON
#define TCP_QLEN_DEBUG LWIP_DBG_ON
#define UDP_DEBUG LWIP_DBG_ON
#define TCPIP_DEBUG LWIP_DBG_ON
#define PPP_DEBUG LWIP_DBG_ON
#define SLIP_DEBUG LWIP_DBG_ON
#define DHCP_DEBUG LWIP_DBG_ON
#define AUTOIP_DEBUG LWIP_DBG_ON
#define SNMP_MSG_DEBUG LWIP_DBG_ON
#define SNMP_MIB_DEBUG LWIP_DBG_ON
#define DNS_DEBUG LWIP_DBG_ON
#endif //LWIP_DEBUG
若需关闭,将#define LWIP_DBG_TYPES_ON LWIP_DBG_ON 修改为
#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF
至此工程已经配置完成,编译工程下到开发板中,可以ping通,如下图:
在写这篇文章之前笔者就踩了大坑,那就是默认任务没有加大内存,也只设置了128 Words,然后一直ping不通,困了几天,后面是请教别的大佬才顺利解决。
第二天续写:
如果要实现TCP Server功能只需要新建两个文件,将其加入工程中(别忘了编译路径,我是放在了LWIP/APP目录下),代码如下:
tcpecho.c代码:
#include "tcpecho.h"#include "lwip/opt.h"#if LWIP_SOCKET
#include <lwip/sockets.h>#include "lwip/sys.h"
#include "lwip/api.h"
/*-----------------------------------------------------------------------------------*/
#define LOCAL_PORT 5001
#define RECV_DATA (1024)static void
tcpecho_thread(void *arg)
{int sock = -1,connected;char *recv_data;struct sockaddr_in server_addr,client_addr;socklen_t sin_size;int recv_data_len;printf("本地端口号是%d\n\n",LOCAL_PORT);recv_data = (char *)pvPortMalloc(RECV_DATA);if (recv_data == NULL){printf("No memory\n");goto __exit;}sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){printf("Socket error\n");goto __exit;}server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(LOCAL_PORT);memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){printf("Unable to bind\n");goto __exit;}if (listen(sock, 5) == -1){printf("Listen error\n");goto __exit;}while(1){sin_size = sizeof(struct sockaddr_in);connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);printf("new client connected from (%s, %d)\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));{int flag = 1;setsockopt(connected,IPPROTO_TCP, /* set option at TCP level */TCP_NODELAY, /* name of option */(void *) &flag, /* the cast is historical cruft */sizeof(int)); /* length of option value */}while(1){recv_data_len = recv(connected, recv_data, RECV_DATA, 0);if (recv_data_len <= 0) break;printf("recv %d len data\n",recv_data_len);write(connected,recv_data,recv_data_len);}if (connected >= 0) closesocket(connected);connected = -1;}
__exit:if (sock >= 0) closesocket(sock);if (recv_data) free(recv_data);
}
/*-----------------------------------------------------------------------------------*/
void
tcpecho_init(void)
{sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, 512, 4);
}
/*-----------------------------------------------------------------------------------*/#endif /* LWIP_NETCONN */
tcpecho.h代码如下;
#ifndef LWIP_TCPECHO_H
#define LWIP_TCPECHO_Hvoid tcpecho_init(void);#endif /* LWIP_TCPECHO_H */
之后在main.h添加代码头文件(其他地方也行,只要不报错):#include "tcpecho.h"
最后再找到FreeRTOS的第一个任务,将"tcpecho_init();"语句添加到语句 "MX_LWIP_Init();的后面即可",随后编译,再用网络调试助手进行TCP连接已经可以连接上,并且发送的信息还可以回显,如下图:
第三天续写:
如果要实现TCP_Client功能,只需在第一天的基础上做些许改动,具体步骤如下:
新建两个文件,将其加入工程中(别忘了编译路径,我是放在了LWIP/APP目录下),代码如下:
"client.c"代码如下:
/** Copyright (c) 2001-2003 Swedish Institute of Computer Science.* All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met:** 1. Redistributions of source code must retain the above copyright notice,* this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright notice,* this list of conditions and the following disclaimer in the documentation* and/or other materials provided with the distribution.* 3. The name of the author may not be used to endorse or promote products* derived from this software without specific prior written permission. ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE.** This file is part of the lwIP TCP/IP stack.* * Author: Adam Dunkels <adam@sics.se>**/
#include "client.h"#include "lwip/opt.h"#include "lwip/sys.h"
#include "lwip/api.h"#include <lwip/sockets.h>#define DEST_IP_ADDR0 192
#define DEST_IP_ADDR1 168
#define DEST_IP_ADDR2 0
#define DEST_IP_ADDR3 15#define DEST_PORT 5001static void client(void *thread_param)
{int sock = -1;struct sockaddr_in client_addr;ip4_addr_t ipaddr;uint8_t send_buf[]= "This is a TCP Client test...\n";printf("目地IP地址:%d.%d.%d.%d \t 端口号:%d\n\n", \DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3,DEST_PORT);printf("请将电脑上位机设置为TCP Server.在User/arch/sys_arch.h文件中将目标IP地址修改为您电脑上的IP地址\n\n");printf("修改对应的宏定义:DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3,DEST_PORT\n\n");IP4_ADDR(&ipaddr,DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3);while(1){sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){
// printf("Socket error\n");vTaskDelay(10);continue;} client_addr.sin_family = AF_INET; client_addr.sin_port = htons(DEST_PORT); client_addr.sin_addr.s_addr = ipaddr.addr;memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero)); if (connect(sock, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1) {
// printf("Connect failed!\n");closesocket(sock);vTaskDelay(10);continue;} printf("Connect to server successful!\n");while (1){if(write(sock,send_buf,sizeof(send_buf)) < 0)break;vTaskDelay(1000);}closesocket(sock);}}void
client_init(void)
{sys_thread_new("client", client, NULL, 512, 4);
}
"client.h"代码如下:
#ifndef _CLIENT_H
#define _CLIENT_Hvoid client_init(void);#endif /* _CLIENT_H */
之后在main.h添加代码头文件(其他地方也行,只要不报错):#include "tcpecho.h"
最后再找到FreeRTOS的第一个任务,将"tcpecho_init();"语句添加到语句 "client_init();的后面即可",随后编译,再用网络调试助手创建TCP_Server,将代码下入开发板一会可以看到已经可以连接上,定时接收到开发板发送的消息,并且电脑发送的信息还可以回显,如下图:
至此LWIP+FreeRTOS进行TCP连接的功能就已经全部实现了,但是我还发现一个问题就是当程序正常运行时如果按下复位键重启,任务可以正常运行,LED灯可以正常闪烁,但是LWIP不能正常运行,电脑也ping不通,除非开发板断电重启。这个问题我也是刚发现,具体问题还需后面继续查找,待找到原因后将会更新后续。
事隔接近10天后,终于把剩下的问题解决了,最近大降温,同时也比较忙,终于有时间把它解决了。
之前遗留的问题其实就是热插拔的问题。这段时间我也参考了很多大佬的解决办法,但是我尝试了适合我们这种静态IP的解决办法的就是增加3个字符:找到ethernetif.c文件,将其中的ethernet_link_thread函数的倒数第三条语句“HAL_ETH_Start(&heth);”修改成“HAL_ETH_Start_IT(&heth);”。其实就是在括号前加了“_IT”这三个字符。虽然只是简单的换了字符,但是启动方式却不一样,采用中断接收后热插拔的功能也就实现了。
至此STM32F4 LWIP+FreeRTOS实现TCP通信的博客终于告一段落!希望对大家有所帮助。
野火挑战者V2开发板CubeMX+LWIP+FreeRTOS+TCP_Server+TCP_Client实现相关推荐
- 性能猛兽野火STM32H743 V2开发板跑Linux 5.10,分数爆炸1836.884644
研究了三个月的移植过程,终于能运行了.用户名:root 密码:123 附件附上二进制文件: 1.将uboot.bin下载到stm32 flash 0x08000000 2.将stm32h743-fir ...
- 使用轮询方式进行ADC转换(野火STM32 MINI开发板)
实验器材:野火STM32 MINI开发板 任务目标:利用ADC采集电位器的电压,并通过串口调试助手输出变化的电压值 任务内容:调整开发板上的滑动变阻器,将电压值通过开发板到PC进行显示 开发板原理图: ...
- 基于野火F407骄阳开发板的苹果采摘机器人机械臂的采摘轨迹与夹持器的采摘动作的设计(1)
基于野火F407骄阳开发板的苹果采摘机器人机械臂的采摘轨迹与夹持器的采摘动作的设计(1) 苹果采摘机器人 1.采摘流程与硬件设计 2.机械臂驱动以及采摘轨迹设计 2.1.台达A2电机驱动实现 2.2. ...
- 野火EBF 6ULL 开发板 烧录ubuntu18 emmc 固件 并安装桌面
一. 选择官方教程 镜像构建 镜像构建 使用MfgTool进行烧录 烧录 一. 选择下载我打包好的工具和镜像进行烧录 下载地址 镜像配置在cfg.ini 默认是ubuntu18.04 bionic 是 ...
- 野火的DSP28335开发板吧代码烧写到Flash中
说明是针对野火的DSP28335开发板里的例程进行实验的,环境是CCS5.5,已经验证.开发板里的例程都是在RAM里运行的,每次开机都是祝你生日快乐的音乐,经过一周的努力终于不用再受音乐的困扰.可以随 ...
- 野火的6ull开发板TF卡问题
项目场景: 野火的6ull开发板将内核和文件系统都放在tf卡中运行 问题描述: Uboot能正常运行,在Uboot中能正常读写TF卡,能正常启动内核,完成其它初始化后,卡在TF卡初始化部分,但偶尔也能 ...
- 【FreeRTOS】在Cortex-M4开发板上移植FreeRTOS并且实现LED灯闪烁(保姆级教程)
相信有不少小伙伴手上只有M4的开发板,想要移植FreeRTOS:但是,网上大部分都是M3移植教程.因此,陷入深深的迷茫中,难不成只能使用仿真了???
- 启明欣欣STM32开发板 --- 运行LWIP (无RTOS)
最近体验了一下CubeMX,发现真的是非常好用,里面使用了ST自家的HAL库,这应该是ST的策略,为了绑定客户- 本文讲述使用CubeMX生成LWIP的Keil工程并在启明欣欣板子上运行,不使用RTO ...
- 春节烟花特效(基于野火stm32指南者开发板屏幕)
先来看看效果 就是一个基于stm32的野火例程的一个改进,实现了一个小小的烟花特效 没啥创新点 就改了一个函数(基于野火stm32的例程进行了应用的修改而已) 可以更方便的画直线 配了点蜂鸣器电路 声 ...
最新文章
- Ubuntu开机自启动与sh脚本
- LeetCode Gray Code(回溯法)
- Lambda 表达式(=):网络摘抄,自学用,侵删。
- mybaits三:全局配置文件(全面)
- QML Camera 摄像头拍照(带滑动条设置焦距)
- php 快递查询,PHP查询快递信息
- Debian7.2上一键安装Jetty
- HDU 3342 Legal or Not(拓扑排序)
- 【渝粤教育】国家开放大学2018年春季 0089-21TInternet和Intranet应用 参考试题
- JStorm—实时流式计算框架入门介绍
- 测试线程池(Java)
- Jmeter(三十八)while控制器实现ssh三次重连
- python 反弹shell,加了UDP
- 统一认证 - Apereo CAS 客户端的集成以及小结
- PHP array_rand随机获取数组中的数据
- Android学习分享:执行某ViewGroup的动画时,子控件太多导致动画执行卡顿的问题...
- 中兴捧月2020年比赛CV方向思路
- 计算机网络思科DNS配置,Cisco交换机 正确连接和初级配置
- oracle中..符号,oracle中带有特殊符号的模糊查询
- 关于xpath解析网页中tbody问题
热门文章
- 使用n2disk和PF_RING构建一个(便宜的)连续数据包记录器(Part2)
- html文本角标设计,css实现角标
- 物联网时代25大开源IoT框架
- 相机标定详解(转载不易)
- 教你如何进行c字符串解密
- c语言如何打开文件并进行编辑,C语言打开并写入文件
- Spellman电源维修FF60P4X3313荧光光谱仪维修
- 计算机985大学高考分数,高考志愿“捡漏王”。460分被985大学录取,考生填报志愿要注意...
- java 员工信息_JAVA控制台输入输出员工信息
- Laravel中错误页面的显示