最近在做一个基于stm32f107 实现 UDP 组播通信的项目,项目基于 stm32cube 配置生成,如下图:

UDP组播头文件:

#ifndef __MULTICAST_H__
#define __MULTICAST_H__#include "lwip/udp.h"
#include "lwip/pbuf.h"
#include "lwip/igmp.h"
#include "User.h"/*port */
#define UDP_MULTICASE_RECV_PORT 8642    // multicast port for recive
#define UDP_MULTICASE_SEND_PORT 8642    // multicast port for send
#define  MULTUDP_BUF_SIZE     2048extern struct udp_pcb* udp_server_multi_pcb;             //组播PCB控制块
extern ip4_addr_t ipgroup_rev,ipgroup_send;void multicast_send_data(unsigned char * data,unsigned short len);
void udp_server_rev(void *arg, struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *addr, u16_t port);
void Multicast_Config( void );
void MulticastUDP_SendTest(void);#endif /* __MULTICAST_H__ */

UDP组播C文件:

/********************************************************************************* @file    udp_echoserver.c* @author  MCD Application Team* @version V1.1.0* @date    31-July-2013* @brief   UDP echo server******************************************************************************* @attention** <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>** Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");* You may not use this file except in compliance with the License.* You may obtain a copy of the License at:**        http://www.st.com/software_license_agreement_liberty_v2** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.********************************************************************************//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip.h"
#include <string.h>
#include <stdio.h>
#include "multicast.h"
#include "User.h"#define PRINT(...)/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
struct udp_pcb* udp_server_multi_pcb;             // 组播PCB控制块
ip4_addr_t ipgroup_rev,ipgroup_send;// UDP发送
void multicast_send_data(unsigned char * data,unsigned short len)
{struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);memcpy(p->payload, data, len);udp_sendto(udp_server_multi_pcb, p,&ipgroup_send,UDP_MULTICASE_SEND_PORT);pbuf_free(p);}// 组播接收,回调函数
void udp_server_rev(void *arg, struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *addr, u16_t port)
{
#if 1ProtoFrame_t UdpRxTemp;if( p != NULL ){if( p->tot_len >= sizeof(ProtoFrame_t)  )memcpy( (void *)&UdpRxTemp, p->payload, sizeof(ProtoFrame_t) );else memcpy( (void *)&UdpRxTemp,p ->payload,p->tot_len );// 校验数据是否符合协议if( (FrameCheck(&UdpRxTemp) == 1) || (FrameCheck(&UdpRxTemp) == 2) ){UdpRxCmd[UdpRxCmdWrite] = UdpRxTemp;UdpRxCmdWrite = (UdpRxCmdWrite+1)%MAX_CMD_BUFF;}if( FrameCheck(&UdpRxTemp) > 1 )  // 转发数据到 485{TxCmd[TxCmdWrite] = UdpRxTemp;TxCmdWrite = (TxCmdWrite+1)%MAX_CMD_BUFF;}/* Free the p buffer */pbuf_free(p);}#else// 回显功能/* Connect to the remote client */udp_connect(pcb, addr, UDP_MULTICASE_SEND_PORT);/* Tell the client that we have accepted it *///udp_send(pcb, p);udp_sendto(pcb, p,&ipgroup_send,UDP_MULTICASE_SEND_PORT);/* free the UDP connection, so we can accept new clients */udp_disconnect(pcb);/* Free the p buffer */pbuf_free(p);#endif
}void Multicast_Config( void )
{err_t err;IP4_ADDR(&ipgroup_rev, 224,0,0,100);                                                     // 用于接收组播的地址IP4_ADDR(&ipgroup_send, 224,0,0,100);                                                   // 用于发送组播的地址
#if LWIP_IGMPigmp_joingroup(IP_ADDR_ANY,&ipgroup_rev);   // 只需要将接收地址放入igmp组,发送的不需要
#endifudp_server_multi_pcb = udp_new();if ( udp_server_multi_pcb ){/* Bind the upcb to the UDP_PORT port *//* Using IP_ADDR_ANY allow the upcb to be used by any local interface */err = udp_bind(udp_server_multi_pcb,IP_ADDR_ANY,UDP_MULTICASE_RECV_PORT);if(err == ERR_OK){/* Set a receive callback for the upcb */udp_recv(udp_server_multi_pcb,udp_server_rev,NULL);}else{udp_remove(udp_server_multi_pcb);PRINT("can not bind pcb");}}else{PRINT("can not create pcb");}}// 测试发送的方法
void MulticastUDP_SendTest(void)
{multicast_send_data("igmp test\r\n",11 );
}/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

注意,我在做好上面的代码后发现,能实现UDP发送,但收到不信号,经过多方查找发现是因为网络接口配置有些问题,

找到stm32f1xx_hal_eth.c文件中的 ETH_MACDMAConfig 函数 ,如下图,将代码改成:

/*** @brief  Configures Ethernet MAC and DMA with default parameters.* @param  heth: pointer to a ETH_HandleTypeDef structure that contains*         the configuration information for ETHERNET module* @param  err: Ethernet Init error* @retval HAL status*/
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
{ETH_MACInitTypeDef macinit;ETH_DMAInitTypeDef dmainit;uint32_t tmpreg1 = 0U;if (err != ETH_SUCCESS) /* Auto-negotiation failed */{/* Set Ethernet duplex mode to Full-duplex */(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;/* Set Ethernet speed to 100M */(heth->Init).Speed = ETH_SPEED_100M;}/* Ethernet MAC default initialization **************************************/macinit.Watchdog = ETH_WATCHDOG_ENABLE;macinit.Jabber = ETH_JABBER_ENABLE;macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE){macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;}else{macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;}macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; // ETH_RECEIVEALL_ENABLE; // macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;  // ETH_MULTICASTFRAMESFILTER_PERFECT;macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;macinit.HashTableHigh = 0x0U;macinit.HashTableLow = 0x0U;macinit.PauseTime = 0x0U;macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;macinit.VLANTagIdentifier = 0x0U;/*------------------------ ETHERNET MACCR Configuration --------------------*//* Get the ETHERNET MACCR value */tmpreg1 = (heth->Instance)->MACCR;/* Clear WD, PCE, PS, TE and RE bits */tmpreg1 &= ETH_MACCR_CLEAR_MASK;/* Set the WD bit according to ETH Watchdog value *//* Set the JD: bit according to ETH Jabber value *//* Set the IFG bit according to ETH InterFrameGap value *//* Set the DCRS bit according to ETH CarrierSense value *//* Set the FES bit according to ETH Speed value *//* Set the DO bit according to ETH ReceiveOwn value *//* Set the LM bit according to ETH LoopbackMode value *//* Set the DM bit according to ETH Mode value *//* Set the IPCO bit according to ETH ChecksumOffload value *//* Set the DR bit according to ETH RetryTransmission value *//* Set the ACS bit according to ETH AutomaticPadCRCStrip value *//* Set the BL bit according to ETH BackOffLimit value *//* Set the DC bit according to ETH DeferralCheck value */tmpreg1 |= (uint32_t)(macinit.Watchdog |macinit.Jabber |macinit.InterFrameGap |macinit.CarrierSense |(heth->Init).Speed |macinit.ReceiveOwn |macinit.LoopbackMode |(heth->Init).DuplexMode |macinit.ChecksumOffload |macinit.RetryTransmission |macinit.AutomaticPadCRCStrip |macinit.BackOffLimit |macinit.DeferralCheck);/* Write to ETHERNET MACCR */(heth->Instance)->MACCR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACCR = tmpreg1;/*----------------------- ETHERNET MACFFR Configuration --------------------*//* Set the RA bit according to ETH ReceiveAll value *//* Set the SAF and SAIF bits according to ETH SourceAddrFilter value *//* Set the PCF bit according to ETH PassControlFrames value *//* Set the DBF bit according to ETH BroadcastFramesReception value *//* Set the DAIF bit according to ETH DestinationAddrFilter value *//* Set the PR bit according to ETH PromiscuousMode value *//* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value *//* Set the HUC and HPF bits according to ETH UnicastFramesFilter value *//* Write to ETHERNET MACFFR */(heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |macinit.SourceAddrFilter |macinit.PassControlFrames |macinit.BroadcastFramesReception |macinit.DestinationAddrFilter |macinit.PromiscuousMode |macinit.MulticastFramesFilter |macinit.UnicastFramesFilter);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACFFR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFFR = tmpreg1;/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*//* Write to ETHERNET MACHTHR */(heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;/* Write to ETHERNET MACHTLR */(heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;/*----------------------- ETHERNET MACFCR Configuration -------------------*//* Get the ETHERNET MACFCR value */tmpreg1 = (heth->Instance)->MACFCR;/* Clear xx bits */tmpreg1 &= ETH_MACFCR_CLEAR_MASK;/* Set the PT bit according to ETH PauseTime value *//* Set the DZPQ bit according to ETH ZeroQuantaPause value *//* Set the PLT bit according to ETH PauseLowThreshold value *//* Set the UP bit according to ETH UnicastPauseFrameDetect value *//* Set the RFE bit according to ETH ReceiveFlowControl value *//* Set the TFE bit according to ETH TransmitFlowControl value */tmpreg1 |= (uint32_t)((macinit.PauseTime << 16U) |macinit.ZeroQuantaPause |macinit.PauseLowThreshold |macinit.UnicastPauseFrameDetect |macinit.ReceiveFlowControl |macinit.TransmitFlowControl);/* Write to ETHERNET MACFCR */(heth->Instance)->MACFCR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACFCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFCR = tmpreg1;/*----------------------- ETHERNET MACVLANTR Configuration ----------------*//* Set the ETV bit according to ETH VLANTagComparison value *//* Set the VL bit according to ETH VLANTagIdentifier value */(heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |macinit.VLANTagIdentifier);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACVLANTR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACVLANTR = tmpreg1;/* Ethernet DMA default initialization ************************************/dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;dmainit.DescriptorSkipLength = 0x0U;dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;/* Get the ETHERNET DMAOMR value */tmpreg1 = (heth->Instance)->DMAOMR;/* Clear xx bits */tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value *//* Set the RSF bit according to ETH ReceiveStoreForward value *//* Set the DFF bit according to ETH FlushReceivedFrame value *//* Set the TSF bit according to ETH TransmitStoreForward value *//* Set the TTC bit according to ETH TransmitThresholdControl value *//* Set the FEF bit according to ETH ForwardErrorFrames value *//* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value *//* Set the RTC bit according to ETH ReceiveThresholdControl value *//* Set the OSF bit according to ETH SecondFrameOperate value */tmpreg1 |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |dmainit.ReceiveStoreForward |dmainit.FlushReceivedFrame |dmainit.TransmitStoreForward |dmainit.TransmitThresholdControl |dmainit.ForwardErrorFrames |dmainit.ForwardUndersizedGoodFrames |dmainit.ReceiveThresholdControl |dmainit.SecondFrameOperate);/* Write to ETHERNET DMAOMR */(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->DMAOMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMAOMR = tmpreg1;/*----------------------- ETHERNET DMABMR Configuration ------------------*//* Set the AAL bit according to ETH AddressAlignedBeats value *//* Set the FB bit according to ETH FixedBurst value *//* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value *//* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value *//* Set the DSL bit according to ETH DesciptorSkipLength value *//* Set the PR and DA bits according to ETH DMAArbitration value */(heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |dmainit.FixedBurst |dmainit.RxDMABurstLength |    /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */dmainit.TxDMABurstLength |(dmainit.DescriptorSkipLength << 2U) |dmainit.DMAArbitration |ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx *//* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->DMABMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMABMR = tmpreg1;if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE){/* Enable the Ethernet Rx Interrupt */__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);}/* Initialize MAC address in ethernet MAC */ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
}

这样就可以正常收到组播端口发来的数据了!!

而且实际发现,在我改了st32f1xx_hal_eth.c 中函数 后, LWIP_IGMP 宏即使为 0 也可以实现组播通信!!

代码量比开启 LWIP_IGMP 宏少了 2K 左右。但是就是所有的组播地址中的数据都会被收到,如果要针对某一地址进行组播通信, LWIP_IGMP 宏还是要设为1才行。

基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信相关推荐

  1. Qt网络编程-简易版UDP组播通信入门Demo(5)

    Qt网络编程-简易版UDP组播通信入门Demo(5)

  2. STM32CubeMx + LWIP(实现UDP组播/MQTT/热插拔)系列 二 ----- CubeMx生成文件的简单介绍与热插拔

    CubeMx生成的文件主要是两个文件,lwipopts.h和ethnetif.c. lwipopts.h主要是对于lwip中一些宏的定义的选择.该文件include在lwip的opt.h文件前面.因此 ...

  3. STM32CubeMx + LWIP(实现UDP组播/MQTT/热插拔)系列 四 ----- MQTT的连接与使用

    mqtt的全局变量 mqtt_client_t *lwip_mqtt; mqtt的连接,不要直接复制粘贴哦,记得把参数设置成你项目中用到的数据 char LWIP_Connect(mqtt_clien ...

  4. 虚拟机无法接受组播消息_基于UDP的组播通信

    基于UDP的组播通信 在Java实现基于UDP协议的发送端与接收端通信中,我们可以知道它的一些主要操作: 在发送端:1,创建绑定指定端口的发送接口:DatagramSocket(port) 2,创建绑 ...

  5. UDP通讯协议广播和组播实现

    UDP 通讯协议广播 UDP广播发送端 #include "myhead.h" int main(int argc,char **argv) {     int udpsock; ...

  6. 如何利用UDP组播实现海康网络摄像机(IPC)的自动探测【源码】【监控】【录播】【NVR】【ONVIF】

    前言: 监控项目中,经常会遇到管理大量网络摄像机IPC的情况,如果每个IPC都要手动输入IP和端口,是非常繁琐的事情,于是,出现了与设备无关的ONVIF协议.海康提供的SADPTool就是基于ONVI ...

  7. UDP 组播---你需要了解这些

    先来了解下UDP UDP 是UserDatagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一 ...

  8. UDP 组播---基本概念

     本文章已收录于: 先来了解下UDP UDP 是UserDatagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式 ...

  9. 【网络工具】使用 iperf测试 udp组播

    文章目录 下载iperf程序 测试组播协议 pc1 客户端发送组播包 pc2 服务端接收组播包 参数说明 -B, --bind host 服务端专用参数 -T, --ttl 客户端专用参数 下载ipe ...

最新文章

  1. excel模糊匹配两列文字_高效便捷的Word、Excel操作技巧
  2. ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务
  3. Oracle 10G select工作原理
  4. CentOS7.2.1511 安装Mysql-5.7.13
  5. 三、如何手动实现一个微前端框架雏形
  6. Android之日期时间选择器使用方法
  7. 2048源码 linux,分享|2 的威力,Linux 的威力:终端中的 2048
  8. 再见,我的程序青葱岁月!
  9. 原因及解决办法:Failed to load module “canberra-gtk-module“
  10. 直接选择排序(含图解)
  11. metabase开源BI
  12. 嘀嘀的费用是优步的两倍?
  13. 抖音中用小程序自动制作人物关系图
  14. fatal error C1859的有效解决办法
  15. HDU6441(费马大定理)
  16. 最新的基于mvc毕业设计题目50例
  17. Java的图书商城项目如何添加商品到购物车
  18. spring--ApplicationContextAware
  19. 很好的源码软件列表,有助于学习提高
  20. iperf3 测试100G网卡带宽性能

热门文章

  1. .NET Core Community 第二个千星项目诞生:Util
  2. c语言long long类型赋值
  3. 让我们一起Go(十三)
  4. 关于图片按比例自适应缩放
  5. Linux echo命令和查看环境变量实例
  6. Win32 多线程学习总结
  7. wireshark过滤规则学习总结
  8. 很多优秀的软件公司和开发者为什么愿意开源和共享?
  9. .net EF监控 MiniProfiler
  10. asp.net mvc5 分析器错误消息: 未能加载类型“XXX.MvcApplication”