STM32 裸机 LWIP RAW接口 TCP客户端和服务端,以及UDP收发实现

RAW接口

RAW/Callback API 是 LwIP 的一大特色, 在没有操作系统支持的裸机环境中,只能使用这种 API 进行开发;此文章基于野火LWIP教程记录使用方法;使用CubeMX生成LWIP项目,1分钟就可实现TCP、UDP通信;很方便。

关于网线热插拔:我使用CubeMX生成的LWIP裸机项目中发现,网线热插拔在MX_LWIP_Process();已经做了相关处理。直接在轮询中调用即可。

/**
 * ----------------------------------------------------------------------
 * Function given to help user to continue LwIP Initialization
 * Up to user to complete or change this function ...
 * Up to user to call this function in main.c in while (1) of main(void)
 *-----------------------------------------------------------------------
 * Read a received packet from the Ethernet buffers
 * Send it to the lwIP stack for handling
 * Handle timeouts if LWIP_TIMERS is set and without RTOS
 * Handle the llink status if LWIP_NETIF_LINK_CALLBACK is set and without RTOS
 */
void MX_LWIP_Process(void)
{
/* USER CODE BEGIN 4_1 */
/* USER CODE END 4_1 */
  ethernetif_input(&gnetif);

/* USER CODE BEGIN 4_2 */
/* USER CODE END 4_2 */
  /* Handle timeouts */
  sys_check_timeouts();

  Ethernet_Link_Periodic_Handle(&gnetif); //检测网线连接状态

/* USER CODE BEGIN 4_3 */
/* USER CODE END 4_3 */
}

使用方法,MAIN函数部分。

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */

   TCP_Client_Init(); //TCP客户端
   TCP_Server_Init();  //TCP服务端
   UDP_Echo_Init();  //UDP通信
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 if(tick_1ms)
	 {
		MX_LWIP_Process();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		tick_1ms = false;
	 }
   }

TCP 客户端

#include "tcpclient.h"
#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 <stdio.h>	
#include <string.h>

#define TCP_CLIENT_PORT 5001
void TCP_Client_Init(void);


static struct tcp_pcb *client_pcb = NULL;

static void client_err(void *arg, err_t err)
{
  printf("connect error! closed by core!!\n");
	printf("try to connect to server again!!\n");
  
  //连接失败的时候释放TCP控制块的内存
  tcp_close(client_pcb);  
  
  //重新连接
  TCP_Client_Init();
}


static err_t client_send(void *arg, struct tcp_pcb *tpcb)
{
  uint8_t send_buf[]= "This is a TCP Client test...\n";
  
  //发送数据到服务器
  tcp_write(tpcb, send_buf, sizeof(send_buf), 1); 
  
  return ERR_OK;
}

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);
  } 
  else if (err == ERR_OK) 
  {
    //服务器断开连接
    printf("server has been disconnected!\n");
    tcp_close(tpcb);
    
    //重新连接
    TCP_Client_Init();
  }
  return ERR_OK;
}

static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
  printf("connected ok!\n");
  
  //注册一个周期性回调函数
  tcp_poll(pcb,client_send,2);
  
  //注册一个接收函数
  tcp_recv(pcb,client_recv);
  
  return ERR_OK;
}


void TCP_Client_Init(void)
{        
  ip4_addr_t server_ip;
  /* 创建一个TCP控制块  */
  client_pcb = tcp_new();	  

  IP4_ADDR(&server_ip, DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3);

  printf("client start connect!\n");
  
  //开始连接
  tcp_connect(client_pcb, &server_ip, TCP_CLIENT_PORT, client_connected); 
  
  //注册异常处理
  tcp_err(client_pcb, client_err); 	     
}

TCP服务端

#include "tcpserver.h"
#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 <stdio.h>	
#include <string.h>

#define TCP_Server_PORT 5001
void TCP_Server_Init(void);

static err_t tcpecho_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);
    
  } 
  else if (err == ERR_OK) 
  {
    return tcp_close(tpcb);
  }
  return ERR_OK;
}

static err_t tcpecho_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{     

  tcp_recv(newpcb, tcpecho_recv);
  return ERR_OK;
}

void TCP_Server_Init(void)
{
  struct tcp_pcb *pcb = NULL;	            		
  
  /* 创建一个TCP控制块  */
  pcb = tcp_new();	  
  
  /* 绑定TCP控制块 */
  tcp_bind(pcb, IP_ADDR_ANY, TCP_Server_PORT );       


  /* 进入监听状态 */
  pcb = tcp_listen(pcb);				

  /* 处理连接 */	
  tcp_accept(pcb, tcpecho_accept);   
}

UDP通信

搞不懂,UDP是无连接通信,不区分服务器和客户端;但是总有人分客户端和服务端。

#include "udpecho.h"
#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 <stdio.h>	
#include <string.h>	

#define UDP_ECHO_PORT 5001
void UDP_Echo_Init(void);

static void udp_demo_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
   struct pbuf *q = NULL;
   const char* reply = "This is reply!\n";

   if(arg)
   {
       printf("%s",(char *)arg);
   }

   pbuf_free(p);
   
   q = pbuf_alloc(PBUF_TRANSPORT, strlen(reply)+1, PBUF_RAM);
   if(!q)
   {
   	   printf("out of PBUF_RAM\n");
	   return;
   }

   memset(q->payload, 0 , q->len);
   memcpy(q->payload, reply, strlen(reply));
   udp_sendto(upcb, q, addr, port);
   pbuf_free(q);
}

static char * st_buffer= "We get a data\n";
void UDP_Echo_Init(void)
{
    struct udp_pcb *udpecho_pcb;
    /* 新建一个控制块*/      
    udpecho_pcb = udp_new();    

    /* 绑定端口号 */
    udp_bind(udpecho_pcb, IP_ADDR_ANY, UDP_ECHO_PORT);
    
    /* 注册接收数据回调函数 */
    udp_recv(udpecho_pcb, udp_demo_callback, (void *)st_buffer);
}
  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32CubeIDE是ST公司推出的一款开发工具,用于开发STM32系列微控制器。 LWIP(Lightweight IP)是一个轻量级的开源TCP/IP协议栈,适用于嵌入式系统。 在STM32CubeIDE中使用LWIP库进行UDP通信,可以通过以下步骤实现: 1. 首先,需要创建一个新的STM32项目,并选择合适的型号和外设。在项目配置中,选择LWIP库,并启用UDP协议。 2. 在代码中,需要进行一些配置。首先,在"LwIP SYS"组件中,设置正确的IP地址和子网掩码。然后,在"LwIP UDP"组件中,配置正确的端口号,以及设置允许UDP广播和多播。 3. 接下来,需要创建UDP通信的客户端和服务器端。客户端需要创建一个socket,并设置目标IP地址和端口号。然后,可以使用lwip_sendto函数发送UDP数据包。 4. 服务器端需要创建一个socket,并绑定到本地IP地址和端口号。然后,使用lwip_recvfrom函数接收来自客户端UDP数据包。 5. 在接收到UDP数据包后,可以对数据进行处理,并根据需要进行相应的操作。例如,可以将数据发送到其他设备,或者执行相应的程序逻辑。 通过以上步骤,就可以在STM32CubeIDE中使用LWIP实现UDP通信。在实际应用中,根据具体需求,可以进一步优化代码和功能,以实现更复杂的通信功能。 ### 回答2: STM32CubeIDE是STMicroelectronics推出的一款面向STM32微控制器的集成开发环境。它集成了STM32CubeMX配置工具和TrueSTUDIO IDE,可以方便地进行STM32微控制器的开发和调试。 lwIP是一个轻量级的嵌入式TCP/IP协议栈,它为嵌入式系统提供了网络通信功能。在STM32CubeIDE中,可以通过lwIP协议栈实现UDP通信。 在使用STM32CubeIDE进行lwIP UDP通信时,首先需要通过STM32CubeMX配置工具进行初始化设置。在配置工具中,可以选择启用lwIP协议栈,并设置相关的网络参数,如IP地址、子网掩码、网关等。同时,还可以选择启用UDP协议,并设置相关的端口号。 配置完成后,生成代码并导入到STM32CubeIDE中。接下来,可以在工程中编写相关的代码实现UDP通信功能。首先,需要创建一个UDP Socket,并设置相关的参数,如IP地址和端口号。然后,可以使用lwIP提供的API函数发送和接收UDP数据包。 发送UDP数据包时,可以使用lwIP提供的函数lwip_sendto(),将要发送的数据和目标地址通过参数传入。接收UDP数据包时,可以使用lwIP提供的函数lwip_recvfrom(),指定接收数据的缓冲区和缓冲区大小,并将接收到的数据和发送方的地址存储在传入的参数中。 通过以上的步骤,就可以在STM32CubeIDE中实现lwIP UDP通信。用户可以根据实际需求进行相关的配置和代码编写,以实现网络通信功能。需要注意的是,在使用lwIP协议栈时,需要了解其相关的API函数和使用方法,以确保正确实现所需功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值