基于最新版本stm32cubeIDE的lwip进行TCP、UDP组播通讯

本文介绍了基于STM32CubeIDE和LWIP库进行TCP/UDP组播通信的配置步骤。首先,详细说明了ETH配置,包括LAN8720A PHY芯片的reset脚操作和RMII接口设置。然后,讲解了如何在LWIP中配置平台和网络,如固定IP地址、开启UDP组播,并展示了如何加入组播组和解除MAC过滤。最后,提供了UDP接收RAW API的相关代码片段。
摘要由CSDN通过智能技术生成

基于stm32cubeIDE的lwip进行TCP、UDP组播通讯


一、ETH配置

采用LAN8720A的PHY芯片,原理图为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iea2Tmkw-1652691553020)(LAN8720A原理图.png)]
需注意reset脚
在初始化PHY芯片前,拉高拉低下reset脚

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_Delay(55);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(55);

该PHY芯片采用RMII接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w79kKbB3-1652691553022)(./PHY%E9%85%8D%E7%BD%AE.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBtxCjIU-1652691553023)(./PHY%E9%85%8D%E7%BD%AE1.png)]

二、配置LWIP

1、platform设置

因PHY芯片采用的是LAN8720A则,platform参数选择同系列的LAN8742
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5d2s2N04-1652691553023)(./lwip_platform%E8%AE%BE%E7%BD%AE.png)]

2、网络配置

  • 固定IP的话就配置DHCP disable

  • 并配置IP地址、子网掩码,网关地址
    在这里插入图片描述

  • 开启UDP组播
    首先勾选Key option里的show advantage parameters选项
    在这里插入图片描述
    在这里插入图片描述

    只有这两项开启,才能开启IGMP模式
    在这里插入图片描述

    RawAPI进行UDP组播通讯

err_t Medom_UDP_Midcast_init(void)
{
	err_t error;
	ip_addr_t ipgroup_rev,ipgroup_send;//组播地址

	IP4_ADDR(&ipgroup_rev, 239,255,255,1);//初始化组播收地址
	IP4_ADDR(&ipgroup_send, 239,255,255,1);//初始化组播发地址

	Modemudp=udp_new();//创建UDP连接
	if(Modemudp==NULL)
	{
		goto exit;
	}
	error=  igmp_joingroup(IP_ADDR_ANY,&ipgroup_rev);//加入组播
	if(error!=ERR_OK)
	{
		goto exit;
	}
	  error = udp_bind(Modemudp,IP_ADDR_ANY,ModemUdpPort);
	  if(error!=ERR_OK)
	  {
		  goto bind_error;
	  }
	  LogInfo("udp bind ok");
	  udp_recv(Modemudp,udp_server_rev,NULL);
	  LogInfo("udp ok");
	  return ERR_OK;
bind_error:
	igmp_leavegroup(IP_ADDR_ANY,&ipgroup_rev);
exit:
	udp_remove(Modemudp);
	return -1;
}

在初始化UDP前将组播地址加入组播组,调用 igmp_joingroup(IP_ADDR_ANY,&ipgroup_rev)

还有一个坑就是,stm32HAL MAC库默认是将组播地址给过滤掉的,所以要配置下MAC,关闭组播的MAC过滤,在low_level_init函数里添加以下代码:

netif->flags |=NETIF_FLAG_IGMP;

HAL_ETH_GetMACFilterConfig(&heth,&Mac_Fliter);
Mac_Fliter.PassAllMulticast=ENABLE;
HAL_ETH_SetMACFilterConfig(&heth,&Mac_Fliter);

具体的low_leve_init函数见下:

static void low_level_init(struct netif *netif)
{
  HAL_StatusTypeDef hal_eth_init_status = HAL_OK;
/* USER CODE BEGIN OS_THREAD_ATTR_CMSIS_RTOS_V2 */
  osThreadAttr_t attributes;
  ETH_MACFilterConfigTypeDef Mac_Fliter;
/* USER CODE END OS_THREAD_ATTR_CMSIS_RTOS_V2 */
  uint32_t duplex, speed = 0;
  int32_t PHYLinkState = 0;
  ETH_MACConfigTypeDef MACConf = {0};
  /* Start ETH HAL Init */

   uint8_t MACAddr[6] ;
  heth.Instance = ETH;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;
  heth.Init.MACAddr = &MACAddr[0];
  heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
  heth.Init.TxDesc = DMATxDscrTab;
  heth.Init.RxDesc = DMARxDscrTab;
  heth.Init.RxBuffLen = 1536;

  /* USER CODE BEGIN MACADDRESS */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
  HAL_Delay(55);
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
  HAL_Delay(55);
  /* USER CODE END MACADDRESS */

  hal_eth_init_status = HAL_ETH_Init(&heth);

  memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
  TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;

  /* End ETH HAL Init */

  /* Initialize the RX POOL */
  LWIP_MEMPOOL_INIT(RX_POOL);

#if LWIP_ARP || LWIP_ETHERNET

  /* set MAC hardware address length */
  netif->hwaddr_len = ETH_HWADDR_LEN;

  /* set MAC hardware address */
  netif->hwaddr[0] =  heth.Init.MACAddr[0];
  netif->hwaddr[1] =  heth.Init.MACAddr[1];
  netif->hwaddr[2] =  heth.Init.MACAddr[2];
  netif->hwaddr[3] =  heth.Init.MACAddr[3];
  netif->hwaddr[4] =  heth.Init.MACAddr[4];
  netif->hwaddr[5] =  heth.Init.MACAddr[5];

  /* maximum transfer unit */
  netif->mtu = ETH_MAX_PAYLOAD;

  /* Accept broadcast address and ARP traffic */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  #if LWIP_ARP
    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
  #else
    netif->flags |= NETIF_FLAG_BROADCAST;
  #endif /* LWIP_ARP */

  /* create a binary semaphore used for informing ethernetif of frame reception */
  RxPktSemaphore = osSemaphoreNew(1, 1, NULL);

  /* create a binary semaphore used for informing ethernetif of frame transmission */
  TxPktSemaphore = osSemaphoreNew(1, 1, NULL);

  /* create the task that handles the ETH_MAC */
/* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
  netif->flags |=NETIF_FLAG_IGMP;
  memset(&attributes, 0x0, sizeof(osThreadAttr_t));
  attributes.name = "EthIf";
  attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
  attributes.priority = osPriorityRealtime;
  osThreadNew(ethernetif_input, netif, &attributes);
/* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */

/* USER CODE BEGIN PHY_PRE_CONFIG */
  HAL_ETH_GetMACFilterConfig(&heth,&Mac_Fliter);
  Mac_Fliter.PassAllMulticast=ENABLE;
  HAL_ETH_SetMACFilterConfig(&heth,&Mac_Fliter);
/* USER CODE END PHY_PRE_CONFIG */
  /* Set PHY IO functions */
  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  LAN8742_Init(&LAN8742);

  if (hal_eth_init_status == HAL_OK)
  {
    PHYLinkState = LAN8742_GetLinkState(&LAN8742);

    /* Get link state */
    if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN)
    {
      netif_set_link_down(netif);
      netif_set_down(netif);
    }
    else
    {
      switch (PHYLinkState)
      {
      case LAN8742_STATUS_100MBITS_FULLDUPLEX:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      case LAN8742_STATUS_100MBITS_HALFDUPLEX:
        duplex = ETH_HALFDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      case LAN8742_STATUS_10MBITS_FULLDUPLEX:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_10M;
        break;
      case LAN8742_STATUS_10MBITS_HALFDUPLEX:
        duplex = ETH_HALFDUPLEX_MODE;
        speed = ETH_SPEED_10M;
        break;
      default:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      }

    /* Get MAC Config MAC */
    HAL_ETH_GetMACConfig(&heth, &MACConf);
    MACConf.DuplexMode = duplex;
    MACConf.Speed = speed;
    HAL_ETH_SetMACConfig(&heth, &MACConf);

    HAL_ETH_Start_IT(&heth);
    netif_set_up(netif);
    netif_set_link_up(netif);

/* USER CODE BEGIN PHY_POST_CONFIG */

/* USER CODE END PHY_POST_CONFIG */
    }

  }
  else
  {
    Error_Handler();
  }
#endif /* LWIP_ARP || LWIP_ETHERNET */

/* USER CODE BEGIN LOW_LEVEL_INIT */

/* USER CODE END LOW_LEVEL_INIT */
}

这样就解除了MAC的过滤

再完善下UDP的接收RAW API接收函数就可以了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值