STM32F4板子使用LWIP进行组播收发数据的完整过程,附代码

 
开发环境:
硬件板卡: STM32F427ZITx
网卡:DP83848

LWIP版本:V3.2

最近要使用LWIP协议实现组播,由于此前并不知道这个板卡,对嵌入式也不算熟悉,平时还有其他的任务,前前后后忙了近两个月,后来发现实现过程非常简单,下面介绍我的实现过程。

首先,使用STM32F4时不用完全自己搭建环境的,到官网下载类似于stsw-stm32070.zip的文件包,里面包含了多个典型的Keil uVision工程,配置一下就能用。这个过程改天再写个文档。
在Kei工程中配置组播的过程可以分为三步:配置LWIP,启动组播;编写组播实现代码;调用。

Step1.首先配置LWIP,启动组播功能

修改lwipopts.h 文
#define LWIP_IGMP                       1
在lwip初始化后调用
2.配置组播计时器
在 netconf.c文件靠前的位置添加变量,大约在该文件的第70行左右,代码如下所示。
 
#ifdef LWIP_IGMP
uint32_t  IGMPTimer=0;
#endif

然后在该文件的#ifdef USE_DHCP前面,大约在第180行的位置添加igmp计时器调用代码:
 #if LWIP_IGMP
if(localtime-IGMPTimer>=IGMP_TMR_INTERVAL)
  {
IGMPTimer=localtime;
    igmp_tmr();
  }
 #endif
编译,如果能正确编译,并且在编译过程中看到编译igmp.c文件,说明配置基本成功了。

Step2:编写组播实现代码

添加两个文件,multicast.h和multicast.c文件。废话少说,先上代码:

multicast.h文件的代码为:

#ifndef __MULTICAST__H
#define __MULTICAST__H

#include "stm324xg_eval_sdio_sd.h"
 
#include "lwip/udp.h"
#include "lwip/pbuf.h"
#include "lwip/igmp.h"

/*port */
#define UDP_MULTICASE_RECV_PORT 1178    // multicast port for recive
#define UDP_MULTICASE_SEND_PORT 1180   // multicast port for send

#define  LWIP_DEMO_BUF     2048

#endif

其中  UDP_MULTICASE_RECV_PORT 1178   是板子接收组播的端口, UDP_MULTICASE_SEND_PORT 1180  是 板子对外发送组播的端口

multicast.c的代码为:

#include "multicast.h"

struct udp_pcb* udp_server_multi_pcb;//组播PCB控制块
struct ip_addr ipgroup_rev,ipgroup_send;

u16 lwip_demo_buf_len = 0;
u8_t lwip_demo_buf[LWIP_DEMO_BUF];

//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,(struct ip_addr *) (&ipgroup_send),UDP_MULTICASE_SEND_PORT);//1180
		
		pbuf_free(p);
	 
}

//组播接收,回调函数
void udp_server_rev(void* arg,struct udp_pcb* upcb,struct pbuf* p,struct ip_addr*addr ,u16_t port){

	int i,j;
	
	if(p!=NULL){
		if((p->tot_len)>=LWIP_DEMO_BUF){         //如果长度过长则额外处理        
			memcpy(lwip_demo_buf,p->payload,LWIP_DEMO_BUF);
			lwip_demo_buf_len = LWIP_DEMO_BUF;
		}else{				
			memcpy(lwip_demo_buf,p->payload,p->tot_len);
			lwip_demo_buf_len = p->tot_len;
		}
  	
	 for(i=0;i<p->tot_len;i++)//测试组播时,有时候即使没发出去也可能显示收到,因此,我这里将收到的数据加2,以作区分
		{
			printf("%02x  ",lwip_demo_buf[i]);
		  lwip_demo_buf[i]=lwip_demo_buf[i]+2;
		}

		printf("\n"); 

	} 
}
 
void Multicast_Config()	
{
		int i; 
   	IP4_ADDR(&ipgroup_rev, 230,1,1,11);//用于接收组播的地址
    IP4_ADDR(&ipgroup_send, 230,12,2,22);//用于发送组播的地址
	
    igmp_joingroup(IP_ADDR_ANY,(struct ip_addr *)(&ipgroup_rev));//只需要将接收地址放入igmp组,发送的不需要
	
	  udp_server_multi_pcb = udp_new();	
	
	if(udp_server_multi_pcb!=NULL){
				
		udp_bind(udp_server_multi_pcb,IP_ADDR_ANY,UDP_MULTICASE_RECV_PORT);//组播接收地址1178
		
		udp_recv(udp_server_multi_pcb,udp_server_rev,NULL);//
 
	}

}
//测试发送的方法 
void UDP_Send()
{ 
 	   multicast_send_data(lwip_demo_buf,lwip_demo_buf_len);
}

Step3:调用

  在主函数main.c下添加#include "multicast.h"引用
并在main()函数中的while循环的前面添加组播配置方法
Multicast_Config();
添加成功后板子就能接收组播了。
如果想测试发送,则直接调用UDP_Send()方法即可。我为了进行长时间测试,直接在stm32f4xx_it.c文件的TIM2_IRQHandler中添加了调用,这样可以使得板子每隔一秒就发送一次。该函数的代码为:
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
				if(flash==1)
				{
					STM_EVAL_LEDOff(LED1);
					flash=0;
				}
				else
				{
					STM_EVAL_LEDOn(LED1);
					flash=1;
				}
    UDP_Send();
    }


}

解释

接收的持续监听是如何进行

上述代码有两点让人不太明确,也是起初一直让我迷糊的地方:1组播到底是如何接收的?2如何实现收发同步。
在《LwIP协议深度剖析与实战演练》一书的16.3给了一个组播的例子。代码如下。如果了解高级编程语言,这个例子非常易懂,但是其前提是必须配置好一个操作系统,目前常用的是FreeOST和uosII,但是在板子上配置这个系统要做很多工作,我曾花了近半个月来配置,后来发现根本不需要这么做。
void lwip_demo(void *pdata)
{
 struct netconn *conn;
 struct ip_addr local_addr,group_addr,remote_addr;

 lwip_init_task();
 EnableMacInt();
 
 IP4_ADDR(&local_addr,192,168,1,37);
 IP4_ADDR(&group_addr,233,0,0,6);
 IP4_ADDR(&remote_addr,192,168,1,78);
 
 conn=netconn_new(NETCONN_UDP);

 netconn_bind(conn,NULL,9090);
 netconn_join_leave_group(conn,&group_addr,&local_addr,NETCONN_JOIN);
 
 while(1)
  {
	 struct netbuf *inbuf;
	 inbuf = netconn_recv(conn);
	 if(inbuf!=NULL)
	 {
       netconn_sendto(conn,inbuf,&remote_addr,8080);
       netbuf_delete(inbuf);
     }
  }
  netconn_delete(conn);
}
在无操作系统的环境下使用组播的关键在于前面我们提到的 添加 igmp_tmr()的调用,它能保证板子可以在一定的周期内监听网络上发来的组播流。如果你对嵌入式编程很熟悉,这一点不难理解,如果像我一样习惯了高级编程语言的风格,会一直想不明白。

 如何实现收发同步进行

上面解决了接收的问题,那如何发送呢?并且如何保证收发能同步进行呢?其实发送更为简单,只要你配置好UDP环境,将单播地址换成组播地址就能发送,这里的关键在于Multicast_Config()中的配置。

开始我一直在想是否需要写两个配置函数,一个同事坚持认为应该建立两个pcb,一个用于收,一个用于发,但是测试发现根本不需要,只要为pcb添加两个组播地址就行了
IP4_ADDR(&ipgroup_rev, 230,1,1,11);用来配置接收组播的地址,为了能收到数据,还需要将其添加到igmp_joingroup组中。然后将其与udp_server_multi_pcb绑定,最后在回调函数中执行。这几个函数包涵了大量的底层操作,感兴趣的话可以看看LWIP的源代码。
IP4_ADDR(&ipgroup_send, 230,12,2,22)用来配置发送组播的地址,multicast_send_data()用来发送,具体请参考代码。

测试

我的测试如下图所示:左侧是我发送数据,右侧为接收,我的设置是接收一次后每隔一秒发送一次,因此可以看到大量的接收信息。

 完善

上述代码还有一些不足的,一个是一次不能收发比较大的数据,测试发现,一次收发1KB的字节都不行,这个我调试完成后再补充。另一个是缺少业务控制逻辑,其实这个已经很简单了,只要添加一个bool变量,接收到新数据是置为1,发送了之后置为0即可灵活地控制数据收发,进而封装到你的业务逻辑中。

感谢

虽然STM32用的比较多,LWIP也用的比较多,但是如何实现组播,网络的材料比较杂乱,含金量实在很低,梳理出上面的内容花了我很长的时间。不过,在此特别感谢lutao614http://bbs.csdn.net/topics/391894501,我曾两次和他交流,他为了明确方向给了很大的帮助,并且无私地将自己的代码给我看,特此表示感谢。

  • 16
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
### 回答1: STM32F4x7是意法半导体(STMicroelectronics)推出的一款高性能的微控制器。它采用ARM Cortex-M4内核,具有丰富的外设和强大的性能。FreeRTOS是一种基于实时操作系统(RTOS)的开源操作系统,它提供了一种用于开发嵌入式系统的程序框架。LWIP(Lightweight IP)是一个轻量级的TCP/IP协议栈,在嵌入式设备上提供了网络通信的功能。SSL(Secure Sockets Layer)是一种安全通信协议,用于对网络通信进行加密和身份验证。MQTT(Message Queuing Telemetry Transport)是一种用于物联网设备之间进行通信的轻量级消息协议。 在STM32F4x7上使用FreeRTOS和LWIP可以实现网络通信的功能:可以通过LWIP库来实现TCP/IP协议栈的功能,实现设备与设备之间的网络连接和通信。同时,通过FreeRTOS可以实现实时任务调度和多线程处理,提高系统的并发性能。 而在使用网络通信时,SSL协议的加密通信功能可以保证通信的安全性和数据完整性。通过为LWIP和MQTT添加SSL支持,可以在基于STM32F4x7的嵌入式系统中实现加密和安全的网络通信。 MQTT协议是一种轻量级的通信协议,适用于物联网场景。它具有低开销、可靠性高的特点,可以实现设备之间的即时通信。通过在STM32F4x7上集成MQTT库,可以实现与其他设备的MQTT通信,实现数据输入和输出的功能。 综上所述,利用STM32F4x7的强大性能和外设,加上FreeRTOS、LWIP、SSL和MQTT等库的支持,可以在嵌入式系统中实现高效、安全且可靠的网络通信功能。这对于物联网设备和其他嵌入式系统应用来说是非常有价值的。 ### 回答2: STM32F4x7是一款高性能的32位微控制器系列,配备了丰富的外设和强大的处理能力。它可以通过内置的操作系统FreeRTOS来实现多任务管理,并且可以使用LwIP协议栈来实现网络通信。同时,STM32F4x7还支持SSL(Secure Sockets Layer)和MQTT(Message Queuing Telemetry Transport)协议。 首先,FreeRTOS是一种实时操作系统,可以在STM32F4x7上实现多任务管理和调度。它提供了任务创建、删除、挂起和恢复等功能,使得开发者可以轻松实现多个任务的同时运行。在使用FreeRTOS时,我们首先需要配置和初始化任务、信号量和消息队列等资源,然后使用任务调度器来管理任务的执行。 其次,LwIP是一个在STM32F4x7上常用的TCP/IP协议栈,它能够提供IP网络连接、TCP和UDP数据传输等功能。使用LwIP,我们可以轻松实现网络通信,连接互联网或者局域网。通过LwIP的API接口,我们可以实现对网络数据发送接收,以及对网络连接的管理。 另外,SSL是一种用于加密和认证网络通信的协议,可以提供数据的机密性和完整性。在STM32F4x7上,我们可以使用SSL来进行安全的网络通信,保护敏感数据的传输。通过配置SSL证书和密钥等参数,我们可以使用SSL协议来对数据进行加密和解密。 最后,MQTT是一种轻量级的消息传输协议,常用于物联网应用中的设备间通信。在STM32F4x7上,我们可以使用MQTT来实现设备与云端的通信。通过配置MQTT客户端和服务器的参数,我们可以订阅和发布消息,实现设备和云端之间的数据传输和通信。 综上所述,STM32F4x7结合FreeRTOS、LwIP、SSL和MQTT等技术,可以实现高效的多任务管理、网络通信和安全数据传输,非常适用于物联网等应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵横千里,捭阖四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值