精华内容
下载资源
问答
  • 两块W5500以太网模块,一块TCP服务端,一块TCP客户端,单独与PC通信都可以,两种用交叉网线连接通信失败,已经改了MAC地址不一样,两者的IP和端口也符合要求,Debug时发现接收方不能接收
  • 文档包含以太网模块W5500中文和英文文档介绍资料,非常方便,分享给大家!
  • /*********************************************************************************************** 工 程 名:W5500模块测试** 硬件连接:*PB12←--→ LED 小蓝开发版管脚示意图*PB0 ←--→ W5500_SCS ...

    /**********************************************************************************************

    * 工 程 名:  W5500模块测试

    *

    * 硬件连接:

    *  PB12←--→ LED                       小蓝开发版管脚示意图

    *  PB0 ←--→ W5500_SCS                          ┌   SW  ─┐

    *      ←--→                              Vbat─┤VB    3.3├─3.3V

    *  PA5 ←--→ W5500_SCK                        ─┤C13   GND├─GND

    *  PA6 ←--→ W5500_MISO                       ─┤C14    5v├─5v

    *  PA7 ←--→ W5500_MOSI                       ─┤C15    B9├─

    *      ←--→                                  ─┤A0     B8├─

    *  PA9 ←--→ USART1_TX                        ─┤A1     B7├─

    *  MCU ←--→ 00000000                         ─┤A2     B6├─

    *  MCU ←--→ 00000000                         ─┤A3     B5├─

    *  MCU ←--→ 00000000                         ─┤A4     B4├─

    *  MCU ←--→ 00000000                spi1_CLK ─┤A5     B3├─

    *  MCU ←--→ 00000000                spi1_MISO─┤A6    A15├─

    *  MCU ←--→ 00000000                spi1_MOSI─┤A7    A12├─

    *  MCU ←--→ 00000000                         ─┤B0    A11├─

    *  MCU ←--→ 00000000                         ─┤B1    A10├─Uar1_Tx

    *  MCU ←--→ 00000000                         ─┤B10    A9├─Uar1_Rx

    *  MCU ←--→ 00000000                         ─┤B11    A8├─

    *  MCU ←--→ 00000000                     REST─┤RSET  B15├─

    *  MCU ←--→ 00000000                      3.3─┤3.3   B14├─

    *  MCU ←--→ 00000000                      GND─┤GND   B13├─

    *  MCU ←--→ 00000000                      GND─┤GND   B12├─(LED)

    *                                                └─ USB ─┘

    *

    ***********************************************************************************************/

    Pin Nb  PINs          FUNCTIONs           LABELs

    5       PD0-OSC_IN    RCC_OSC_IN

    6       PD1-OSC_OUT   RCC_OSC_OUT

    15      PA5           SPI1_SCK            W5500_SCK

    16      PA6           SPI1_MISO           W5500_MISO

    17      PA7           SPI1_MOSI           W5500_MOSI

    18      PB0           GPIO_Output         W5500_SCS

    19      PB1           GPIO_Output

    25      PB12          GPIO_Output         LED

    30      PA9           USART1_TX

    31      PA10          USART1_RX

    34      PA13          SYS_JTMS-SWDIO

    37      PA14          SYS_JTCK-SWCLK

    Configuration        STM32F103C8

    STM32CubeMX         4.26.0

    Date        07/05/2018

    MCU        STM32F103C8Tx

    PERIPHERALS        MODES        FUNCTIONS        PINS

    RCC        Crystal/Ceramic Resonator        RCC_OSC_IN        PD0-OSC_IN

    RCC        Crystal/Ceramic Resonator        RCC_OSC_OUT        PD1-OSC_OUT

    SPI1        Full-Duplex Master        SPI1_MISO        PA6

    SPI1        Full-Duplex Master        SPI1_MOSI        PA7

    SPI1        Full-Duplex Master        SPI1_SCK        PA5

    SYS        Serial Wire        SYS_JTCK-SWCLK        PA14

    SYS        Serial Wire        SYS_JTMS-SWDIO        PA13

    SYS        SysTick        SYS_VS_Systick        VP_SYS_VS_Systick

    USART1        Asynchronous        USART1_RX        PA10

    USART1        Asynchronous        USART1_TX        PA9

    展开全文
  • W5500以太网芯片及模块使用

    万次阅读 2016-04-29 14:19:16
    以太网转spi接口的,模块上有3个led和一个复位按钮 25  LINKLED  网络连接指示灯(Link LED)  显示当前连接状态:  低电平:连接建立;  高电平:未连接;  26  DUPLED  全/半双工指示灯

    一、模块介绍

    是以太网转spi接口的,模块上有3个led和一个复位按钮,灯的含义是:

    LINKLED 
    网络连接指示灯(Link LED) 
    显示当前连接状态: 
    低电平:连接建立; 
    高电平:未连接; 

    DUPLED 
    全/半双工指示灯(Duplex LED) 
    显示当前连接的双工状态: 
    低电平:全双工状态; 
    高电平:半双工状态; 

    ACTLED 
    活动状态指示灯(Active LED) 
    显示数据收/发活动时,物理介质子层的载波侦听活动情
    况: 
    低电平:有物理介质子层的载波侦听信号; 
    高电平:无物理介质子层的载波侦听信号;


    但貌似配置成全双工100M的速度也没什么增加,哪里出问题了呢?我现在使用18M的spi,使用wiz官方loopback软件测试速度为5Mb/s左右,好慢啊(/ □ \)

    二、模块驱动

    注意:在官网上有人共享了github的库函数驱动,不过是C99标准的,这一段Keil的c编译器支持好像有问题,而且对于是库函数很致命,使用寄存器则无所谓

    比如:ctlsocket和ctlwizchip函数的参数会因C99和C89的强转void类型定义不同,使其失效。eg:0x0000不会错,0x0010可能会篡改成0x4e3c

    展开全文
  • 支持wifi以太网双网络通信,支持阿里云MQTT通信,数据上传到阿里生活平台,阿里云IoT Studio web可视化开发,支持onenet MQTT与http通信,onenet web可视化开发。使用Android Studio 自主写一个MQTT手机app远程...
  • W5500以太网模块是一款基于WIZnet W5500芯片的以太网模块,性能出色、性价比高。 模块集成硬件化TCP/IP协议;内部具有32K字节存储器作为TX/RX缓存;支持10/100Mbps网络传输速率;支持8个独立端口同时运行;同时支持...
  • 本篇详细的记录了如何使用STM...W5500以太网模块 这里我使用常见的以太网模块W5500: W5500官网 http://www.w5500.cn/ W5500中文手册 iEthernet W5500 Datasheet 软件准备 需要安装好Keil - MDK及芯片对应的包,以

    本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件SPI外设与以W5500通信,驱动以太网模块。

    1. 准备工作

    硬件准备

    • 开发板

    首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi):

    • W5500以太网模块

    这里我使用常见的以太网模块W5500:

    软件准备

    • 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码;
    • 准备一个串口调试助手,这里我使用的是Serial Port Utility
    • 准备一个网络调试助手,这里我使用的是sockettool

    2.生成MDK工程

    选择芯片型号

    打开STM32CubeMX,打开MCU选择器:
    mark

    搜索并选中芯片STM32L431RCT6:
    mark

    配置时钟源

    • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
    • 如果使用默认内部时钟(HSI),这一步可以略过;

    这里我都使用外部时钟:

    mark

    配置以太网模块控制GPIO

    以太网模块需要额外配置的GPIO有两个:

    以太网模块引脚名 GPIO 作用
    RST PC9 以太网模块硬复位
    INT PA0 中断引脚

    复位引脚配置为输出模式即可:

    中断引脚需要接收来自以太网模块的中断,所以需要配置EXTI外部中断引脚:

    配置SPI1接口

    本实验中,我将以太网模块接到了SPI1接口,引脚对应表如下:

    需要注意,SPI片选引脚不通过硬件SPI外设来控制,而是配置为普通GPIO,手动控制

    以太网模块引脚 MCU引脚
    MISO PA6(SPI1_MISO)
    MOSI PA12(SPI1_MOSI)
    SCS PA4(SPI1_NSS)
    SCLK PA1(SPI1_SCK)

    配置SPI接口的时候有三个需要注意的点:

    ① 分频系数;
    ② CPOL:CLK空闲时候的电平为高电平或者低电平;
    ③ CPHA:在第1个时钟边缘采样,还是在第2个时钟边缘采样;

    接下来开始配置SPI1外设,首先配置SPI1外设的模式和引脚:

    因为选择了不使用硬件SPI外设控制片选引脚,所以需要手动配置片选引脚PA4:

    W5500手册中给出的SPI总线时钟为80Mhz:

    但是,需要注意,手册中明确注明了实际至少保证33.3Mhz,所以为了稳妥起见,本实验中配置SPI总线时钟为20Mhz

    对于CPOL,W5500两种模式都支持,选择空闲时为LOW的模式,CPHA手册中给出为第一个时钟沿:

    综上所述,时序参数配置如下:

    配置串口

    开发板板载了一个CH340z换串口,连接到USART1。

    接下来开始配置USART1

    配置时钟树

    STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:
    mark

    生成工程设置

    代码生成设置

    最后设置生成独立的初始化文件:

    生成代码

    点击GENERATE CODE即可生成MDK-V5工程:
    mark

    3. 重定向printf函数到USART1

    参考:【STM32Cube_09】重定向printf函数到串口输出的多种方法

    4. 移植W5500官方驱动库

    4.1. 下载官方驱动库

    W5500官方提供了ioLibrary v2.0.0,ioLibrary是WIZnet芯片的以太网驱动库,它包括驱动程序和应用程序协议。该驱动程序(ioLibrary)可用于WIZnet TCP / IP芯片的应用设计,如W5500,W5300,W5200,W5100 W5100S。

    下载地址有两个:

    源码目录结构如图:

    • Ethernet : 类似BSD的SOCKET API接口,以及WIZCHIP(W5500 / W5300 / W5200 / W5100 / W5100S) 驱动
    • Internet : 各种应用层协议栈
      • DHCP client
      • DNS client
      • FTP client
      • FTP server
      • SNMP agent/trap
      • SNTP client
      • TFTP client
      • HTTP server
      • MQTT Client

    4.2. 添加驱动库到工程中

    在工程目录下新建 Hardware/W5500,将驱动库中的三个文件夹都复制过来:

    注意,这其中只有Ethernet下的文件是必需的,其余两个文件夹的文件可选添加,在后面进行测试时会用到。

    接下来将Ethernet目录下和W5500相关的文件添加到MDK工程中:

    添加头文件路径:

    确保C99模式开启(STM32Cubemx生成的工程中默认开启):

    4.3. 配置所使用的芯片型号

    打开wizchip_conf.h文件,在最开始修改宏定义_WIZCHIP_,该宏定义指明了我们所用的芯片型号,设置为W5500:

    5. 适配W5500官方驱动

    W5500官方驱动库中通过 _WIZCHIP 结构体中定义的一组函数指针来管理spi驱动,为了防止添加后直接报错,在 wizchip_conf.c 中提供了这些函数指针的默认实现,都为空函数,所以此时编译时不会报错。

    这两个适配文件已开源,Github地址:https://github.com/Mculover666/HAL_Driver_Lib

    5.1. 添加移植适配文件

    接下来我们在项目工程中,新建w5500_port_hal.h文件和w5500_port_hal.c文件来存放自己的实现,并利用驱动库提供的接口,注册到驱动库中。

    加入到MDK工程中:

    添加头文件路径:

    5.2. 编写头文件

    编写w5500_port_hal.h文件:

    #ifndef _W5500_PORT_HAL_
    #define _W5500_PORT_HAL_
    
    #include "wizchip_conf.h"
    #include "stm32l4xx.h"
    #include <string.h>
    #include <stdio.h>
    
    #define W5500_SPI_HANDLE    hspi1
    #define W5500_CS_PORT       GPIOA
    #define W5500_CS_PIN        GPIO_PIN_4
    #define W5500_RST_PORT      GPIOC
    #define W5500_RST_PIN       GPIO_PIN_9
    
    #define DEFAULT_MAC_ADDR    {0x00,0xf1,0xbe,0xc4,0xa1,0x05}
    #define DEFAULT_IP_ADDR     {192,168,0,136}
    #define DEFAULT_SUB_MASK    {255,255,255,0}
    #define DEFAULT_GW_ADDR     {192,168,0,1}
    #define DEFAULT_DNS_ADDR    {8,8,8,8}
    
    /* 定义该宏则表示使用自动协商模式,取消则设置为100M全双工模式 */
    #define USE_AUTONEGO
    
    /* 定义该宏则表示在初始化网络信息时设置DHCP */
    //#define USE_DHCP
    
    extern SPI_HandleTypeDef W5500_SPI_HANDLE;
    
    void w5500_network_info_show(void);
    int w5500_init(void);
    
    #endif
    
    

    5.3. 编写c文件

    首先包含头文件:

    #include "w5500_port_hal.h"
    

    5.3.1. SPI驱动接口实现

    接着用HAL库实现W5500驱动所需要的8个SPI函数指针的具体函数:

    /**
     * @brief   enter critical section
     * @param   none
     * @return  none
     */
    static void w5500_cris_enter(void)
    {
        __set_PRIMASK(1);
    }
    
    /**
     * @brief   exit critical section
     * @param   none
     * @return  none
     */
    static void w5500_cris_exit(void)
    {
        __set_PRIMASK(0);
    }
    
    /**
     * @brief   select chip
     * @param   none
     * @return  none
     */
    static void w5500_cs_select(void)
    {
        HAL_GPIO_WritePin(W5500_CS_PORT, W5500_CS_PIN, GPIO_PIN_RESET);
    }
    
    /**
     * @brief   deselect chip
     * @param   none
     * @return  none
     */
    static void w5500_cs_deselect(void)
    {
        HAL_GPIO_WritePin(W5500_CS_PORT, W5500_CS_PIN, GPIO_PIN_SET);
    }
    
    /**
     * @brief   read byte in SPI interface
     * @param   none
     * @return  the value of the byte read
     */
    static uint8_t w5500_spi_readbyte(void)
    {
        uint8_t value;
        
        if (HAL_SPI_Receive(&W5500_SPI_HANDLE, &value, 1, 1000) != HAL_OK) {
            value = 0;
        }
        
        return value;
    }
    
    /**
     * @brief   write byte in SPI interface
     * @param   wb  the value to write
     * @return  none
     */
    static void w5500_spi_writebyte(uint8_t wb)
    {
        HAL_SPI_Transmit(&W5500_SPI_HANDLE, &wb, 1, 1000);
    }
    
    /**
     * @brief   burst read byte in SPI interface
     * @param   pBuf    pointer of data buf
     * @param   len     number of bytes to read
     * @return  none
     */
    static void w5500_spi_readburst(uint8_t* pBuf, uint16_t len)
    {
        if (!pBuf) {
            return;
        }
        
        HAL_SPI_Receive(&W5500_SPI_HANDLE, pBuf, len, 1000);
    }
    
    /**
     * @brief   burst write byte in SPI interface
     * @param   pBuf    pointer of data buf
     * @param   len     number of bytes to write
     * @return  none
     */
    static void w5500_spi_writeburst(uint8_t* pBuf, uint16_t len)
    {
        if (!pBuf) {
            return;
        }
        
        HAL_SPI_Transmit(&W5500_SPI_HANDLE, pBuf, len, 1000);
    }
    
    /**
     * @brief   hard reset
     * @param   none
     * @return  none
     */
    static void w5500_hard_reset(void)
    {
        HAL_GPIO_WritePin(W5500_RST_PORT, W5500_RST_PIN, GPIO_PIN_RESET);
        HAL_Delay(50);
        HAL_GPIO_WritePin(W5500_RST_PORT, W5500_RST_PIN, GPIO_PIN_SET);
        HAL_Delay(10);
    }
    

    5.3.2. 芯片操作实现

    基于官方驱动库编写芯片初始化函数,并设置socket的发送和接收缓冲大小(默认2KB):

    /**
     * @brief   Initializes WIZCHIP with socket buffer size
     * @param   none
     * @return  errcode
     * @retval  0   success
     * @retval  -1  fail
     */
    static int w5500_chip_init(void)
    {
        /* default size is 2KB */
        
        return wizchip_init(NULL, NULL);
    }
    

    再编写硬件PHY配置函数,比如工作模式、速率,以及是否协商等配置:

    自动协商功能需要在上电前连接好网线至路由器,手动配置模式不需要。

    /**
     * @brief   set phy config if autonego is disable
     * @param   none
     * @return  none
     */
    static void w5500_phy_init(void)
    {
    #ifdef USE_AUTONEGO
        // no thing to do
    #else
        wiz_PhyConf conf;
        
        conf.by = PHY_CONFBY_SW;
        conf.mode = PHY_MODE_MANUAL;
        conf.speed = PHY_SPEED_100;
        conf.duplex = PHY_DUPLEX_FULL;
        
        wizphy_setphyconf(&conf);
    #endif
    }
    

    再编写配置和打印网络信息函数:

    /**
     * @brief   initializes the network infomation
     * @param   none
     * @return  none
     */
    static void w5500_network_info_init(void)
    {
        wiz_NetInfo info;
        
        uint8_t mac[6] = DEFAULT_MAC_ADDR;
        uint8_t ip[4] = DEFAULT_IP_ADDR;
        uint8_t sn[4] = DEFAULT_SUB_MASK;
        uint8_t gw[4] = DEFAULT_GW_ADDR;
        uint8_t dns[4] = DEFAULT_DNS_ADDR;
        
        memcpy(info.mac, mac, 6);
        memcpy(info.ip, ip, 4);
        memcpy(info.sn, sn, 4);
        memcpy(info.gw, gw, 4);
        memcpy(info.dns, dns, 4);
        
    #ifdef USE_DHCP
        info.dhcp = NETINFO_DHCP;
    #else
        info.dhcp = NETINFO_STATIC;
    #endif
        
        wizchip_setnetinfo(&info);
    }
    
    /**
     * @brief   read and show the network infomation
     * @param   none
     * @return  none
     */
    void w5500_network_info_show(void)
    {
        wiz_NetInfo info;
        
        wizchip_getnetinfo(&info);
        
        printf("w5500 network infomation:\r\n");
        printf("  -mac:%d:%d:%d:%d:%d:%d\r\n", info.mac[0], info.mac[1], info.mac[2], 
                info.mac[3], info.mac[4], info.mac[5]);
        printf("  -ip:%d.%d.%d.%d\r\n", info.ip[0], info.ip[1], info.ip[2], info.ip[3]);
        printf("  -sn:%d.%d.%d.%d\r\n", info.sn[0], info.sn[1], info.sn[2], info.sn[3]);
        printf("  -gw:%d.%d.%d.%d\r\n", info.gw[0], info.gw[1], info.gw[2], info.gw[3]);
        printf("  -dns:%d.%d.%d.%d\r\n", info.dns[0], info.dns[1], info.dns[2], info.dns[3]);
        
        if (info.dhcp == NETINFO_DHCP) {
            printf("  -dhcp_mode: dhcp\r\n");
        } else {
            printf("  -dhcp_mode: static\r\n");
        }
    }
    

    最后编写w5500初始化函数:

    /**
     * @brief   w5500 init
     * @param   none
     * @return  errcode
     * @retval  0   success
     * @retval  -1  chip init fail
     */
    int w5500_init(void)
    {
        /* W5500 hard reset */
        w5500_hard_reset();
        
        /* Register spi driver function */
        reg_wizchip_cris_cbfunc(w5500_cris_enter, w5500_cris_exit);
        reg_wizchip_cs_cbfunc(w5500_cs_select, w5500_cs_deselect);
        reg_wizchip_spi_cbfunc(w5500_spi_readbyte, w5500_spi_writebyte);
        reg_wizchip_spiburst_cbfunc(w5500_spi_readburst, w5500_spi_writeburst);
    
        /* socket buffer size init */
        if (w5500_chip_init() != 0) {
            return -1;
        }
        
        /* phy init */
        w5500_phy_init();
        
        /* network infomation init */
        w5500_network_info_init();
        
        /* show network infomation */
        w5500_network_info_show();
        
        return 0;
    }
    

    5.3. 测试W5500初始化

    在main.c中包含头文件:

    #include "w5500_port_hal.h"
    

    在main函数中测试初始化函数:

    /* USER CODE BEGIN 2 */
     printf("W5500 test on BearPi board by Mculover666\r\n");
     
     int ret;
     ret = w5500_init();
     if (ret != 0) {
       printf("w5500 init fail, ret is %d\r\n", ret);
     } else {
       printf("w5500 init success\r\n");
     }
    
     /* USER CODE END 2 */
    

    编译,下载,暂不运行。

    因为使用的是自动协商模式,确保W5500网线连接至路由器,然后上电运行,串口日志如下:

    确保windows主机和开发板连接至同一个路由器(或者同一网段之下),ping一下开发板测试:

    6. W5500的Socket测试

    W5500官方驱动库中实现了标准Socket API,在socket.h和socket.c中,可以直接调用编写TCP或者UDP测试程序。

    W5500官方驱动库中也提供了一个Socket的使用案例,其中包括TCP服务端、TCP客户端、UDP服务端的回环测试,在application/loopback文件夹中:

    本文接下来将进行TCP客户端的回环测试。

    6.1. 开启TCP服务器

    在电脑上开启网络调试助手,建立一个TCP server,监听本机8000端口:

    6.2. 添加loopback测试文件

    在MDK中添加c文件:

    添加头文件路径:

    6.3. 调用loopback测试函数

    在main函数的开始创建变量:

    /* USER CODE BEGIN 1 */
    int ret;
    uint8_t destip[4] = {192, 168, 0, 100};
    uint16_t destport = 8000;
    /* USER CODE END 1 */
    

    然后在while循环中调用:

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
      /* USER CODE END WHILE */
    
      /* USER CODE BEGIN 3 */
      ret = loopback_tcpc(0, buffer, destip, destport);
      if (ret != 1) {
          printf("loopback_tcpc err is %d\r\n", ret);
      }
    }
    /* USER CODE END 3 */
    

    6.4. 测试结果

    编译、下载到开发板中运行,串口日志如下:

    在网络调试助手向开发板发送消息,会收到开发板发回的消息:

    若开发板提示连接超时,无法连接TCP服务器,应当检查是否关闭windows网络防火墙。

    更多精彩文章及资源,请关注我的微信公众号:『mculover666』。

    mark

    展开全文
  • W5500以太网原理图.pdf

    2020-03-11 16:51:56
    使用的主控芯片是STM32F103,W5500模块以太网参考电路原理图(全),给硬件设计师们一个参考,可以照我这个直接画的。
  • w5500 以太网芯片资料

    2015-03-26 10:15:06
    w5500 datasheet 和 官方模块原理图2份
  • STM32上移植MQTT协议使用W5500以太网芯片连接阿里云前言正题核心代码结论 前言 有机会做这次项目很开心,学到了很多东西,但刚开始的时候是真的从零开始,网上找的资料都大相径庭,很多代码都有问题,而且把别人做的...
  • 基于STM32 W550的网络通信,包含TCP server client, NTFS
  • 提供以太网w5500相应的CAE原理图,方便硬件工程师借鉴,以此提高效率,此原理图本人亲测并调试成功。
  • 利尔达近期推出工控解决方案,串口转以太网模块LSD1ES-W5500_S2E0,模块基于WIZnet-W5500
  • 具有W5500以太网的ESP8266作为ESP-Now节点的网关运行。 包含节点演示代码。 更多信息 提供了有关此项目的更多信息。 组件 此存储库分为两部分,网关代码(ESP-Now_Gateway)和独立传感器节点的演示/执行程序代码...
  • 前两天世伟兄发了一篇RJ45以太网模块的技术分享文章,用的是W5500以太网模块,他也将他的学习成果和实验共享到我们的私聊小蜜圈里,这是他分享的文章,链接如下:STM32CubeMX系列 ...

    前两天世伟兄发了一篇RJ45以太网模块的技术分享文章,用的是W5500以太网模块,他也将他的学习成果和实验共享到我们的私聊小蜜圈里,这是他分享的文章,链接如下:

    STM32CubeMX系列 | 使用小熊派硬件SPI驱动W5500以太网模块

    最近我也在用类似的模块,但我选的这个模块更简单,没有W5500那么复杂,它就是峰汇物联开发的一款ETH-01串口以太网模块,外观如下:

    1、硬件管脚说明

    2、STM32CubeMX配置

    以下根据目前需要配置为TCP客户端模式,方便后面与云平台通信:

    2.1、时钟配置

    2.2、调试接口配置

    2.3、调试串口配置

    2.4、网口模块配置

    网口模块通信串口配置如下,这里用的是USART3:

    然后采用串口+DMA的方式来处理。

    以下是读TCP状态的IO,配置为上拉输入模式,用于监测网卡是否已经连接服务器

    下是配置模式IO,当输出电平为低时为指令配置模式,当输出电平为高时为数据透传模式:

    2.5、调试灯配置

    2.6、生成工程

    3、软件编程

    由于官方没有提供MCU的例程,所以只能从头到尾自己写啦,由于篇幅原因,这里仅分享其中一部分代码,完整工程请从我的码云上clone获取,以下根据目前需要配置为TCP客户端模式,方便后面与云平台通信:

    3.1、串口指令配置模块之写命令操作

    命令头1

    命令头2

    命令码

    数据

    0x57

    0xAB



    由于需要进行TCP传输,所以只设置红框圈起来的这几个指令就好了,还有一个更新指令到EEPROM的在手册示例里出现。

    根据要求,简单实现如下函数(暂时不优化,先保证能用即可):

    rj45_eth.h头文件实现如下:

    #ifndef __RJ45_ETH_H
    #define __RJ45_ETH_H
    #include "main.h"
    
    #define UART_NNUM      USART3
    #define UART_PORT      &huart3
    #define RJ45_CONFIG_PORT  GPIOC
    #define RJ45_CONFIG_PIN     GPIO_PIN_9
    
    #define RJ45_READ_TCP_STATUS_PORT   GPIOA
    #define RJ45_READ_TCP_STATUS_PIN     GPIO_PIN_8
    
    #define RJ45_RXBUFFER_SIZE 1024
    #define RJ45_TXBUFFER_SIZE 1024
    
    #define NR_RJ45(x)  (sizeof(x)/sizeof(x[0]))
    #define Delay_ms(x) HAL_Delay(x)
    #define ACK_OK 0
    #define ACK_TIMEOUT 1
    
    typedef struct
    {
        __IO uint8_t  BufferReady ;
        uint8_t  RJ45TxBuffer[RJ45_TXBUFFER_SIZE];
        uint8_t  RJ45RxBuffer[RJ45_RXBUFFER_SIZE];
    } RJ45HandleTypeDef;
    extern RJ45HandleTypeDef RJ45r_Handler ;
    
    typedef struct _DEVICEPORT_CONFIG
    {
        uint8_t  dataMode;  /* 数据模式:0:命令模式 1:透传模式*/
        uint8_t  bNetMode;    /* 网络工作模式: 0: TCP SERVER;1: TCP CLENT; 2: UDP SERVER 3:UDP CLIENT; */
        uint8_t  gDesIP[4];   /* 目的IP地址 */
        uint16_t gNetPort;    /* 目的端口号 */
        uint8_t  bMacAddr[4]; /* 芯片MAC地址*/
        __IO uint8_t tcp_status ; /*服务器连接状态*/
    } DevicePortConfigS;
    extern DevicePortConfigS Deice_Para_Handledef ;
    
    
    /**********************写指令函数*************************/
    /*使能RJ45配置模式*/
    void Enable_RJ45_Config_Mode(void);
    /*RJ45设置模式*/
    uint8_t RJ45_Set_Mode(uint8_t mode, uint16_t delay_ms);
    /*设置模块目的端口号*/
    uint8_t Set_Module_Gobal_Port_Number(uint16_t number, uint16_t delay_ms);
    /*RJ45设置目标IP*/
    uint8_t Set_Module_Gobal_Ipaddr(uint8_t bit0, uint8_t bit1, uint8_t bit2, uint8_t bit3, uint16_t delay_ms);
    
    /*更新配置参数到EEPROM*/
    uint8_t Update_Config_Para_To_EEPROM(uint16_t delay_ms);
    /*执行配置参数*/
    uint8_t Runing_Config_Para_To_EEPROM(uint16_t delay_ms);
    /*配置RJ45模块参数*/
    uint8_t Config_RJ45_Module_Para(void);
    /**********************写指令函数*************************/
    
    /**********************读指令函数*************************/
    /*获取芯片工作模式*/
    void Get_RJ45_Chip_Work_Mode(uint16_t delay_ms);
    /*获取芯片目的IP地址*/
    void Get_RJ45_Chip_Gobal_Ipaddr(uint16_t delay_ms);
    /*获取芯片目的端口号*/
    void Get_RJ45_Chip_Gobal_Port_Number(uint16_t delay_ms);
    /*获取芯片Mac地址*/
    void Get_RJ45_Chip_Mac_Addr(uint16_t delay_ms);
    /*获取RJ45模块参数*/
    uint8_t Get_RJ45_Module_Config_Para(void);
    /**********************读指令函数*************************/
    
    /*使能RJ45配置模式*/
    void Enable_RJ45_Config_Mode(void);
    /*失能RJ45配置模式*/
    void Disable_RJ45_Config_Mode(void);
    /*检测TCP状态,返回1则为未连接,返回0则已连接*/
    
    /*进入数据透传模式*/
    uint8_t Enter_Data_Penetrate_Mode(void);
    /*退出数据透传模式*/
    uint8_t Quit_Data_Penetrate_Mode(void);
    //RJ45发送网络透传数据函数,必须在透传模式下使用
    void RJ45_Send_NetWork_Penetrate_Data(char* fmt, ...);
    uint8_t Check_TCP_Status(void);
    
    #endif //__RJ45_ETH_H
    

    以设置模式为例编写函数:

    /*使能RJ45配置模式*/
    void Enable_RJ45_Config_Mode(void)
    {
      /*关闭空闲中断,此时不接收非配置模式的数据,只接收模块本身指令收发的回复数据*/
      __HAL_UART_DISABLE_IT(UART_PORT, UART_IT_IDLE);
        HAL_GPIO_WritePin(RJ45_CONFIG_PORT, RJ45_CONFIG_PIN, GPIO_PIN_RESET);
    }
    
    /*使能DMA,清除数据包*/
    static void Enable_And_Clear_Data_Packet(void)
    {
        HAL_UART_DMAStop(UART_PORT);
        memset(RJ45r_Handler.RJ45TxBuffer, 0, RJ45_TXBUFFER_SIZE);
        memset(RJ45r_Handler.RJ45RxBuffer, 0, RJ45_RXBUFFER_SIZE);
        HAL_UART_Receive_DMA(UART_PORT, RJ45r_Handler.RJ45RxBuffer, RJ45_RXBUFFER_SIZE);
    }
    
    /*0 成功  其他失败*/
    static uint8_t RJ45_Check_Cmd_Ack(uint8_t ack)
    {
        if(RJ45r_Handler.RJ45RxBuffer[0] == ack)
            return 0;
    
        return 1;
    }
    
    /*RJ45设置模式*/
    uint8_t RJ45_Set_Mode(uint8_t mode, uint16_t delay_ms)
    {
        uint8_t Res = 0 ;
        Enable_And_Clear_Data_Packet();
        RJ45r_Handler.RJ45TxBuffer[0] = 0x57 ;
        RJ45r_Handler.RJ45TxBuffer[1] = 0xab ;
        RJ45r_Handler.RJ45TxBuffer[2] = 0x10 ;
        RJ45r_Handler.RJ45TxBuffer[3] = mode ;
        wifi_uart_write_data( RJ45r_Handler.RJ45TxBuffer, 4);
    
        while(delay_ms--)
        {
            Res = RJ45_Check_Cmd_Ack(0xAA) ;
    
            if(0 == Res)
                return 0 ;
    
            Delay_ms(1);
        }
    
        return ACK_TIMEOUT ;
    }
    

    在调用如上设置指令前,先要将配置引脚拉低,然后开启DMA接收,接下来按照通信协议要求将对应的格式填入到发送Buffer,然后调用wifi_uart_write_data函数将协议数据通过串口发给模块,在一定超时延时以后,需要检测DMA接收缓存区是否有协议回复AA,如果有则表示该指令设置成果,这样就完成了写数据的过程,其它指令也是类似的,我们只需要照着手册实现即可。

    3.2、串口指令配置模块之读命令操作

    命令1

    命令头2

    命令码

    0x57

    0xAB


    读命令比写命令要简洁许多,查看手册主要支持以下指令:

    同样的,由于例程需要进行TCP传输,所以只实现红框圈起来的这几个指令就好了。

    以获取芯片工作模式、获取芯片目的IP地址为例,实现如下函数:

    /*获取芯片工作模式*/
    void Get_RJ45_Chip_Work_Mode(uint16_t delay_ms)
    {
        Enable_RJ45_Config_Mode();
        Enable_And_Clear_Data_Packet();
        RJ45r_Handler.RJ45TxBuffer[0] = 0x57 ;
        RJ45r_Handler.RJ45TxBuffer[1] = 0xab ;
        RJ45r_Handler.RJ45TxBuffer[2] = 0x60 ;
        wifi_uart_write_data( RJ45r_Handler.RJ45TxBuffer, 3);
        Delay_ms(delay_ms);
        Deice_Para_Handledef.bNetMode = RJ45r_Handler.RJ45RxBuffer[0];
    }
    
    /*获取芯片目的IP地址*/
    void Get_RJ45_Chip_Gobal_Ipaddr(uint16_t delay_ms)
    {
        Enable_RJ45_Config_Mode();
        Enable_And_Clear_Data_Packet();
        RJ45r_Handler.RJ45TxBuffer[0] = 0x57 ;
        RJ45r_Handler.RJ45TxBuffer[1] = 0xab ;
        RJ45r_Handler.RJ45TxBuffer[2] = 0x65 ;
        wifi_uart_write_data( RJ45r_Handler.RJ45TxBuffer, 3);
        Delay_ms(delay_ms);
        Deice_Para_Handledef.gDesIP[0] = RJ45r_Handler.RJ45RxBuffer[0] ;
        Deice_Para_Handledef.gDesIP[1] = RJ45r_Handler.RJ45RxBuffer[1] ;
        Deice_Para_Handledef.gDesIP[2] = RJ45r_Handler.RJ45RxBuffer[2] ;
        Deice_Para_Handledef.gDesIP[3] = RJ45r_Handler.RJ45RxBuffer[3] ;
    }
    

    与写命令操作一样,在调用如上读指令前,先要将配置引脚拉低,然后开启DMA接收,接下来按照通信协议要求将对应的格式填入到发送Buffer,然后延时一段时间,直接查看串口缓存区对应数据即可,但是如上写法并不严谨,更严谨的做法是是否判断串口一共回复了多少个字节,然后对每个字节进行校验,如果正确才获取,这里先不考虑优化问题,先保证能用即可,其它读指令函数也是差不多的逻辑,由于篇幅有限,这里就不贴出来了。

    3.3、初始化函数及与服务器通信过程实现

    初始化部分分为配置参数和获取参数两部分,这里我配置的服务器IP和端口号是移动OneNet的,分别实现如下

    /*配置RJ45模块参数*/
    uint8_t Config_RJ45_Module_Para(void)
    {
        uint8_t ret = 1;
        Enable_RJ45_Config_Mode();
        Deice_Para_Config_Handledef.bNetMode = 0x01 ;
        ret = RJ45_Set_Mode(Deice_Para_Config_Handledef.bNetMode, 300);
        if(ret != 0)
            return 1;
        Deice_Para_Config_Handledef.gDesIP[0] = 0xB7 ; //180
        Deice_Para_Config_Handledef.gDesIP[1] = 0xE6 ; //230
        Deice_Para_Config_Handledef.gDesIP[2] = 0x28 ; //40
        Deice_Para_Config_Handledef.gDesIP[3] = 0x21 ; //33
        ret = Set_Module_Gobal_Ipaddr(Deice_Para_Config_Handledef.gDesIP[0],  \
        Deice_Para_Config_Handledef.gDesIP[1], Deice_Para_Config_Handledef.gDesIP[2], \
        Deice_Para_Config_Handledef.gDesIP[3], 300);
        if(ret != 0)
            return 2;
        Deice_Para_Config_Handledef.gNetPort = 80 ;  //80
        ret = Set_Module_Gobal_Port_Number(Deice_Para_Config_Handledef.gNetPort, 300);
        if(ret != 0)
            return 3;
        ret = Update_Config_Para_To_EEPROM(300);
        if(ret != 0)
            return 4;
        ret = Runing_Config_Para_To_EEPROM(300);
        if(ret != 0)
            return 5;
        printf("配置RJ45模块参数如下:\n");
        printf("1.配置RJ45模块工作模式:%d\n",Deice_Para_Config_Handledef.bNetMode);
        printf("2.配置RJ45模块目的IP地址:%d.%d.%d.%d\n",Deice_Para_Config_Handledef.gDesIP[0], \
        Deice_Para_Config_Handledef.gDesIP[1],Deice_Para_Config_Handledef.gDesIP[2],
        Deice_Para_Config_Handledef.gDesIP[3]);
        printf("3.配置RJ45模块端口号:%d\n",Deice_Para_Config_Handledef.gNetPort);
        return 0 ;
    }
    
    /*获取RJ45模块参数*/
    uint8_t Get_RJ45_Module_Config_Para(void)
    {
      printf("读取RJ45模块配置参数如下:\n");
     /*读取芯片工作模式*/
      Get_RJ45_Chip_Work_Mode(300);
      printf("1.读取芯片工作模式:%d\n",Deice_Para_Handledef.bNetMode);
      /*读取芯片目的IP地址*/
      Get_RJ45_Chip_Gobal_Ipaddr(300);
      printf("2.读取目的IP地址:%d.%d.%d.%d\n", Deice_Para_Handledef.gDesIP[0], Deice_Para_Handledef.gDesIP[1], \
                   Deice_Para_Handledef.gDesIP[2], Deice_Para_Handledef.gDesIP[3]);
      /*读取芯片目的端口号*/
      Get_RJ45_Chip_Gobal_Port_Number(300);
      printf("3.读取芯片目的端口号:%d\n", Deice_Para_Handledef.gNetPort);
      /*读取芯片Mac地址*/
      Get_RJ45_Chip_Mac_Addr(300);
      printf("4.读取芯片Mac地址:%d.%d.%d.%d\n", Deice_Para_Handledef.bMacAddr[0], Deice_Para_Handledef.bMacAddr[1], \
                   Deice_Para_Handledef.bMacAddr[2], Deice_Para_Handledef.bMacAddr[3]);
      return 0 ;
    }
    

    在配置完毕以后获取模块配置参数,如果获取到的模块配置参数正确,接下来在网口连接正确的情况下即可以进入数据透传模式,就是直接和服务器打交道了,实现如下:

    /*进入数据透传模式*/
    uint8_t Enter_Data_Penetrate_Mode(void)
    {
     /*失能配置模式*/
     Disable_RJ45_Config_Mode();
     /*使能DMA,清除数据包*/
     Enable_And_Clear_Data_Packet();
     /*开启空闲中断,此时接收的是TCP/IP协议收发的数据*/
      __HAL_UART_ENABLE_IT(UART_PORT, UART_IT_IDLE);
     Deice_Para_Config_Handledef.dataMode = 1 ;
     return 0 ;
    }
    

    首先需要将配置引脚拉高,然后使能DMA,开启空闲中断,然后在中断服务函数处编写空闲中断处理逻辑:

    /**
      * @brief This function handles USART3 global interrupt.
      */
    void USART3_IRQHandler(void)
    {
        /* USER CODE BEGIN USART3_IRQn 0 */
        if(RESET != __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart3);
            HAL_UART_DMAStop(&huart3);
            //如果支持RTOS,则数据接收完毕时发送信号量,否则发一个全局变量标志位
            #ifdef CMSIS_RTOS_SUPPORT
            osSemaphoreRelease(reciver_rj45_sem);
            #else
            RJ45r_Handler.BufferReady = 1 ;
            #endif
        }
    
        /* USER CODE END USART3_IRQn 0 */
        HAL_UART_IRQHandler(&huart3);
        /* USER CODE BEGIN USART3_IRQn 1 */
    
        /* USER CODE END USART3_IRQn 1 */
    }
    

    当串口触发了空闲中断,则表示一包数据已经接收完了,这时候就可以将整包数据获取出来,处理获取数据的逻辑在main函数的while循环中实现:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_DMA_Init();
        MX_USART1_UART_Init();
        MX_USART3_UART_Init();
        /* USER CODE BEGIN 2 */
        printf("RJ45 dEMO\n");
        /*配置模块参数*/
        Config_RJ45_Module_Para();
        printf("\r\n");
        Read_Config_Para:
        /*获取RJ45模块参数*/
        Get_RJ45_Module_Config_Para();
        /*进入数据透传模式*/
        Enter_Data_Penetrate_Mode();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
            /*1.检查与远端服务器的连接状况,返回1表示已连接服务器*/
            Deice_Para_Handledef.tcp_status = Check_TCP_Status();
    
            if(1 == Deice_Para_Handledef.tcp_status)
            {
                if(Count_LED_Timer > 500)
                {
                    Count_LED_Timer = 0 ;
                    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
                }
            }
            else
            {
                if(Count_LED_Timer > 500)
                {
                    Count_LED_Timer = 0 ;
                    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
                }
            }
    
            /*2.每1s透传一次数据给服务器*/
            if(Count_Timer >= 10000)
            {
                Count_Timer = 0 ;
                printf("透传数据:\n%s\n", post_http_data);
    
                if(1 == Deice_Para_Handledef.tcp_status)
                {
                    RJ45_Send_NetWork_Penetrate_Data(post_http_data);
                    printf("服务器已连接,发送成功!\n");
                }
                else
                {
                    printf("服务器未连接,发送失败!\n");
                }
            }
    
            /*3.接收服务器下发的数据*/
            if(RJ45r_Handler.BufferReady)
            {
                RJ45r_Handler.BufferReady = 0 ;
                printf("接收网络数据:\n%s\n", RJ45r_Handler.RJ45RxBuffer);
                /*退出透传模式*/
                //Quit_Data_Penetrate_Mode();
                //goto Read_Config_Para ;
                memset(RJ45r_Handler.RJ45RxBuffer, 0, RJ45_RXBUFFER_SIZE);
                HAL_UART_Receive_DMA(UART_PORT, RJ45r_Handler.RJ45RxBuffer, RJ45_RXBUFFER_SIZE);
            }
        }
    
        /* USER CODE END 3 */
    }
    

    通过自己的服务器发送测试协议进行测试,由于这是我私人创建的设备,所以就不将设备ID和api-key公布出来了,结果如下:

    之前写过类似的文章,参考如下即可:

    ESP8266实战贴:使用HTTP POST请求上传数据到公有云OneNet

    上传数据流展示:

    4、项目开源地址

    本节代码已同步到码云的代码仓库中,获取方法如下:

    码云仓库:

    https://gitee.com/morixinguan/bear-pi/tree/master/24.RJ45_ETH-1
    

    获取项目方法:

    git clone https://gitee.com/morixinguan/bear-pi.git
    

    我还将之前做的一些项目以及练习例程在近期内全部上传完毕,与大家一起分享交流,如果有任何问题或者对该项目感兴趣,欢迎加我微信:morixinguan一起交流学习。

    往期精彩

    都说软件架构要分层、分模块,具体应该怎么做(二)

    开源:智能宠物弹射喂食器连载贴之步进电机控制(二)

    U盘容量大小造假技术手段实现之8M变4G(以STM32 SPI_FLASH为例)

    手把手教你在STM32上实现OLED视频播放(很简单也很硬很肝!)

    一些值得被定义为常用C语言头文件库的漂亮宏定义(值得收藏,以备使用参考)

    觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

    展开全文
  • 以太网_W5500模块资料软硬件设计资料+STM32软件工程源码文件: 1-配套程序 2-官方文档_数据手册 W5500与各开发板引脚连接说明 W5500网络扩展板介绍.pdf W5500网络扩展板教程.pdf 串口与多功能调试助手.rar 原理图_...
  • W5500网络模块与SPI总线

    千次阅读 2020-09-21 14:49:09
    (之前用的是另一个模组串口转以太网的,但是不方便的地方就是不能通过屏幕的方式直接修改ip,或者是模式,而且在速度上因为串口转以太网模组要经过一个mcu,速度上比不过spi,所以就有了这篇博文) 先从寄存器和...
  • 这个方案采用的是FPGA+W5500。串口部分利用串口数据收发硬件加速器,充分利用Buff及FiFO资源,从而极大程度上的提高了16串口的数据调度能力。与此同时,网络部分采用ToE技术的W5500,从而极大程度上的降低了系统中断...
  • 最近接触到Arduino模块的开发,并且模块的主要使用场景是机房,因此选择使用以太网W5500模组使得数据能够通过网线稳定而快速地将数据上传到外网。在开发的过程中发现,Arduino模块的库示例代码配套使用的是W5100模块...
  • 利尔达最近推出工控解决方式,串口转以太网模块LSD1ES-W5500_S2E0,模块基于WIZnet-W5500。 同一时候,这也是利尔达科技集团成为WIZnet代理商后,自行推出的第一款基于WIZnet产品的成品解决方式。 嵌入式串口...

空空如也

空空如也

1 2 3 4 5
收藏数 97
精华内容 38
关键字:

w5500以太网模块