实现了利用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地址、网关等
void NET_set_addr(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
const ip4_addr_t *gw)
{
if (ip4_addr_isany(ipaddr)) {
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);
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个数字是否合法
struct ip_tmp_udp{
uint8_t tmp[3];
int8_t count;
};
void udp_string_to_num(struct ip_tmp_udp str,uint8_t *dest){
uint8_t num = 0;
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;
}
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;
uint8_t j = 4;
uint8_t check = 1;
struct IP_INFO ip_info_tmp;
struct ip_tmp_udp str;
while(check)
{
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++;
j = 0;
while(recv_msg[i-1] != '>' && check)
{
str.count = 0;
while(recv_msg[i] != '.' && recv_msg[i] != '>' && check)
{
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;
str.count++;
if(str.count >3)
{
sprintf(send_data,"(3)fail to setip : %d\r\n",i);
check = 0;
break;
}
i++;
}
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++;
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)
{
udp_ResetIp();
}
}
}
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_parse_cmd(udp_msg);
pbuf_free(p);
}
}
5、运行截图
|