lwip路由实现_STM32407+LAN8720A+LWIP 实现TCP Client

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-17 08:11   50   0

硬件

一、配置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函数的住循环中加入

extern struct netif *netif_default;

ethernetif_set_link(netif_default);

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

void ethernetif_update_config(struct netif *netif)

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

ethernetif_notify_conn_changed()

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

1 /**2 * @brief This function notify user about link status changement.3 * @param netif: the network interface4 * @retval None5 */

6 __weak void ethernetif_notify_conn_changed(struct netif *netif)7 {8 /*NOTE : This is function could be implemented in user file9 when the callback is needed,10 */

11 if(netif_is_link_up(netif) && !netif_is_up(netif))12 {13 netif_set_up(netif);14 extern err_t dhcp_start(struct netif *netif);15 dhcp_start(netif);16 }17 }

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

五、添加API文件

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

1 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size)2 {3 err_t ret_err;4 struct echoclient *es;5 es=tpcb->callback_arg;6 if(es!=NULL) //连接处于空闲时可以发送数据

7 {8 es->p_tx=pbuf_alloc(PBUF_TRANSPORT, size,PBUF_POOL); //申请内存

9 pbuf_take(es->p_tx,(char*)buff,size); //将tcp_client_sentbuf[]中的数据拷贝到es->p_tx中

10 tcp_echoclient_send(tpcb,es);  //将tcp_client_sentbu[]里面复制给pbuf的数据发送出去

11 if(es->p_tx)pbuf_free(es->p_tx); //释放内存

12 ret_err=ERR_OK;13 }else

14 {15 tcp_abort(tpcb);  //终止连接,删除pcb控制块

16 ret_err=ERR_ABRT;17 }18 returnret_err;19 }

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

1 #include "err.h"

2 #include "tcp.h"

3 /*Includes ------------------------------------------------------------------*/

4 /*Exported types ------------------------------------------------------------*/

5 /*Exported constants --------------------------------------------------------*/

6 /*Exported macro ------------------------------------------------------------*/

7 /*Exported functions -------------------------------------------------------*/

8 void tcp_echoclient_connect(void);9 err_t tcp_client_usersent(struct tcp_pcb *tpcb, uint8_t *buff,uint16_t size);10

11 #define DEST_IP_ADDR0 192

12 #define DEST_IP_ADDR1 168

13 #define DEST_IP_ADDR2 000

14 #define DEST_IP_ADDR3 108

15

16

17 #define DEST_PORT 9001

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

1 /**2 * @brief 发送数据包3 * @retval None4 */

5 void UCP_DataAnswer(void)6 {7 tcp_client_usersent(echoclient_pcb, ToSendBuf, 23);8 tcp_client_usersent(echoclient_pcb, DeSendBuf, 23);9 }

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

1 /*USER CODE BEGIN WHILE*/

2 while (1)3 {4 HAL_GPIO_TogglePin(ALARM_GPIO_Port, ALARM_Pin);5 MX_LWIP_Process(); //LwIP Initialization

6 ethernetif_set_link(netif_default); //This function sets the netif link status.7

8 //拔掉网线后,由于服务端单向断开连接,客户端会进入FIN_WAIT_2等待状态

9 if(echoclient_pcb->state == CLOSED || echoclient_pcb->state ==FIN_WAIT_2)10 {11 tcp_abort(echoclient_pcb);12 tcp_echoclient_connect(); //断线重连

13 }14

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP