STM32407+LAN8720A+LWIP 实现TCP Client

硬件

一、配置CubeMax工程

二、配置系统时钟

因为LAN8720使用的是外部25MHz的晶振,所以不需要单片机输出时钟

三、配置ETH和LWIP参数

四、更改代码

LAN8720A在初始化的时候需要复位,因此在ethernetif.c的 static void low_level_init(struct netif *netif) 函数中添加LAN8720A 的复位程序

再mian函数主循环中添加一下代码,然后编译运行,正常的话,再路由器中能看到程序中设置的MAC地址,以及分配的IP,此时能够ping通

MX_LWIP_Process();

成功了?NoNoNO,如果你启动的时候没有接网线,等启动之后,再插上网线,你会发现,板子死活都不会找dhcp服务器要IP, 结果就是失联。。重大缺陷,不能忍!幸亏LWIP协议栈早就想到了这种情况,LWIP_NETIF_LINK_CALLBACK是干嘛的?就是在连接状态改变的时候,调用一个回调函数,来做相应的处理

在main函数的住循环中加入

1extern struct netif *netif_default; 2ethernetif_set_link(netif_default);

这个函数会查询当前的连接状态,当状态改变的时候,调用回调函数,在ethernetif.c里我们可以找到这个回调函数,

void ethernetif_update_config(struct netif *netif)

果然有很多处理,那为什么还是不能打开dhcp呢?来看看这个函数的末尾,调用了这个函数

ethernetif_notify_conn_changed()

这个函数,而这个函数看看注释就知道,是需要咱自己来实现的,所以我们加入以下的代码

1 1 /** 2 2 * @brief This function notify user about link status changement. 3 3 * @param netif: the network interface 4 4 * @retval None 5 5 */ 6 6 __weak void ethernetif_notify_conn_changed(struct netif *netif) 7 7 { 8 8 /* NOTE : This is function could be implemented in user file 9 9 when the callback is needed, 1010 */ 1111 if(netif_is_link_up(netif) && !netif_is_up(netif)) 1212 { 1313 netif_set_up(netif); 1414 extern err_t dhcp_start(struct netif *netif); 1515 dhcp_start(netif); 1616 } 1717 }

重编译下载,拔掉网线,开机,再插上网线,获得了IP, 大功告成!

五、添加API文件

从库中示例代码中把LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c 和 tcp_echoclient.h 拷贝到工程中,然后添加发送函数

1 1 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size) 2 2 { 3 3 err_t ret_err; 4 4 struct echoclient *es; 5 5 es=tpcb->callback_arg; 6 6 if(es!=NULL) //连接处于空闲时可以发送数据 7 7 { 8 8 es->p_tx=pbuf_alloc(PBUF_TRANSPORT, size,PBUF_POOL); //申请内存 9 9 pbuf_take(es->p_tx,(char*)buff,size); //将tcp_client_sentbuf[]中的数据拷贝到es->p_tx中 1010 tcp_echoclient_send(tpcb,es);  //将tcp_client_sentbu[]里面复制给pbuf的数据发送出去 1111 if(es->p_tx)pbuf_free(es->p_tx); //释放内存 1212 ret_err=ERR_OK; 1313 }else 1414 { 1515 tcp_abort(tpcb);  //终止连接,删除pcb控制块 1616 ret_err=ERR_ABRT; 1717 } 1818 return ret_err; 1919 }

在 tcp_echoclient.h中需要添加连接到的服务器的IP地址和端口

1 1 #include "err.h" 2 2 #include "tcp.h" 3 3 /* Includes ------------------------------------------------------------------*/ 4 4 /* Exported types ------------------------------------------------------------*/ 5 5 /* Exported constants --------------------------------------------------------*/ 6 6 /* Exported macro ------------------------------------------------------------*/ 7 7 /* Exported functions ------------------------------------------------------- */ 8 8 void tcp_echoclient_connect(void); 9 9 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size); 1010 1111 #define DEST_IP_ADDR0 192 1212 #define DEST_IP_ADDR1 168 1313 #define DEST_IP_ADDR2 000 1414 #define DEST_IP_ADDR3 108 1515 1616 1717 #define DEST_PORT 9001

 通过以上更改,就可以使用 tcp_client_usersent()函数进行发送数据了

11 /** 22 * @brief 发送数据包 33 * @retval None 44 */ 55 void UCP_DataAnswer(void) 66 { 77 tcp_client_usersent(echoclient_pcb, ToSendBuf, 23); 88 tcp_client_usersent(echoclient_pcb, DeSendBuf, 23); 99 }

上面已经能正常发送数据了,如果我把网线拔下来,在插上去又怎么样呢,试试?所有在main函数的主循环中增加断线重连的代码

1 1 /* USER CODE BEGIN WHILE */ 2 2 while (1) 3 3 { 4 4 HAL_GPIO_TogglePin(ALARM_GPIO_Port, ALARM_Pin); 5 5 MX_LWIP_Process(); // LwIP Initialization 6 6 ethernetif_set_link(netif_default); // This function sets the netif link status. 7 7 8 8 // 拔掉网线后,由于服务端单向断开连接,客户端会进入FIN_WAIT_2等待状态 9 9 if(echoclient_pcb->state == CLOSED || echoclient_pcb->state == FIN_WAIT_2) 1010 { 1111 tcp_abort(echoclient_pcb); 1212 tcp_echoclient_connect(); // 断线重连 1313 } 1414

 参考博客:https://blog.csdn.net/hustwf/article/details/80040578

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )