STM32 LWIP UDP 一对一 一对多发送

news2024/10/1 7:31:58

STM32 LWIP UDP通信

  • 前言
  • 设置 IP 地址
  • 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

在这里插入图片描述

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发来的数据,刚刚前面说过我设置自己的电脑ip:192.168.1.36,电脑本机端口号设置和STM32单片机发送数据端口号一致才能收到数据
在这里插入图片描述

广播发送,一对多发送

	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发来的数据,电脑本机端口号端口号设置和STM32单片机发送数据端口号一致才能收到数据,因为我刚刚设置STM32广播发送的端口号是8080,所以本地端口号8089是不会收到数据的,重新打开一个网络调试助手(端口号设置为8080),此时就可以正常收到数据了
在这里插入图片描述
没有 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,不需要源码的也不强求;记录下自己的学习过程,我只是刚入门的新手,知道有许多会的大佬,不喜勿喷!欢迎各位小伙伴一起前来讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/807376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual C++中的虚函数和纯虚函数(以外观设计模式为例)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中的虚函数和纯虚函数。该系列帖子全部使用我本人自创的对比学习法。也就是当C学不下去的时候&#xff0c;就用JAVA实现同样的代码&#xff0c;然后再用对比的方法把C学会。 直接说虚函数…

Redis学习---大数据技术之Redis(NoSQL简介、Redis简介、Redis安装、五大数据类型、相关配置、持久化)

星光下的赶路人star的个人主页 毅力是永久的享受 文章目录 1、NoSQL1.1 NoSQL数据库1.1.1 NoSQL是什么1.1.2 NoSQL的特点1.1.3 NoSQL的适用场景1.1.4 NoSQL的不适场景 1.2 NoSQL家族 2、Redis简介2.1 Redis官网2.2 Redis是什么2.3 Redis的应用场景2.3.1 配合关系型数据库做高速…

java复盘

这一题中外部类是Outer。外部类不能直接使用内部类的成员变量和方法&#xff0c;需要内部类的对象来访问他的成员变量和方法。所以该题只是new了一个外部类&#xff0c;内部类无法访问&#xff0c;所以没有输出。 wait后进入等待锁定池&#xff0c;只有针对此对象发出notify或者…

TCP网络通信编程之字节流

目录 【TCP字节流编程】 // 网络编程中&#xff0c;一定是server端先运行 【案例1】 【思路分析】 【客户端代码】 【服务端代码】 【结果展示】 【案例2】 【题目描述】 【注意事项】 【服务端代码】 【客户端代码】 【代码结果】 【TCP字节流编程】 // 网络编程中&a…

list与流迭代器stream_iterator

运行代码&#xff1a; //list与流迭代器 #include"std_lib_facilities.h" //声明Item类 struct Item {string name;int iid;double value;Item():name(" "),iid(0),value(0.0){}Item(string ss,int ii,double vv):name(ss),iid(ii),value(vv){}friend ist…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 26 日论文合集)

文章目录 一、分割|语义相关(7篇)1.1 Learning Transferable Object-Centric Diffeomorphic Transformations for Data Augmentation in Medical Image Segmentation1.2 Optical Flow boosts Unsupervised Localization and Segmentation1.3 Spectrum-guided Multi-granularity…

latex论文----写作代码

一般来说论文机构会给定latex模板代码&#xff0c;我们只需要知道怎么写就行&#xff0c;格式机构都给你调好了 1 各类标题 section是最大的标题&#xff0c;后边每一级小标题&#xff0c;都在前边加个sub就行 \section{Method} \subsection{Dataset} \subsubsection{Dataset…

2014年全国硕士研究生入学统一考试管理类专业学位联考写作试题——解析版

2014年1月真题: 四、写作:第56~57小题&#xff0c;共65分。其中论证有效性分析30 分&#xff0c;论说文35分。 56.论证有效性分析: 分析下述论证中存在的缺陷和漏洞&#xff0c;选择若干要点&#xff0c;写一篇600字左右的文章&#xff0c;对该论证的有效性进行分析和评论。…

error: cannot call member function ‘void me::sendMessage()‘ without object

error: cannot call member function void me::sendMessage&#xff08;&#xff09; without object 原因分析解决方案 原因分析 在connect中&#xff0c;传递函数地址不用带括号。&#xff08;参考函数指针的赋值&#xff09; #include <iostream> // 包含头…

redis线程模型

文章目录 一、redis单线程模型1.1 为什么redis命令处理是单线程&#xff0c;而不采用多线程1.2 单线程的局限及redis的优化方式 二、redis单线程为什么这么快2.1 采用的机制2.2 优化的措施 三、redis的IO多线程模型3.1 redis 为什么引入IO多线程模型3.2 配置io-threads-do-read…

安全测试国家标准解读——数据库管理和文件管理

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解&#xff0c;该标准是2020年4月28日&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&…

SQL-每日一题【1045.买下所有产品的客户】

题目 Customer 表&#xff1a; Product 表&#xff1a; 写一条 SQL 查询语句&#xff0c;从 Customer 表中查询购买了 Product 表中所有产品的客户的 id。 示例&#xff1a; 解题思路 1.题目要求我们 从 Customer 表中查询购买了 Product 表中所有产品的客户的 id。我们可以先…

Memcached服务分布式集群如何实现?

Memcached服务分布式集群如何实现? 在分布式系统中&#xff0c;为了提高可用性、性能和扩展性&#xff0c;通常会使用多台服务器来构建一个Memcached集群。Memcached是一个高性能的分布式内存缓存系统&#xff0c;可以用于缓存数据以减轻数据库或其他后端存储的负载。 以下我们…

网络防御之防病毒网关

1. 什么是恶意软件&#xff1f; 恶意软件是任何软件故意设计造成损害计算机、服务器、客户端或计算机网络&#xff08;相比之下&#xff0c;软件导致无意的伤害由于一些缺陷通常被描述为一个软件错误&#xff09;。各种各样的类型的恶意软件存在的&#xff0c;包括计算机病毒、…

一次性彻底讲透Python中pd.concat与pd.merge

目录 数据拼接&#xff1a;pd.concat数据关联:pd.merge两者区别 数据的合并与关联是数据处理过程中经常遇到的问题&#xff0c;在SQL、HQL中大家可能都有用到 join、uion all 等 &#xff0c;在 Pandas 中也有同样的功能&#xff0c;来满足数据处理需求&#xff0c;个人感觉 …

感谢@中原一点红提供的华为OD机试真题2023Q1 100分“座位调整”,一看nike标志,就稳了

目录 专栏导读一、鸣谢二、题目描述三、输入描述四、输出描述五、思路分析解题思路 六、Java算法源码七、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷…

【动态规划part12】| 309.买卖股票的最佳时机含冷冻期、714.买卖股票的最佳时机含手续费

目录 &#x1f388;LeetCode309.最佳买卖股票时机含冷冻期 &#x1f388;LeetCode714.买卖股票的最佳时机含手续费 &#x1f388;LeetCode309.最佳买卖股票时机含冷冻期 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计…

【Mysql】万字长文带你快速掌握数据库基础概念及SQL基本操作

文章目录 前言一、数据库相关概念1. 什么是数据库2. 数据库的种类3. Mysql 简介4. SQL简介5. 数据库中常见的数据类型 二、SQL基础1. SQL通用语法2. SQL的主要分类3. DDL&#xff08;数据库&#xff0c;表&#xff0c;索引&#xff0c;视图&#xff09;4. DML&#xff08;数据的…

无涯教程-jQuery - Explode方法函数

爆炸效果可以与show/hide/toggle一起使用。这会将元素爆炸或分解为许多碎片。 Explode - 语法 selector.hide|show|toggle( "explode", {arguments}, speed ); 这是所有参数的描述- pieces - exploded/imploded次数。model - 动画的模式。可以设置为"…