在本实验中,开发板主控芯片通过 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
的值即可,当然也要修改端口避免冲突。代码如下:文章来源:https://www.toymoban.com/news/detail-733137.html
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。文章来源地址https://www.toymoban.com/news/detail-733137.html
到了这里,关于【STM32F1】以太网通信之UDP/TCP实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!