STM32 LWIP UDP 一对一 一对多发送

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,不需要源码的也不强求;记录下自己的学习过程,我只是刚入门的新手,知道有许多会的大佬,不喜勿喷!欢迎各位小伙伴一起前来讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kata Containers

Kata Containers&#xff08;简称 Kata 或 Kata Containers&#xff09;是一个开源的容器运行时项目&#xff0c;它提供了一种轻量级的虚拟化解决方案&#xff0c;用于在容器内运行应用程序。Kata Containers 结合了虚拟机&#xff08;VM&#xff09;和容器的优势&#xff0c;旨…

【容器编排】初识 Kubernetes

目录 1.简介 2.为什么需要 k8s 3.k8s 能做什么? 4.k8s 不是什么? 1.简介 摘取官网: 概述 | Kubernetes Kubernetes 这个名字源于希腊语&#xff0c;意为舵手或飞行员。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kub…

gti 远程操作

目录 一. 分布式版本控制管理系统 1. 理解分布式版本控制管理系统 二. 创建远程仓库 ​编辑 ​编辑 三. 克隆远程仓库_HTTP 四. 克隆远程仓库_SSH 配置公钥 添加公钥 五. git 向远程仓库推送 六. 拉取远程仓库 七. 忽略特殊文件 八. 配置别名 一. 分布式版本控制管理…

【腾讯云 Cloud Studio 实战训练营】体验搭建软件系统,无经验也能做开发

文章目录 前言IDE 解放开发者的生产力功能强大的 IDE快速搭建 Vue 开发环境注册 Cloud Studio进入Vue预置开发环境安装相关依赖包主文件 main.js 引入相关库和包首页增加移动端默认样式增加主要代码 IDE 的适用场景总结 前言 云计算技术的不断发展为代码开发带来了全新的体验&…

git本地库和远程库的相关操作命令

目录 一、分支概念&#xff1a; 二、 本地库分支管理&#xff1a; 1. 查看分支情况&#xff1a; 命令1&#xff1a;git branch 2. 新建分支 命令1&#xff1a; git branch <分支名> 命令2&#xff1a; git branch <新建分支名> <源分支名> 命令3&…

打印Winform控件实现简陋版的分页打印(C#)

本文的代码可以从这里获取&#xff1a;winformDemo.rar 张祥裕/分享的资源名称 - Gitee.com 作者的水平有限&#xff0c;如有错误&#xff0c;望指正。 为了简单起见&#xff0c;纸张大小&#xff0c;打印机等信息按照默认的来&#xff0c;本文的实现方案是&#xff1a;打印Pa…

RN 设置背景图片(使用ImageBackground组件)

在RN版本0.46版本的时候添加了ImageBackground控件。ImageBackground可以设置背景图片&#xff0c;使用方法和image一样&#xff0c;里面嵌套了其他的组件 import React from "react"; import { ImageBackground, StyleSheet, Text, View } from "react-native…

可以写进简历的kafka优化-----吞吐量提升一倍的方法

冲突 在看到项目工程里kafka 生产端配置的batch.size为500&#xff0c;而实际业务数据平均有1K大小的时候&#xff1b;我有点懵了。是的&#xff0c;这里矛盾了&#xff1b;莫非之前的作者认为这个batch.size是发送的条数&#xff0c;而不是kafka生产端内存缓存记录的大小&…

脑电信号处理与特征提取——5.频谱分析和时频分析(张治国)

目录 五、频谱分析和时频分析 5.1 频谱估计 5.1.1 基本概念 5.1.2 频谱估计方法&#xff1a;周期图 5.1.3 频谱估计方法&#xff1a;Welch法 5.1.4 频谱估计方法的比较 5.1.5 频谱特征提取 5.2 时频分析 5.2.1 短时傅里叶变换 5.2.2 连续小波变换 5.3 事件相关同步…

【能量管理系统( EMS )】基于粒子群算法对光伏、蓄电池等分布式能源DG进行规模优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

vuejs源码阅读之代码生成器

代码生成器是模版编译的最后以后&#xff0c;它的作用是将AST转换成渲染函数中的内容&#xff0c;这个内容可以称为代码字符串。 代码字符串可以被包装在函数中执行&#xff0c;这个函数就是我们通常说的渲染函数。 渲染函数被执行之后&#xff0c;可以生成一份VNode&#xf…

爬取微博热搜榜并进行数据分析

设计方案 爬虫爬取的内容 &#xff1a;爬取微博热搜榜数据。 网络爬虫设计方案概述 用requests库访问页面用get方法获取页面资源&#xff0c;登录页面对页面HTML进行分析&#xff0c;用beautifulsoup库获取并提取自己所需要的信息。再讲数据保存到CSV文件中&#xff0c;进行…

day48-Random Image Feed(随机图片显示)

50 天学习 50 个项目 - HTMLCSS and JavaScript day48-Random Image Feed&#xff08;随机图片显示&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&…

EIP-2535 Diamond standard 实用工具分享

前段时间工作对接到了这标准的协议&#xff0c;于是简单介绍下这个标准分享下方便前端er使用的调用工具 一、标准的诞生 在写复杂逻辑的solidity智能合约时&#xff0c;经常会碰到两个问题&#xff0c;升级和合约大小限制。 升级目前有几种proxy模式&#xff0c;通过delegateca…

如何选择合适的客户管理系统(CRM系统)

本篇文章将介绍如何选择适合您业务的客户管理系统。我们将讨论如何考虑不同的需求、功能和预算&#xff0c;以及如何在众多选项中选择最佳解决方案。 一、选择合适的客户管理系统的重要性 1、提高工作效率: 客户管理系统可以简化许多繁琐、重复的工作流程&#xff0c;如数据输…

Spring Alibaba Sentinel实现集群限流demo

1.背景 1.什么是单机限流&#xff1f; 小伙伴们或许遇到过下图这样的限流配置 又或者是这样的Nacos动态配置限流规则&#xff1a; 以上这些是什么限流&#xff1f;没错&#xff0c;就是单机限流&#xff0c;那么单机限流有什么弊端呢&#xff1f; 假设我们集群部署3台机器&a…

【*1900 图论+枚举思想】CF1328 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 注意到题目的性质&#xff1a;满足条件的路径个数是极少的&#xff0c;因为每个点离路径的距离<1 先考虑一条链&#xff0c;那么直接就选最深那个点作为端点即可 为什么&#xff0c;因为我们需要遍历所有点…

桥接模式——处理多维度变化

1、简介 1.1、概述 桥接模式是一种很实用的结构型设计模式。如果软件系统中某个类存在两个独立变化的维度&#xff0c;通过该模式可以将这两个维度分离出来&#xff0c;使两者可以独立扩展&#xff0c;让系统更加符合单一职责原则。与多层继承方案不同&#xff0c;它将两个独…

nosql之redis集群

nosql之redis集群 一.redis集群 1.单节点redis服务器带来的问题 &#xff08;1&#xff09;单点故障、服务不可用 &#xff08;2&#xff09;无法处理大量的并发数据请求 &#xff08;3&#xff09;数据丢失 2.集群redis &#xff08;1&#xff09;提供在多个redis节点间…

网络运维基础问题及解答

前言 本篇文章是对于网络运维基础技能的一些常见问题的解答&#xff0c;希望能够为进行期末复习或者对网络运维感兴趣的同学或专业人员提供一定的帮助。 问题及解答 1. 列举 3 种常用字符编码&#xff0c;简述怎样在 str 和 bytes 之间进行编码和解码。 答&#xff1a;常用的…