[MM32生态]基于MM32F3273移植W5500的ioLibrary实现PING测试

1、MM32F3270简介
MM32F3270系列MCU使用高性能的ARM Cortex-M3为内核的32位微控制器,最高工作频率可达120MHz,内置高速存储器,256KB FLASH & 128KB SRAM,丰富的 I/O 端口和外设连接到外部总线。本产品包含多达3个12位的ADC、2个比较器、 2个16 位通用定时器、2个32 位通用定时器、2个16 位基本定时器和2个16位高级定时器。还包含标准的通信接口:2 个I2C接口、3个I2S接口、3个SPI 接口、1个USB OTG全速接口、1个CAN接口、1个SDIO接口和8个UART接口。



2、W5500简介
W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。 W5500集成了TCP/IP协议栈,10/100M以太网数据链路层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。W5500内置的全硬件TCP/IP协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及 PPPoE协议。W5500还内嵌了32K字节片上缓存以供以太网包处理。如果使用W5500,只需要一些简单的Socket编程就轻松能实现以太网应用。这将会比其他嵌入式以太网方案更加快捷、简便。
 



3、硬件原理图
我们直接购买了一块使用STM32F103C8T6作为主控MCU的W5500开发板。对于MM32F3270系列MCU支持LQFP48/64/100/144四种封装形式,与STM32F103系列在硬件上能够做到完全的PIN TO PIN兼容,所以我们将板载的STM32F103C8T6直接替换成MM32F3270G6P,原理图如下所示:


通过如上原理图获知,PC13控制LED发光二极管、PA0作为输入按键检测端口引脚、PA9/PA10作为UART串口功能,连接到了RS232芯片上,与DB9相连接、最后就是MM32F3273与W5500连接的部分了,使用PA2作为W5500的硬件复位控制引脚、使用PA3作为W5500的中断输入检测引脚、使用SPI1(PA4/PA5/PA6/PA7)与W5500的SPI通讯接口相连接,实现数据交互。

4、程序设计
4.1.下载MM32F3270系列MCU的官方库函数与例程:
https://www.mindmotion.com.cn/products/mm32mcu/performance_line/mm32f_performance/mm32f3270/

4.2.下载W5500官方的库函数与例程:
https://github.com/Wiznet/ioLibrary_Driver

4.3.初始化板载资源配置(KEY、LED、UART、SysTick等)

复制
#define __PLATFORM_C



#include "platform.h"



volatile uint32_t SysTick_DelayTick = 0;



void PLATFORM_InitSysTick(void)

{

    RCC_ClocksTypeDef  RCC_Clocks;

    RCC_GetClocksFreq(&RCC_Clocks);



    if (SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000))

    {

        while (1)

        {

        }

    }



    NVIC_SetPriority(SysTick_IRQn, 0x0);

}



void SysTick_DelayMS(uint32_t Tick)

{

    SysTick_DelayTick = Tick;



    while (SysTick_DelayTick)

    {

    }

}



void PLATFORM_InitConsole(uint32_t Baudrate)

{

    GPIO_InitTypeDef GPIO_InitStruct;

    UART_InitTypeDef UART_InitStruct;



    RCC_APB2PeriphClockCmd(RCC_APB2ENR_UART1, ENABLE);



    UART_StructInit(&UART_InitStruct);

    UART_InitStruct.BaudRate      = Baudrate;

    UART_InitStruct.WordLength    = UART_WordLength_8b;

    UART_InitStruct.StopBits      = UART_StopBits_1;

    UART_InitStruct.Parity        = UART_Parity_No;

    UART_InitStruct.HWFlowControl = UART_HWFlowControl_None;

    UART_InitStruct.Mode          = UART_Mode_Tx;

    UART_Init(UART1, &UART_InitStruct);



    UART_Cmd(UART1, ENABLE);



    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);



    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);



    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_9;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

}



int fputc(int ch, FILE *f)

{

    UART_SendData(UART1, (uint8_t)ch);



    while (RESET == UART_GetFlagStatus(UART1, UART_FLAG_TXEPT))

    {

    }



    return (ch);

}



void PLATFORM_InitKEY(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;



    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);



    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_0;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

}



void PLATFORM_InitLED(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;



    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOC, ENABLE);



    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_13;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOC, &GPIO_InitStruct);



    GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);

}



void PLATFORM_PrintInfo(void)

{

    RCC_ClocksTypeDef RCC_Clocks;



    printf("\r\n");

    printf("\r\nMCU : MM32F3273G6P");

    printf("\r\n");



    switch (RCC->CFGR & RCC_CFGR_SWS)

    {

        case 0x00:

            printf("\r\nHSI used as system clock source");

            break;



        case 0x04:

            printf("\r\nHSE used as system clock source");

            break;



        case 0x08:

            if (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC)

            {

                printf("\r\nPLL (clocked by HSE) used as system clock source");

            }

            else

            {

                printf("\r\nPLL (clocked by HSI) used as system clock source");

            }



            break;



        case 0x0C:

            printf("\r\nLSI used as system clock source");

            break;



        default:

            break;

    }



    RCC_GetClocksFreq(&RCC_Clocks);



    printf("\r\n");

    printf("\r\nSYSCLK Frequency : %7.3f MHz", (double)RCC_Clocks.SYSCLK_Frequency / (double)1000000.0);

    printf("\r\nHCLK   Frequency : %7.3f MHz", (double)RCC_Clocks.HCLK_Frequency   / (double)1000000.0);

    printf("\r\nPCLK1  Frequency : %7.3f MHz", (double)RCC_Clocks.PCLK1_Frequency  / (double)1000000.0);

    printf("\r\nPCLK2  Frequency : %7.3f MHz", (double)RCC_Clocks.PCLK2_Frequency  / (double)1000000.0);

    printf("\r\n");

}



void PLATFORM_Init(void)

{

    PLATFORM_InitSysTick();



    PLATFORM_InitConsole(115200);



    PLATFORM_InitKEY();



    PLATFORM_InitLED();



    PLATFORM_PrintInfo();

}


4.4.初始化MM32F3273与W5500的控制IO(RST、INT)
对W5500硬件RST的控制,低电平的时候对W5500进行硬件复位,低电平需要持续500us以上;对于INT引脚,如果没有使用到,可以忽略不配置,如果使用到了,需要配置为EXTI,通过EXTI中断来及时的响应W5500的反馈,具体配置如下所示:

复制
void W5500_InitGPIO(void)

{

    EXTI_InitTypeDef EXTI_InitStruct;

    GPIO_InitTypeDef GPIO_InitStruct;

    NVIC_InitTypeDef NVIC_InitStruct;



    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);



    /* RST */

    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_2;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOA, &GPIO_InitStruct);



    /* W5500 Hardware Reset */

    GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET);

    SysTick_DelayMS(5);

    GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET);

    SysTick_DelayMS(5);



    /* INT */

    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_3;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

    GPIO_Init(GPIOA, &GPIO_InitStruct);



    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource3);



    EXTI_StructInit(&EXTI_InitStruct);

    EXTI_InitStruct.EXTI_Line    = EXTI_Line3;

    EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Interrupt;

    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;

    EXTI_InitStruct.EXTI_LineCmd = ENABLE;

    EXTI_Init(&EXTI_InitStruct);



    NVIC_InitStruct.NVIC_IRQChannel = EXTI3_IRQn;

    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;

    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;

    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStruct);

}


4.5.初始化MM32F3273与W5500之间的SPI通讯配置

复制
void W5500_InitSPI1(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;

    SPI_InitTypeDef  SPI_InitStruct;



    RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1, ENABLE);



    SPI_StructInit(&SPI_InitStruct);

    SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;

    SPI_InitStruct.SPI_DataSize  = SPI_DataSize_8b;

    SPI_InitStruct.SPI_DataWidth = 8;

    SPI_InitStruct.SPI_CPOL      = SPI_CPOL_Low;

    SPI_InitStruct.SPI_CPHA      = SPI_CPHA_1Edge;

    SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

    SPI_InitStruct.SPI_FirstBit  = SPI_FirstBit_MSB;

    SPI_Init(SPI1, &SPI_InitStruct);



    SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Rx);

    SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);



    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);



    GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_5);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_5);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_5);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_5);



    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOA, &GPIO_InitStruct);



    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_6;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPU;

    GPIO_Init(GPIOA, &GPIO_InitStruct);



    SPI_Cmd(SPI1, ENABLE);

}


4.6.实现MM32F3273的SPI数据读写函数,并注册为W5500的接口函数
W5500的接口注册函数有如下几个:

复制
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));

void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));

void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb));

void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb));

void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len));

因为我们使用的是SPI接口与W5500进行通讯,所以可以仅实现SPI部分的注册函数即可,如下:

复制
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));

void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb));

void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len));

其中reg_wizchip_cs_cbfunc函数是对SPI CS的操作,reg_wizchip_spi_cbfunc函数是注册单字节进行SPI读写操作,reg_wizchip_spiburst_cbfunc函数是注册多字节进行SPI读写操作,reg_wizchip_spi_cbfunc和reg_wizchip_spiburst_cbfunc只需要选其一进行进行函数注册即可。具体实现如下所示:

复制
void W5500_SPI_CS_Select(void)

{

    SPI_CSInternalSelected(SPI1, ENABLE);

}



void W5500_SPI_CS_Deselect(void)

{

    SPI_CSInternalSelected(SPI1, DISABLE);

}



uint8_t W5500_SPI_ReadByte(void)

{

    SPI_SendData(SPI1, 0x00);



    while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_TXEPT))

    {

    }



    while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_RXAVL))

    {

    }



    return (SPI_ReceiveData(SPI1));

}



void W5500_SPI_WriteByte(uint8_t Data)

{

    SPI_SendData(SPI1, Data);



    while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_TXEPT))

    {

    }



    while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_RXAVL))

    {

    }



    SPI_ReceiveData(SPI1);

}



void W5500_SPI_ReadBurst(uint8_t *Buffer, uint16_t Length)

{

    for (uint16_t i = 0; i < Length; i++)

    {

        SPI_SendData(SPI1, 0x00);



        while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_TXEPT))

        {

        }



        while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_RXAVL))

        {

        }



        Buffer[i] = SPI_ReceiveData(SPI1);

    }

}



void W5500_SPI_WriteBurst(uint8_t *Buffer, uint16_t Length)

{

    for (uint16_t i = 0; i < Length; i++)

    {

        SPI_SendData(SPI1, Buffer[i]);



        while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_TXEPT))

        {

        }



        while (RESET == SPI_GetFlagStatus(SPI1, SPI_FLAG_RXAVL))

        {

        }



        SPI_ReceiveData(SPI1);

    }

}


4.7.对W5500进行初始化配置

复制
#include "socket.h"

#include "wizchip_conf.h"



int main(void)

{

    PLATFORM_Init();



    W5500_InitGPIO();

    W5500_InitSPI1();



    reg_wizchip_cris_cbfunc(NULL, NULL);

    reg_wizchip_cs_cbfunc(W5500_SPI_CS_Select, W5500_SPI_CS_Deselect);

    reg_wizchip_spiburst_cbfunc(W5500_SPI_ReadBurst, W5500_SPI_WriteBurst);



    printf("\r\nW5500 VERSIONR : 0x%02X", WIZCHIP_READ(VERSIONR));



    if (ctlwizchip(CW_INIT_WIZCHIP, NULL) == -1)

    {

        printf("\r\nW5500 Initialized Fail.");

    }

    else

    {

        printf("\r\nW5500 Initialized Success.");

    }



    wiz_PhyConf PhyConf;



    PhyConf.by     = PHY_CONFBY_SW;

    PhyConf.mode   = PHY_MODE_MANUAL;

    PhyConf.speed  = PHY_SPEED_100;

    PhyConf.duplex = PHY_DUPLEX_FULL;



    ctlwizchip(CW_SET_PHYCONF, &PhyConf);



    wiz_NetInfo NetInfo;



    uint8_t mac[6] = {0x00, 0xf1, 0xbe, 0xc4, 0xa1, 0x05};

    uint8_t ip[4]  = {192, 168, 103, 136};

    uint8_t sn[4]  = {255, 255, 255, 0};

    uint8_t gw[4]  = {192, 168, 103, 1};

    uint8_t dns[4] = {8, 8, 8, 8};



    memcpy(NetInfo.mac, mac, sizeof(mac));

    memcpy(NetInfo.ip,  ip,  sizeof(ip));

    memcpy(NetInfo.sn,  sn,  sizeof(sn));

    memcpy(NetInfo.gw,  gw,  sizeof(gw));

    memcpy(NetInfo.dns, dns, sizeof(dns));



    NetInfo.dhcp = NETINFO_STATIC;



    ctlnetwork(CN_SET_NETINFO, &NetInfo);



    wiz_NetInfo info;



    ctlnetwork(CN_GET_NETINFO, &info);



    printf("\r\n");

    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");

    }



    printf("\r\n");



    while (1)

    {

        GPIO_WriteBit(GPIOC, GPIO_Pin_13, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0));

    }

}


5、搭建环境
搭建硬件环境我们除了需要必备的W5500开发板之后,还需要准备一个网络交换机,以及3根网线;硬件连接示意图如下所示:
 


网络交换机的其中一个端口连接以太网、第二个接口连接W5500开发板,第三个接口连接PC电脑。

6、PING测试
打开串口监测软件,监控RS232输入的调试打印信息:
 



通过WIN+R快捷键,打开运行窗口,输入CMD进入终端,在窗口中输入ping 192.168.103.136并回车,查看PING的测试结果:



7、附件
原理图: 

 W5500开发板.PDF (374.67 KB)。
---------------------
作者:芯领域电子科技
链接:https://bbs.21ic.com/icview-3389796-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值