【STM32F1】以太网通信之UDP/TCP实验 您所在的位置:网站首页 udp调试助手使用教程图解 【STM32F1】以太网通信之UDP/TCP实验

【STM32F1】以太网通信之UDP/TCP实验

2023-06-08 11:15| 来源: 网络整理| 查看: 265

在本实验中,开发板主控芯片通过 SPI 接口与 CH395Q 以太网芯片进行通讯,从而完成对 CH395Q 以太网芯片的功能配置、数据接收等功能,同时将 CH395Q 以太网芯片的 Socket0 配 置为 UDP 模式,并可通过按键发送 UDP 广播数据至其他的 UDP 客户端,也能够接收其他 UDP 客户端广播的数据,并实时显示至串口调试助手

CH395Q进行UDP实验,实际是在移植的基础上,将ch395_socket结构体内容拷贝给ch395q_t结构体。而ch395q_socket_config函数做的便是这个功能。

1. ch395q_socket_config函数是怎么进行两个结构体的拷贝的?

网络如果正常,也就是说若可以监测到socket,那就判断dhcp状态即是否满足g_ch395q_sta.dhcp_status == DHCP_UP,满足则进行动态ip分配DHCP

这里是ch395_socket结构体:

typedef struct ch395q_socket_t { uint8_t socket_enable; /* Socket使能 */ uint8_t socket_index; /* Socket标号 */ uint8_t proto; /* Socket协议 */ uint8_t des_ip[4]; /* 目的IP地址 */ uint16_t des_port; /* 目的端口 */ uint16_t sour_port; /* 源端口 */ struct { uint8_t *buf; /* 缓冲空间 */ uint32_t size; /* 缓冲空间大小 */ } send; /* 发送缓冲 */ struct { uint8_t recv_flag; /* 接收数据标志位 */ uint8_t *buf; /* 缓冲空间 */ uint32_t size; /* 缓冲空间大小 */ } recv; /* 接收缓冲 */ struct { uint8_t ip[4]; /* IP地址 */ uint8_t gwip[4]; /* 网关IP地址 */ uint8_t mask[4]; /* 子网掩码 */ uint8_t dns1[4]; /* DNS服务器1地址 */ uint8_t dns2[4]; /* DNS服务器2地址 */ } net_info; /* 网络信息 */ struct { uint8_t ipaddr[4]; /* IP地址 32bit*/ uint8_t gwipaddr[4]; /* 网关地址 32bit*/ uint8_t maskaddr[4]; /* 子网掩码 32bit*/ uint8_t macaddr[6]; /* MAC地址 48bit*/ } net_config; /* 网络配置信息 */ } ch395_socket;

结构体g_ch395q_sta

struct ch395q_t { uint8_t version; /* 版本信息 */ uint8_t phy_status; /* PHY状态 */ uint8_t dhcp_status; /* DHCP状态 */ uint8_t ipinf_buf[20]; /* 获取IP信息 */ struct { ch395_socket config; /* 配置信息 */ } socket[8]; /* Socket状态 */ void (*ch395_error)(uint8_t i); /* ch395q错误检测函数 */ void (*ch395_phy_cb)(uint8_t phy_status); /* ch395q phy状态回调函数 */ void (*ch395_reconnection)(void); /* ch395q 重新连接函数 */ }; extern struct ch395q_t g_ch395q_sta;

将结构体g_ch395q_sta赋给ch395_sokect,部分代码如下:

ch395_sokect->net_info.ip[0] = g_ch395q_sta.ipinf_buf[0]; ch395_sokect->net_info.ip[1] = g_ch395q_sta.ipinf_buf[1]; ch395_sokect->net_info.ip[2] = g_ch395q_sta.ipinf_buf[2]; ch395_sokect->net_info.ip[3] = g_ch395q_sta.ipinf_buf[3]; ch395_sokect->net_info.gwip[0] = g_ch395q_sta.ipinf_buf[4]; ch395_sokect->net_info.gwip[1] = g_ch395q_sta.ipinf_buf[5]; ch395_sokect->net_info.gwip[2] = g_ch395q_sta.ipinf_buf[6]; ch395_sokect->net_info.gwip[3] = g_ch395q_sta.ipinf_buf[7];

如果dhcp获取失败就要使用静态方式获取了:

ch395_cmd_set_ipaddr(ch395_sokect->net_config.ipaddr); /* 设置CH395的IP地址 */ ch395_cmd_set_gw_ipaddr(ch395_sokect->net_config.gwipaddr); /* 设置网关地址 */ ch395_cmd_set_maskaddr(ch395_sokect->net_config.maskaddr); /* 设置子网掩码,默认为255.255.255.0*/ ch395_cmd_init(); delay_ms(10);

接着将ch395_sokect中的内容拷贝复制给g_ch395q_sta,实现代码如下;

memcpy(&g_ch395q_sta.socket[ch395_sokect->socket_index].config, ch395_sokect, sizeof(ch395_socket));

接着进行模式判断,判断是udp还是tcp,源代码中用了个switch来实现。

2. 如何使用ch395q_socket_config配置udp进行实验

不能只依赖于DHCP,我们也要配置静态的,那根据ch395_socket结构体中的成员,要配置静态的网络信息,包括ip、网关、子网掩码、mac等。这部分代码定义如下:

/* 设置静态的网络信息,如IP地址、MAC地址、子网掩码、网关*/ uint8_t ch395q_ipaddr[4] = {192,168,1,100}; uint8_t ch395q_gwipaddr[4] = {192,168,1,1}; uint8_t ch395q_ipmask[4] = {255,255,255,0}; uint8_t ch395q_mac_addr[6] = {0xB8,0xAE,0x1D,0x00,0x00,0x00}; //正点原子申购的mac地址 /*设置远程ip地址*/ uint8_t ch395q_des_ipaddr[4] = {172,18,45,96}; //设置为本机的ip /*设置socket的接收发送缓冲区*/ static uint8_t socket0_send_buf[] = {"This is from CH395Q DATA"}; static uint8_t socket0_recv_buf[1024]; ch395_socket ch395q_config[8];//因为有8个socket接口所以是8

接着配置ch395_socket ch395q_config[8];这个即可:

ch395q_config[0].socket_enable = CH395Q_ENABLE; ch395q_config[0].socket_index = CH395Q_SOCKET_0; ch395q_config[0].sour_port = 8080; ch395q_config[0].des_port = 8080; /*设置其静态ip与远程ip*/ memcpy(ch395q_config[0].des_ip,ch395q_des_ipaddr,sizeof(ch395q_des_ipaddr));//远程 memcpy(ch395q_config[0].net_config.ipaddr,ch395q_ipaddr,sizeof(ch395q_ipaddr));//静态 memcpy(ch395q_config[0].net_config.gwipaddr,ch395q_gwipaddr,sizeof(ch395q_gwipaddr));//网关 memcpy(ch395q_config[0].net_config.maskaddr,ch395q_ipmask,sizeof(ch395q_ipmask));//子网掩码 memcpy(ch395q_config[0].net_config.macaddr,ch395q_mac_addr,sizeof(ch395q_mac_addr));//子网掩码 /*设置发送缓冲区*/ ch395q_config[0].recv.buf = socket0_recv_buf; ch395q_config[0].recv.size = sizeof(socket0_recv_buf); ch395q_config[0].send.buf = socket0_send_buf; ch395q_config[0].send.size = sizeof(socket0_send_buf); /*协议类型*/ ch395q_config[0].proto = CH395Q_SOCKET_UDP; ch395q_socket_config(&ch395q_config[0]);

最后编写按键按下发送数据的功能:

while(1){ ch395q_handler(); key = key_scan(0); if(key == KEY0_PRES){ /** * 第一个参数指用socket0发送还是用哪个 * 第二个参数是发送的数据, * 第三个是发送的大小 */ ch395_send_data(0,socket0_send_buf,sizeof(socket0_send_buf)); } } 3. 配置TCPClient与TCPServer通信

在UDP基础上对协议类型进行修改即可:

/*协议类型*/ ch395q_config[0].proto = CH395Q_SOCKET_TCP_CLIENT; 4. 配置多socket口的协议

如socket0配置为udp,socket1配置为tcpclient

这里ch395_socket ch395q_config[8] 修改为ch395_socket ch395q_config; 接着代码其他部分对应修改,修改后;

ch395q_config.socket_enable = CH395Q_ENABLE; ch395q_config.socket_index = CH395Q_SOCKET_0; ch395q_config.sour_port = 8080; ch395q_config.des_port = 8080; /*设置其静态ip与远程ip*/ memcpy(ch395q_config.des_ip,ch395q_des_ipaddr,sizeof(ch395q_des_ipaddr));//远程 memcpy(ch395q_config.net_config.ipaddr,ch395q_ipaddr,sizeof(ch395q_ipaddr));//静态 memcpy(ch395q_config.net_config.gwipaddr,ch395q_gwipaddr,sizeof(ch395q_gwipaddr));//网关 memcpy(ch395q_config.net_config.maskaddr,ch395q_ipmask,sizeof(ch395q_ipmask));//子网掩码 memcpy(ch395q_config.net_config.macaddr,ch395q_mac_addr,sizeof(ch395q_mac_addr));//子网掩码 /*设置发送缓冲区*/ ch395q_config.recv.buf = socket0_recv_buf; ch395q_config.recv.size = sizeof(socket0_recv_buf); ch395q_config.send.buf = socket0_send_buf; ch395q_config.send.size = sizeof(socket0_send_buf); /*协议类型*/ ch395q_config.proto = CH395Q_SOCKET_UDP; ch395q_socket_config(&ch395q_config);

这里就配置好了socket0为udp模式,注意ch395q_config.socket_index = CH395Q_SOCKET_0;这句代码,指明socket0。接着配置socket1,我们只要修改ch395q_config.socket_index的值即可,当然也要修改端口避免冲突。代码如下:

ch395q_config.socket_enable = CH395Q_ENABLE; ch395q_config.socket_index = CH395Q_SOCKET_1; ch395q_config.sour_port = 5050; ch395q_config.des_port = 5050; /*设置发送缓冲区*/ ch395q_config.recv.buf = socket1_recv_buf; ch395q_config.recv.size = sizeof(socket1_recv_buf); ch395q_config.send.buf = socket1_send_buf; ch395q_config.send.size = sizeof(socket1_send_buf); /*协议类型*/ ch395q_config.proto = CH395Q_SOCKET_UDP; ch395q_socket_config(&ch395q_config);

上述代码中新的发送接收缓冲区定义已省略。这样就配置好了多socket。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有