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

这篇具有很好参考价值的文章主要介绍了【STM32F1】以太网通信之UDP/TCP实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在本实验中,开发板主控芯片通过 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。文章来源地址https://www.toymoban.com/news/detail-733137.html

到了这里,关于【STM32F1】以太网通信之UDP/TCP实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32+W5500实现以太网通信

    STM32系列32位微控制器基于Arm® Cortex®-M处理器,旨在为MCU用户提供新的开发自由度。它包括一系列产品,集高性能、实时功能、数字信号处理、低功耗/低电压操作、连接性等特性于一身,同时还保持了集成度高和易于开发的特点。本例采用STM32作为MCU。 W5500是一款全硬件TCP/

    2023年04月22日
    浏览(44)
  • STM32F407以太网DMA描述符和数据链路层收发数据

    本文主要介绍STM32F407单片机MAC内核的DMA描述符,以及如何实现以太网二层的数据收发。这一篇先实现数据链路层的正常收发,下一篇再去介绍如何把LWIP移植到单片机上。大部分资料都是把LWIP移植和以太网卡驱动放在一起介绍,对新手不友好。所以我在这篇文章先把网卡驱动

    2024年02月10日
    浏览(63)
  • STM32CubeMX+STM32F407+FreeRTos+LAN8720 以太网通信实现数据收发功能

    目录 前言 一、STM32CubeMX配置 二、修改代码 三、硬件测试 总结 该工程应用的以太网芯片是LAN8720,代码是基于STM32CUbeMx6.2.1配置生成的,在CubeMx中配置了ETH和LWIP,还有串口1和FREERTOS,最后通过创建任务函数实现udp的以太网数据收发功能。在测试中,可以在电脑的DOS窗口ping通在

    2024年02月08日
    浏览(60)
  • 以太网UDP数据回环实验

            前面说到TCP/IP是一个协议簇,其中包含有IP协议、TCP协议、UDP协议、ARP协议、DNS协议、FTP协议等。设备之间要想完成通信,就必须通过这些网络通信协议。          物理层的主要作用就是传输比特流(将1、0转化为电流强弱来进行传输,到达目的地后在转化为1、

    2024年01月23日
    浏览(52)
  • FPGA - 以太网UDP通信(一)

    ​以太网是一种计算机局域网技术。IEEE组织的IEEE 802.3标准制定了以太网的技术标准,它规定了包括物理层的连线、电子信号和介质访问层协议的内容。 ​ 以太网是现实世界中最普遍的一种计算机网络。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一

    2024年04月18日
    浏览(58)
  • STMicroelectronics的STM32微控制器和WIZnet的W5500以太网通信单片机代码

    单片机代码   #include \\\"stm32f1xx_hal.h\\\" #include \\\"string.h\\\"   #define W5500_CS_GPIO_Port GPIOB #define W5500_CS_Pin GPIO_PIN_12   SPI_HandleTypeDef hspi2;   void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SPI2_Init(void);   uint8_t W5500_ReadByte(void) {     uint8_t byte;     HAL_SPI_Receive(hspi2, byte, 1, 10);  

    2023年04月13日
    浏览(86)
  • 基于光口的以太网 udp 回环实验

    本章实验我们通过网络调试助手发送数据给 FPGA,FPGA通过光口接收数据并将数据使用 UDP 协议发送给电脑。 提示:任何文章不要过度深思!万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」 ;不要急着评判文

    2024年01月19日
    浏览(49)
  • FPGA优质开源项目 – UDP万兆光纤以太网通信

    本文开源一个FPGA项目:UDP万兆光通信。该项目实现了万兆光纤以太网数据回环传输功能。Vivado工程代码结构和之前开源的《UDP RGMII千兆以太网》类似,只不过万兆以太网是调用了Xilinx的10G Ethernet Subsystem IP核实现。 下面围绕该IP核的使用、用户接口,以及数据传输方案展开介

    2024年02月10日
    浏览(61)
  • 车载以太网 - 传输层 - TCP通信过程

    TCP 通信阶段 1、连接建立Connection establishment 2、数据传输 Data transfer 3、连接释放 Connection release TCP通信的三个阶段: TCP连接(三次握手) 1、Client(ECUA) - Server(ECU B)第一次握手 2、Server - Client 第二次握手 3、Client - Server 第三次握手 数据传输 1、Client - ServerTCP 数据请求 2、TC

    2024年02月11日
    浏览(48)
  • LwIP系列(3):以太网帧、IP、TCP、UDP、IGMP、ICMP帧格式详解

    TCP/IP 本质上是软件协议,而LwIP也是对软件协议进行解析处理,所以我们有必要了解下以太网帧、IP、TCP、UDP、IGMP、ICMP帧格式,这样在代码中,才能有的放矢。 以太网帧是最底层的原始数据,帧框架如下图所示: 其中【前同步码】和【以太网尾部】我们在抓包的时候,并不

    2024年02月14日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包