STM32 LWIP UDP 一对一 一对多发送

这篇具有很好参考价值的文章主要介绍了STM32 LWIP UDP 一对一 一对多发送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

之前没有接触过网络的通信,工作需要 UDP 接收和发送通信,在网上没有找到一对一、一对多的相关例程;于是在技术总监对我的指导,用正点原子板子给的例程是从官方的程序修改的,实现了Lwip UDP通信一对一、一对多的发送程序,可以随便指定发送ip地址、发送端口号,以及发送十六进制或是 ASCII码都可以,本人测试STM32F1系列和F4系列都没问题,十分的方便。

设置 IP 地址

  1. 假设设置STM32单片机IP为:192.168.1.130
	lwipx->ip[0]=192;	
	lwipx->ip[1]=168;
	lwipx->ip[2]=1;
	lwipx->ip[3]=130;
  1. 假设设置我的电脑的IP为:192.168.1.36

STM32 LWIP UDP 一对一 一对多发送,STM32,stm32,udp,嵌入式硬件,LWIP

UDP函数配置

  1. STM32单片机上电不需要每次手动按键调节设置远端IP地址(ip地址、端口号)
//	udp_demo_set_remoteip();//先选择IP
	LCD_Clear(WHITE);	//清屏
	POINT_COLOR=RED; 	//红色字体
	LCD_ShowString(30,30,200,16,16,"WARSHIP STM32F103");
	LCD_ShowString(30,50,200,16,16,"UDP Test");
	LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");  
	LCD_ShowString(30,90,200,16,16,"KEY0:Send data");  
	LCD_ShowString(30,110,200,16,16,"KEY_UP:Quit"); 
	LCD_ShowString(30,130,200,16,16,"KEY1:Connect");
	tbuf=mymalloc(SRAMIN,200);	//申请内存
	if(tbuf==NULL)return ;		//内存申请失败了,直接退出
	sprintf((char*)tbuf,"Local IP:%d.%d.%d.%d",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);//服务器IP
	LCD_ShowString(30,150,210,16,16,tbuf);
	sprintf((char*)tbuf,"Local Port:%d",UDP_DEMO_PORT);//服务器端口号
	LCD_ShowString(30,170,210,16,16,tbuf);
//	sprintf((char*)tbuf,"Remote IP:%d.%d.%d.%d",lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3]);//远端IP
//	LCD_ShowString(30,170,210,16,16,tbuf);  
//	sprintf((char*)tbuf,"Remote Port:%d",UDP_DEMO_PORT);//客户端端口号
//	LCD_ShowString(30,190,210,16,16,tbuf);
	POINT_COLOR=BLUE;
	LCD_ShowString(30,210,210,16,16,"STATUS:Disconnected"); 
  1. UDP客户端连接不需要指定IP地址和端口号的服务器
	udppcb=udp_new();
	if(udppcb)//创建成功
	{ 
		IP4_ADDR(&rmtipaddr,lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3]);
		err=udp_bind(udppcb,IP_ADDR_ANY,UDP_DEMO_PORT);//绑定本地IP地址与端口号
		if(err==ERR_OK)	//绑定完成
		{
			udp_recv(udppcb,udp_demo_recv,NULL);//注册接收回调函数 
			LCD_ShowString(30,210,210,16,16,"STATUS:Connected   ");//标记连接上了(UDP是非可靠连接,这里仅仅表示本地UDP已经准备好)
			udp_demo_flag |= 1<<5;			//标记已经连接上
			POINT_COLOR=RED;
			LCD_ShowString(30,230,lcddev.width-30,lcddev.height-190,16,"Receive Data:");//提示消息		
			POINT_COLOR=BLUE;//蓝色字体
		}else res=1;	
	}else res=1;
  1. UDP回调函数
void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)
{
	u32 data_len = 0;
	struct pbuf *q;
	if(p!=NULL)	//接收到不为空的数据时
	{
		memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零
		for(q=p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
		{
			//判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于
			//的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
			if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)) memcpy(udp_demo_recvbuf+data_len,q->payload,(UDP_DEMO_RX_BUFSIZE-data_len));//拷贝数据
			else memcpy(udp_demo_recvbuf+data_len,q->payload,q->len);
			data_len += q->len;  	
			if(data_len > UDP_DEMO_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出	
		}
		upcb->remote_ip=*addr; 				//记录远程主机的IP地址
		upcb->remote_port=port;  			//记录远程主机的端口号
		lwipdev.remoteip[0]=upcb->remote_ip.addr&0xff; 		//IADDR4
		lwipdev.remoteip[1]=(upcb->remote_ip.addr>>8)&0xff; //IADDR3
		lwipdev.remoteip[2]=(upcb->remote_ip.addr>>16)&0xff;//IADDR2
		lwipdev.remoteip[3]=(upcb->remote_ip.addr>>24)&0xff;//IADDR1 
		udp_demo_flag|=1<<6;	//标记接收到数据了
		pbuf_free(p);//释放内存
	}else
	{
		udp_disconnect(upcb); 
		LCD_Clear(WHITE);			//清屏
		POINT_COLOR = RED;
		LCD_ShowString(30,30,200,16,16,"WARSHIP STM32F103");
		LCD_ShowString(30,50,200,16,16,"UDP Test");
		LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
		
		POINT_COLOR=BLUE;
		LCD_ShowString(30,90,200,16,16,"Connect break!");  
		LCD_ShowString(30,110,200,16,16,"KEY1:Connect");
		udp_demo_flag &= ~(1<<5);	//标记连接断开
	} 
}

实验结果

单播发送,一对一发送

	if(key == KEY0_PRES)//KEY0按下了,发送数据
	{
		u8 remote_add[4] = {192,168,1,36};	//发送对端的ip地址
		u8 send_str_data[] = "hello word!";	//要发送的信息
		Unicast_Send(remote_add,send_str_data,0,8089);//单播发送
	}

我按键按下KEY0_PRES按了三次发送,单播发送的端口号为8089,用 Wireshark 抓包
STM32 LWIP UDP 一对一 一对多发送,STM32,stm32,udp,嵌入式硬件,LWIP
也可以用网络调试助手查看是否收到STM32发来的数据,刚刚前面说过我设置自己的电脑ip:192.168.1.36,电脑本机端口号设置和STM32单片机发送数据端口号一致才能收到数据
STM32 LWIP UDP 一对一 一对多发送,STM32,stm32,udp,嵌入式硬件,LWIP

广播发送,一对多发送

	if(key == KEY2_PRES)//KEY2按下了,发送数据
	{
		u8 send_data[8] = {0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8};	//要发送的信息
		Broadcast_Send(send_data,8,8080);//广播发送
	}

我按键按下KEY2_PRES按了两次发送,广播发送的端口号为8080,用 Wireshark 抓包
STM32 LWIP UDP 一对一 一对多发送,STM32,stm32,udp,嵌入式硬件,LWIP
也可以用网络调试助手查看是否收到STM32发来的数据,电脑本机端口号端口号设置和STM32单片机发送数据端口号一致才能收到数据,因为我刚刚设置STM32广播发送的端口号是8080,所以本地端口号8089是不会收到数据的,重新打开一个网络调试助手(端口号设置为8080),此时就可以正常收到数据了
STM32 LWIP UDP 一对一 一对多发送,STM32,stm32,udp,嵌入式硬件,LWIP
接收是正常的我就不演示了,没有 TFT显示屏 可以使用串口来查看单片机是否收到别的单片机发来的数据

		if(udp_demo_flag&1<<6)//是否收到数据?
		{
			LCD_Fill(30,250,lcddev.width-1,lcddev.height-1,WHITE);//清上一次数据
			LCD_ShowString(30,250,lcddev.width-30,lcddev.height-230,16,udp_demo_recvbuf);//显示接收到的数据			
			
			printf("接收到数据:%s\r\n",udp_demo_recvbuf);
			
			udp_demo_flag&=~(1<<6);//标记数据已经被处理了.
		} 

可能遇到的问题

  1. 移植不成功:不会将F1例程移植到F4板子上之类的问题
  2. 移植不会修改程序
  3. 没有设置自己的电脑ip地址
  4. 程序、STM32单片机、网线都没有问题,但电脑没有收到包,此时检查电脑的防火墙
  5. 端口号不一致也收不到包的 (这一点很重要),端口号要一致才能收发数据
  6. 其它等等问题

总结

本人也花了大量时间去研究,如需要源码支付30元,提供技术服务,加企鹅号:970484728,加企鹅时备注STM32 UDP,不需要源码的也不强求;记录下自己的学习过程,我只是刚入门的新手,知道有许多会的大佬,不喜勿喷!欢迎各位小伙伴一起前来讨论。文章来源地址https://www.toymoban.com/news/detail-615043.html

到了这里,关于STM32 LWIP UDP 一对一 一对多发送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • hibernate 一对一 一对多 多对多

    User 实体类 Address 实体类 测试 User实体类 Vlog实体类 测试 测试 mappedby : 属性指向实体关联表的拥有者,声明在被拥有者。 简单说就是另一边定义了关联规则,这边不用再定义一遍了,直接引用就行。 @JoinColumn : 外键列 在一对一中 @JoinColumn 声明在那个实体类中,生成数据库表

    2024年02月13日
    浏览(50)
  • queryWrapper处理一对一,一对多,多对多

    是的,定义一个 BankUser 对象时,通常需要在其内部定义一个 BankCard 字段来表示其与 bank_card 表的关联关系。 例如,在 BankUser 类中定义一个 BankCard 对象作为其属性:```java ``` 然后,在查询 BankUser 对象时,需要使用 LEFT JOIN 将 bank_user 和 bank_card 表进行关联,并使用 select 方法指

    2024年02月04日
    浏览(49)
  • [MySql]实现多表查询-一对一,一对多

    目录 多表关联关系的分类 mybatis中的多表查询: 数据库准备  项目目录  一对一查询(多对一) 方式一:(xml文件映射) 查询结果:  方式二:(注解映射)  一对多查询(一对多) 方式一:(xml文件映射)  方式二:(注解映射) 既然数据库是存储项目中的数据的,项目中的

    2023年04月10日
    浏览(56)
  • TCP一对一聊天

    客户端 服务端  结果展示  第二种 客户端 服务端 结果

    2024年02月04日
    浏览(45)
  • MyBatis关联查询实战:一对一与一对多详细解析

    MyBatis是一款强大的持久层框架,提供了多种方式来处理关联查询,其中包括一对一和一对多的情况。在本文中,我们将深入探讨这两种关联查询的实现方式,并通过具体的示例代码进行详细解释。 实现一对一关联查询的方式有多种,其中包括嵌套查询(Nested Queries)和结果集

    2024年01月19日
    浏览(73)
  • MyBatis案例三:商品的类别(一对一,一对多查询)

    在数据库分别创建一个product、category表: 商品表(product) 商品编号(id) 商品名称(goodsname) 商品单价(price) 商品类别(typeid) 1 电视机 5000 1 2 冰箱 4000 2 3 空调 3000 2 4 洗衣机 2000 2 商品类别表(category) 商品类别编号(id) 商品类别名称(typename) 1 黑色家电 2 白色家电

    2023年04月08日
    浏览(53)
  • OVS Vxlan一对一模式VS一对多模式

    OVS Vxlan模式 OVS 支持 GRE、VXLAN、STT、Geneve和IPsec隧道协议,这些隧道协议就是overlay网络的基础协议,通过对物理网络做的一层封装和扩展,解决了二层网络数量不足的问题,最大限度的减少对底层物理网络拓扑的依赖性,同时也最大限度的增加了对网络的控制。针对VXLAN隧道创

    2024年02月03日
    浏览(58)
  • TCP实现一对一聊天

    一,创建类 二,类 1.ChatSocketServer类 2.ChatSocketClient类 三,结果(先服务  再客户)

    2024年02月03日
    浏览(47)
  • python#django数据库一对一/一对多/多对多

    搭建 # 一对一 class   TestUser(models.Model):     username=models.CharField(max_length=32)     password = models.CharField(max_length=32) class TestInfo(models.Model):     mick_name=models.CharField(max_length=32)     user=models.OneToOneField(to=TestUser,on_delete=models.CASCADE()#on_delete 删除的模式 CASCADE 级联删除 让后执行数

    2024年02月14日
    浏览(78)
  • Mybatis:一对一查询映射处理

    本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远! MyBatis是一种流行的Java持久化框架,它提供了灵活而强大的查询映射功能。在一些复杂的数据模型中

    2024年02月14日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包