IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32 重置ip地址(udp单播) -> 正文阅读

[嵌入式]stm32 重置ip地址(udp单播)

实现了利用udp通信去重新设置mcu的ip地址、子网掩码、网关
udp使用的是静态的ip
默认已经用cubemx配好ETH、lwip已经配好并能进行udp通信

关于udp的配置可看这位大佬
用cubemx配置生成udp代码

1、ip信息结构体

  • 为了方便使用,需要自定义
  • 不同的lwip驱动ip4_addr_t可能不同
struct IP_INFO{
	uint8_t ip_addr[4];
	uint8_t netmask_addr[4];
	uint8_t gateway_addr[4];
	ip4_addr_t ip;//地址
	ip4_addr_t nm;//掩码
	ip4_addr_t gw;//网关
};

struct IP_INFO ip_info;

2、修改ip的核心函数

  • 一般cubemx生成的代码在lwip.c中会有NET_set_addr
  • 只需要将绑定好的ip地址、掩码、网关传给NET_set_addr就行
  • 需要用这个函数:IP4_ADDR 来绑定你的ip地址、网关等
/*
使用示例
IP4_ADDR(&ip_info.ip,192,168,2,100);//掩码和网关也是这样绑
......
NET_set_addr(&ip_info.ip, &ip_info.nm,&ip_info.gw);
*/
void NET_set_addr(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
    const ip4_addr_t *gw)
{
  if (ip4_addr_isany(ipaddr)) {
    /* when removing an address, we have to remove it *before* changing netmask/gw
       to ensure that tcp RST segment can be sent correctly */
    netif_set_ipaddr(&gnetif, ipaddr);
    netif_set_netmask(&gnetif, netmask);
    netif_set_gw(&gnetif, gw);
  } else {
    netif_set_netmask(&gnetif, netmask);
    netif_set_gw(&gnetif, gw);
    /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
    netif_set_ipaddr(&gnetif, ipaddr);
  }
}

3、从消息里获取ip信息

  • 需要一个全局变量struct IP_INFO ip_info;
  • 命令格式(前面可自定义 只需修改函数中i的初始值)
    $setip<xxx.xxx.xxx.xxx><xxx.xxx.xxx.xxx><xxx.xxx.xxx.xxx>
    最好做个判断决定是否要进入消息解析函数
  • 加入了输入语法检测,即保证拿到的是12个数字
    无法保证这12个数字是否合法
/*用于从消息中获取要设置的ip地址等信息*/
struct ip_tmp_udp{
	uint8_t tmp[3];
	int8_t count;
};
/*********************************************************************
功  能:将字符串转换数字
示例
   str.tmp[0] = 1
   str.tmp[1] = 9
   str.tmp[2] = 2
   转化后
   dest = 192
*********************************************************************/
void udp_string_to_num(struct ip_tmp_udp str,uint8_t *dest){
	
	uint8_t num = 0;
/*
	这段有问题,会传出奇怪的值
	int i = 0;
	str.count--;
	while(1){
	 if(tr.count < 0){
	  break;
	 }
	 num = num + str.tmp[i]*10^str.count;
	 i++;
	 str.count--;
	}
*/
	if(str.count == 3){
		num = str.tmp[0]*100+str.tmp[1]*10+str.tmp[2];
	}
	else if(str.count == 2){
		num = str.tmp[0]*10+str.tmp[1];	
	}
	else{
		num = str.tmp[0];		
	}
	
	*dest = num;
}

/*********************************************************************
功  能:从数据中获取ip地址,子网掩码,网关等信息
					ip                掩码           网关
命令:$setip<xxx.xxx.xxx.xxx><xxx.xxx.xxx.xxx><xxx.xxx.xxx.xxx>
循环1:解析xxx,由于xxx的位数不确定(可能为3,2,1位)  
循环2:解析<...>
循环3:解析<><><>
*********************************************************************/
void udp_GetIp_AND_Reset(char *recv_msg){
	
	char send_data[128] = {0};
	uint8_t left = 0;//计数<
	uint8_t right = 0;//计数>
	uint8_t i = 6;//遍历recv_msg;
	uint8_t j = 4;//计数“.”

	uint8_t check = 1;//检测输入合法性 1合法,0不合法
	
	struct IP_INFO ip_info_tmp;
	struct ip_tmp_udp str;//暂存xxx

	//读到$setip进入本循环
	while(check)//循环3
	{

		if(i > 57 || right > 4 || j <4)//异常结束循环
		{	
			sprintf(send_data,"(1)fail to setip : %d\r\n",i);				
			check = 0;
		}
		else if(right == 3 && right == left)//正常结束所有循环
		{
			break;
		}
					
		if(recv_msg[i] == '<')
		{
			i++;  //recv_msg[i] == '<' 所以要i+1;
			
			j = 0;//“.”计数置0
			while(recv_msg[i-1] != '>' && check)//循环2
			{
				str.count = 0;
				/* <xxx.xxx.xxx.xxx> <>*/
				while(recv_msg[i] != '.' && recv_msg[i] != '>' && check)//循环1
				{
					
					/* xxx每一位合理的范围是 0 ~ 9 */
					if(recv_msg[i]>57 || recv_msg[i]<48)
					{
		        sprintf(send_data,"(2)fail to setip : %d\r\n",i);							
						check = 0;
						break;						
					}
					str.tmp[str.count] = recv_msg[i]-48;//逐位复制xxx
					str.count++;//xxx 计数+1
					
					/* xxx合理位数为1~3,<xxxx.xx*/
					if(str.count >3)
					{
						sprintf(send_data,"(3)fail to setip : %d\r\n",i);
						check = 0;
						break;
					}
					
					i++;
				}
				
				/* xxx合理位数为1~3,<xxx..xxx提醒出错的位数 */
				if(str.count == 0)
				{
					sprintf(send_data,"(4)fail to setip : %d\r\n",i);
					check = 0;
					break;
				}
				
				
				if(check)
				{
					if(left == 0)
					{
						udp_string_to_num(str,&ip_info_tmp.ip_addr[j]);
					}
					else if(left == 1)
					{
						udp_string_to_num(str,&ip_info_tmp.netmask_addr[j]);
					}
					else
					{
						udp_string_to_num(str,&ip_info_tmp.gateway_addr[j]);
					}						
				}

				j++;//“.”计数+1
			
				if(j > 4)
				{
					sprintf(send_data,"(5)fail to setip : %d\r\n",i);						
					check = 0;
					break;
				}
				
				i++;
				
			}
		 left++;
	 }
			
	right++;
		 
 }

	if(check)
	{
		for(i = 0;i<4;i++){
			ip_info.ip_addr[i] = ip_info_tmp.ip_addr[i];
			ip_info.netmask_addr[i] = ip_info_tmp.netmask_addr[i];
			ip_info.gateway_addr[i] = ip_info_tmp.gateway_addr[i]; 
		}
		sprintf(send_data,"step1 of setip is complete\r\n");
		
		
		if(1) //ip 掩码 网关 合法性检测(未完成)
		{
			udp_ResetIp();//重置ip
		}

	}
		
//	udp_app_send(send_data,strlen(send_data));//消息回传到指定地址	
	
}

4、接收回调函数

  • 我是先解析一次消息再调用的上面的函数
static void udp_receive_callback(void *arg, struct udp_pcb *pcb,
	 struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
	char udp_msg[512] = {0};
	
	if(p!=NULL){
		
		pbuf_copy_partial(p,(void *)udp_msg,p->len,0);//这样复制不会有乱码
		
		udp_app_sendto(udp_msg,strlen(udp_msg),*addr,port);//消息回传,并重置udp发送端口
		
		udp_parse_cmd(udp_msg);//命令解析
	
		pbuf_free(p);
	} 
}

5、运行截图

  • 修改测试

在这里插入图片描述

  • 语法检测(仅能检测 $setip后面)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:50:48  更:2022-10-17 12:54:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:19:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码