热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【HAL库】STM32CubeMX开发STM32F407ETH+LWIPTCPclient客户端

STM32CubeMX下载和安装详细教程【HAL库】STM32CubeMX开发----STM32F407----目录前言本次实验主要实现:STM32F407开发板为

STM32CubeMX 下载和安装 详细教程
【HAL库】STM32CubeMX开发----STM32F407----目录



前言

本次实验主要实现:
STM32F407开发板 为 TCPclient客户端,PC端 为 TCPserver服务端,相互之间的发送和接收实验。

前期准备----完美Ping通环境

本次实验需要在STM32F407开发板与PC端,完美Ping通 的前提下,进行 TCPclient 客户端程序设计。

关于如何实现STM32F407开发板和PC端的以太网通信,如何完美Ping通。
相关文章链接:【HAL库】STM32CubeMX开发----STM32F407----ETH+LAN8720A+LWIP----ping通

一、TCPclient客户端----相关函数

TCPclient客户端开发,使用到的相关LWIP API函数,具体如下:

函数描述
tcp_new();创建一个新的TCP协议控制块
tcp_connect();建立远端服务器连接
tcp_err();错误回调函数
tcp_poll();周期性回调函数—最快1s调用两次
tcp_sent();发送回调函数
tcp_recv();接收回调函数
tcp_recved();应用程序在处理数据后应调用此函数,通知内核更新接收窗口
tcp_write();将要发送的数据写入发送缓存队列中
tcp_output();将发送缓冲队列中的数据发送出去
tcp_close();关闭TCP连接
tcp_abort();中断TCP连接

二、TCPclient客户端----开发流程

创建 两个文件 TCPclient.c 和 TCPclient.h,用来存储功能程序。

步骤1:创建 TCPclient 初始化函数

void TCP_Client_Init(void)
{ struct tcp_pcb *client_pcb = NULL;ip4_addr_t server_ip; //服务器的IP地址 client_pcb = tcp_new(); //创建一个TCP控制块 IP4_ADDR(&server_ip, 192,168,1,20); //将目标服务器IP写入结构体,这里是PC机本地IP地址if(client_pcb != NULL){//开始与目标服务器进行连接,参数包括服务器IP和服务器端口tcp_connect(client_pcb, &server_ip, 18099, client_connected);//注册异常处理函数tcp_err(client_pcb, client_error);}
}

步骤2:创建 注册回调函数

/* TCP客户端连接到服务器回调函数 */
static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{//注册一个周期性回调函数---最快500ms一次tcp_poll(pcb,client_poll,1);//注册一个发送回调函数tcp_sent(pcb, client_send);//注册一个接收回调函数tcp_recv(pcb,client_recv);return ERR_OK;
}

步骤3:编写 数据处理函数


1. 周期轮询处理函数

周期轮询处理,最快500ms一次

/* TCP客户端 周期轮询处理函数*/
static err_t client_poll(void *arg, struct tcp_pcb *tpcb)
{/*编写用户想要实现的功能程序*/return ERR_OK;
}

2. 发送处理函数

这里编写发送数据,然后通过tcp_write();加载到发送缓冲中。

/* TCP客户端 发送处理函数*/
static err_t client_send(void *arg, struct tcp_pcb *tpcb, u16_t len)
{/*这里编写发送数据,然后通过tcp_write();加载到发送缓冲中举例如下:char send_buf[] = "工欲善其事,必先利其器。";tcp_write(tpcb, send_buf,strlen(send_buf), 1);//发送数据*/return ERR_OK;
}

3. 接收处理函数

接收数据,然后处理数据

/* TCP客户端 接收处理函数*/
static err_t client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{if (p != NULL) { /* 接收数据*/tcp_recved(tpcb, p->tot_len);/*这里编写处理数据程序*/memset(p->payload, 0 , p->tot_len);pbuf_free(p);} return ERR_OK;
}

4. 异常处理函数

在调用异常处理函数时,说明TCP通信连接已经断开,相关TCP控制块已经删除。所以在这里我们可以重现初始化,重新启动连接。

/* TCP客户端 异常处理函数*/
static void client_error(void *arg,err_t err)
{ TCP_Client_Init();//产生异常的时候,重新启动连接
}

步骤5:在main主函数中调用TCP_Client_Init();

需要在主函数中调用 #include "TCPclient.h"
TCP_Client_Init(); 加入到初始化就行,不用加到主循环中。

/*其他调用函数*/
#include "TCPclient.h"int main(void)
{/*其他初始化函数*/TCP_Client_Init();while (1){MX_LWIP_Process();/*其他功能函数*/}
}

三、TCPclient客户端----具体程序

TCPclient.c

#include
#include
#include "lwip/netif.h"
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/init.h"
#include "netif/etharp.h"
#include "lwip/udp.h"
#include "lwip/pbuf.h"
#include "lwip/priv/tcp_priv.h"
#include "TCPclient.h"static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err); /* TCP客户端连接到服务器回调函数 */
static err_t client_send(void *arg, struct tcp_pcb *tpcb, u16_t len); /* TCP客户端 发送处理函数*/
static err_t client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);/* TCP客户端 接收处理函数*/
static err_t client_poll(void *arg, struct tcp_pcb *tpcb); /* TCP客户端 周期轮询处理函数*/
static void client_error(void *arg,err_t err);void TCP_Client_Init(void)
{ struct tcp_pcb *client_pcb = NULL;ip4_addr_t server_ip; //服务器的IP地址 client_pcb = tcp_new(); //创建一个TCP控制块 IP4_ADDR(&server_ip, DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3); //将目标服务器IP写入结构体,这里是PC机本地IP地址if(client_pcb != NULL){//开始与目标服务器进行连接,参数包括服务器IP和服务器端口tcp_connect(client_pcb, &server_ip, TCP_CLIENT_PORT, client_connected);//注册异常处理函数tcp_err(client_pcb, client_error);}}/* TCP客户端连接到服务器回调函数 */
static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{//注册一个周期性回调函数tcp_poll(pcb,client_poll,1);//注册一个发送回调函数tcp_sent(pcb, client_send);//注册一个接收回调函数tcp_recv(pcb,client_recv);//发送一个建立连接的问候数据tcp_write(pcb,"这里是客户端\n",strlen("这里是客户端\n"), 1);return ERR_OK;
}/* TCP客户端 周期轮询处理函数*/
static err_t client_poll(void *arg, struct tcp_pcb *tpcb)
{return ERR_OK;
}/* TCP客户端 发送处理函数*/
static err_t client_send(void *arg, struct tcp_pcb *tpcb, u16_t len)
{char send_buf[] = "工欲善其事,必先利其器。";tcp_write(tpcb, send_buf,strlen(send_buf), 1);//发送数据return ERR_OK;
}/* TCP客户端 接收处理函数*/
static err_t client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{if (p != NULL) { /* 接收数据*/tcp_recved(tpcb, p->tot_len);/* 发送接收到的数据*/ tcp_write(tpcb, p->payload, p->tot_len, 1);memset(p->payload, 0 , p->tot_len);pbuf_free(p);} return ERR_OK;
}/* TCP客户端 异常处理函数*/
static void client_error(void *arg,err_t err)
{ //产生异常的时候,重新启动连接TCP_Client_Init();
}

TCPclient.h

#ifndef _TCPclient_H_
#define _TCPclient_H_#include "main.h"//远端服务器端口
#define TCP_CLIENT_PORT 18099 //远端服务器IP地址
#define DEST_IP_ADDR0 192
#define DEST_IP_ADDR1 168
#define DEST_IP_ADDR2 1
#define DEST_IP_ADDR3 20void TCP_Client_Init(void);#endif

四、TCPclient客户端----调试程序

在确保STM32F407开发板与PC端,完美Ping通,然后打开网络调试助手。
网络调试助手下载链接:网络调试助手 点击下载

TCPclient客户端—发送

循环发送:工欲善其事,必先利其器。

在这里插入图片描述

TCPclient客户端—接收

将接收到的数据发送回去。

在这里插入图片描述



推荐阅读
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文介绍了网络编程的要点,包括InetAddress类获取IP地址的方法,IP地址的定义和表示方法,IPv4和IPv6的区别,以及网络通信协议中的端口和协议类型。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文介绍了如何使用iptables添加非对称的NAT规则段,以实现内网穿透和端口转发的功能。通过查阅相关文章,得出了解决方案,即当匹配的端口在映射端口的区间内时,可以成功进行端口转发。详细的操作步骤和命令示例也在文章中给出。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
author-avatar
whucad
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有