开发环境介绍:
MCU:STM32F407ZET6
网卡:LAN8720A
LWIP版本:V1.1.0
FreeRTOS 版本:V10.2.1
LAN8720A硬件原理图:
硬件连接说明:
MII_RX_CLK/RMII_REF_CLK ------>PA1 MII_TXD0 ------>PB12MII_MDIO ------>PA2 MII_TXD1 ------>PB13MII_RESET ------>PA3 MII_MDC ------>PC1MII_RX_DV/RMII_CRSDV ------>PA7 MII_RXD0 ------>PC4MII_RX_ER ------>PB10 MII_RXD1 ------>PC5MII_TX_EN ------>PB11
Lwip组播配置:
上图中创建了一个10ms的循环定时器,定时器回调函数为: LwipTimCallBack
void LwipTimCallBack(TimerHandle_t xTimer)
{
uint32_t LocaTime = xTaskGetTickCount();
LwIP_Periodic_Handle(LocaTime);
}
netconf.c--->void LwIP_Periodic_Handle(volatile uint32_t localtime)内添加igmp计时器调用算法
ethernetif.c--->static void low_level_init(struct netif *netif)添加
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
在stm32f429_phy.c---->static void ETH_MACDMA_Config(void)方法中进行以下设置:
组播接收消息设置:
接收消息使用的是8081端口,发送消息使用的是8080端口。组播地址239.0.0.1。客户端设置可参考另一篇文章:QT学习笔记_UDP组播通信(加入组播)_qt 实现udp通信工程文件添加什么-CSDN博客
static void MulticastRxTask(void *pcParameter)
{
uint32_t NotifyValue = 0;
UBaseType_t uxHighWaterMark;
struct netconn *udpconn;
udpconn = netconn_new(NETCONN_UDP);
ip_addr_t destipaddr;
IP4_ADDR(&destipaddr,239,0,0,1);
netconn_bind(udpconn,IP_ADDR_ANY,8081);
netconn_join_leave_group(udpconn,&destipaddr,IP_ADDR_ANY,NETCONN_JOIN);
uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
while(1)
{
struct netbuf *recebuf;
if(netconn_recv(udpconn,&recebuf) == ERR_OK)//会自己阻塞
{
uint16_t ReceByteCount = recebuf->p->len;
uint8_t *pData = recebuf->p->payload;
if((pData[0] == 0xAA &&pData[1] == 0xBB))memcpy((void *)MulticastBuf,(void *)pData,ReceByteCount);
netbuf_delete(recebuf);
}
uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
}
}
组播发送消息:
void MulticastTxTask(void *pvParameter)
{
struct netconn *udpconn;
udpconn = netconn_new(NETCONN_UDP);
netconn_bind(udpconn, IP_ADDR_ANY, 8080);
ip_addr_t ipMultiCast;
IP4_ADDR(&ipMultiCast, 239, 0, 0, 1);
netconn_connect(udpconn,&ipMultiCast,8080);
for(;;)
{
uint32_t NotifyValue = 0;
struct netbuf *sendbuf = netbuf_new();
xTaskNotifyWait(ULONG_MAX,ULONG_MAX,&NotifyValue,portMAX_DELAY);
switch(NotifyValue)
{//组桢
MulticastRxStruct.ReceLen =MakeUpInfoBack(0x3031,MulticastRxStruct.Data);break;
default:break;
}
netbuf_alloc(sendbuf,MulticastRxStruct.ReceLen);
netbuf_ref(sendbuf,MulticastRxStruct.Data,MulticastRxStruct.ReceLen);//发送指定长度字符串
netconn_send(udpconn,sendbuf);//发送报文
netbuf_delete(sendbuf);
}
}