Skip to content

STM32 CubeIDE W5500 initialization Routine

Introduce how to setup W5500 in STM32 CubeIDE.

tonywang_

Published November 02, 2022

STM32 CubeIDE W5500 initialization Routine

Project description

STM32 W5500以太网通讯 

对于内含以太网MAC部分的芯片,可以外部增加以太网PHY芯片和连接器,实现以太网通讯。对于内部没有以太网MAC部分的芯片,通过W5500 S 讯是比较好的方式, 从而STM32F0各低端系列都能实现以太网通讯。采用W5500芯片,可以不占用MCU的 内存 部分做buffer,对于MCU业务逻辑时 MCU和W5500可以通过SPI的DMA方式,实现较快的收发逻辑;W5500最大支持到80Mbps的SPI接口速度,实际情况根据MCU的SPI接口速率和PC 

W5500写读Buffer 的要点笔记

1. 每个SOCKET有自己的写缓冲和读缓冲操作命令/地址,如下: 

在这里插入图片描述

2. 每个SOCKET的写缓冲大小(Sn_TXBUF_SIZE)和读缓冲大小(Sn_RXBUF_SIZE)可调整,写缓冲和读缓冲分离。因为8个socket共享写缓冲 缓冲大小或读缓冲大小不超过16KB。 

3. 写时可进行burst操作。因此首地址的设置,有辅助的信息寄存器: ⑴Sn_TX_FSR : 用于查阅写缓冲区域剩余自由空间,可为Sn_TX_WR和Sn_TX_RD的差值 ⑵Sn_TX_WR : 写缓冲写入的数据指针,指示已经写到的地址 ⑶Sn_TX_RD :写缓冲发送的数据指针,指示发送改到了哪个地址 

4. 读时可进行burst操作。因此首地址的设置,有辅助的信息寄存器: ① Sn_RX_RSR :用于查阅读缓冲剩余的未读取的数据空间大小,可为Sn_RX_WR和Sn_RX_RD的差值 ② Sn_RX_WR :接收数据的边界指针,接收到数据时,指针自动后移,指示前面的部分为已收到的数据。 ③ Sn_RX_RD : 接收数据读取后的边界指针,当进行了接收缓冲区读取后,该指针手动升级到已读取的缓冲区后的地址 

5. 写缓冲和读缓冲都是循环FIFO,因此越界后翻到0地址继续进行。

需要注意的情况: 

1. 是否有不断开连接方式可以将缓冲区复位? 答:不能,且Socket端口打开和连接后的初始化地址也不是0地址,且每次初始化地址还不同。 

2. 越界情况的处理?答:循环缓冲区,控制写入时序,否则会产生对还未发送数据区域的覆盖。 发送数据操作逻辑: 1. 通过读取Sn_TX_WR寄存器获得当前的写缓冲区指针,通过读取Sn_TX_RD寄存器获得当前的写缓冲区发送数据指针,初始时二者一致表示没有 2. 通过从Sn_TX_WR寄存器得到的发送缓冲区地址,写入要发送的数据,发送写数据命令和写数据之间的时间间隔不能过大,否则W5500接收SP 

3. 向Sn_TX_WR寄存器写入后续发送要达到的发送缓冲区地址,即当前发送缓冲区地址+要发送的字节数。实际上,这个写操作后,Sn_TX_WR寄 到发送缓冲区数据指令发送后,才会更新。 

4. 发送缓冲区数据发送指令,此时Sn_TX_WR寄存器更新,W5500从Sn_TX_RD地址开始发送数据,并实时更新Sn_TX_RD地址,等到Sn_TX_R 相同,则完成并停止发送。 

读数据操作逻辑:

1. 通过读取Sn_RX_RD寄存器得到读缓冲区可读取区域首地址 

2. 通过读取Sn_RX_RSR寄存器得到读缓冲区未读的接收到的数据长度 

3. 通过可读取区域首地址读取读缓冲区里的数据,可小于等于Sn_RX_RSR寄存器里的长度,大于则读到无效数据 

4. 向Sn_RX_RD写入新的可读取区域首地址,为之前的首地址+已读取字节数。但此时Sn_RX_RD还未更新,还需发送下述一条指令进行触发更新 

5. 通过向Socket的命令寄存器(Command Register)发送RECV指令,触发Sn_RX_RD更新,同时Sn_RX_RSR也被更新。 

6. 如果没有更新Sn_RX_RD寄存器指针,则再次收到数据时会继续顺序放置,同时Sn_RX_WR和Sn_RX_RSR继续增加。因此前后不同次接收到的 

实际嵌入式时序控制时,需要接收中断控制和读取W5500内部状态寄存器,进行时序调度。

STM32 W5500访问逻辑设计 

这里设计一个例程,采用STM32H743VIT6连接W5500, 同时实现虚拟串口(VCOM)作为测试辅助: 

1. STM32上电后实现对W5500的配置,并读取特定寄存器以判断访问是否成功 

2. 网络连通后,用TCP测试工具,发送任意数据到STM32, STM32接收到后转发到VCOM;另外STM32将预设的特定数据发送到TCP测试工具。注 单回环。 

STM32CUBEIDE配置 

采用STM32CUBEIDE进行工程配置,选择SPI1作为W5500通讯接口,STM32H743VIT6的SPI1能达到80MHz的速率,但测试环境采用短杜邦线连接 输质量,实测60MHz能够正确响应,因此相应的时钟采用120MHz的2分频实现。 

使能外部8MHz晶振时钟,整体的时钟配置如下,包括了SPI和USB VCOM的部分:

在这里插入图片描述
在这里插入图片描述

SPI1配置,W5500连接所用管脚为: 

PD1: W5500_RST 

PD3: W5500_SCS 

PD5: W5500_INT 

PB3: W5500_SCK 

PB4: W5500_MISO 

PB5: W5500_MOSI

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

W5500访问库函数设计 

这里设计W5500开通两个SOCKET端口,测试中只用到第一个SOCKET端口。 

新建w5500.h文件,代码如下:

/*
* PD1: W5500_RST
* PD3: W5500_SCS
* PD5: W5500_INT
*
* PB3: W5500_SCK
* PB4: W5500_MISO
* PB5: W5500_MOSI
*
*
*/
#ifndef  _W5500_H_
#define  _W5500_H_

#define PY_W5500_RST {HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);HAL_Delay(5);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);HAL_Delay(5);}
#define PY_W5500_CS_EN HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET);
#define PY_W5500_CS_DEN HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET);

void PY_W5500_Config(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t data);
void PY_W5500_Read(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t* data, uint16_t length);
void PY_W5500_Send(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t* data, uint16_t length);
void PY_W5500_TCPSERVER_2SOCKETS(void);
void PY_W5500_SOCKET0_CLEARRECINT(void);

#endif

新建w5500.c文件,代码如下:


#include "stm32h7xx_hal.h"
#include <stdio.h>
#include <string.h>
#include "w5500.h"
#include "spi.h"

void PY_W5500_Config(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t data)
{
extern uint8_t PY_SPIDMA__Status;
extern uint8_t* PY_CMD_Seg;


PY_W5500_CS_EN
PY_SPIDMA__Status=1;
PY_CMD_Seg[0]=ah;PY_CMD_Seg[1]=al;PY_CMD_Seg[2]=ctl|0x04;PY_CMD_Seg[3]=data;
HAL_SPI_Transmit_DMA(&hspi1, PY_CMD_Seg,4);
while(PY_SPIDMA__Status==1) ;
PY_W5500_CS_DEN
HAL_Delay(1);
}

void PY_W5500_Read(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t* data, uint16_t length)
{
extern uint8_t PY_SPIDMA__Status;
extern uint8_t* PY_CMD_Seg;
PY_W5500_CS_EN
PY_SPIDMA__Status=1;
PY_CMD_Seg[0]=ah;PY_CMD_Seg[1]=al;PY_CMD_Seg[2]=ctl&0xfb;
HAL_SPI_Transmit_DMA(&hspi1, PY_CMD_Seg,3);
while(PY_SPIDMA__Status==1) ;

PY_SPIDMA__Status=1;
HAL_SPI_Receive_DMA(&hspi1, data, length);
while(PY_SPIDMA__Status==1) ;

PY_W5500_CS_DEN
}

void PY_W5500_Send(uint8_t ah, uint8_t al, uint8_t ctl, uint8_t* data, uint16_t length)
{
extern uint8_t PY_SPIDMA__Status;
extern uint8_t* PY_CMD_Seg;

    PY_W5500_CS_EN
 PY_SPIDMA__Status=1;
 PY_CMD_Seg[0]=ah;PY_CMD_Seg[1]=al;PY_CMD_Seg[2]=ctl|0x04;
 HAL_SPI_Transmit_DMA(&hspi1, PY_CMD_Seg,3);
 while(PY_SPIDMA__Status==1) ;

 PY_SPIDMA__Status=1;
 HAL_SPI_Transmit_DMA(&hspi1, data, length);
 while(PY_SPIDMA__Status==1) ;
 PY_W5500_CS_DEN
}

 

void PY_W5500_TCPSERVER_2SOCKETS(void)
{
/*
* Only one socket receiving interrupt is opened for cmd recognition. Other interrupt sources are closed. To use polling for Tx status.
*/
extern uint8_t PY_SPIDMA__Status;
extern uint8_t* PY_CMD_Seg;
extern uint8_t* PY_DataR_Seg;
extern uint8_t* PY_DataW_Seg;

//Common register:mode register
PY_W5500_Config(0x00, 0x00, 0x04, 0x00);
//Common register:gateway IP address register
PY_W5500_Config(0x00, 0x01, 0x04, 192); //IP: 192.168.1.252
PY_W5500_Config(0x00, 0x02, 0x04, 168);
PY_W5500_Config(0x00, 0x03, 0x04, 1);
PY_W5500_Config(0x00, 0x04, 0x04, 252);
//Common register:subnet mask register
PY_W5500_Config(0x00, 0x05, 0x04, 255);
PY_W5500_Config(0x00, 0x06, 0x04, 255);
PY_W5500_Config(0x00, 0x07, 0x04, 255);
PY_W5500_Config(0x00, 0x08, 0x04, 0);
//Common register:source hardware address register
PY_W5500_Config(0x00, 0x09, 0x04, 0x00);
PY_W5500_Config(0x00, 0x0a, 0x04, 0x08);
PY_W5500_Config(0x00, 0x0b, 0x04, 0xdc);
PY_W5500_Config(0x00, 0x0c, 0x04, 0x01);
PY_W5500_Config(0x00, 0x0d, 0x04, 0x02);
PY_W5500_Config(0x00, 0x0e, 0x04, 0x03);
//Common register:source IP address register
PY_W5500_Config(0x00, 0x0f, 0x04, 192);
PY_W5500_Config(0x00, 0x10, 0x04, 168);
PY_W5500_Config(0x00, 0x11, 0x04, 1);
PY_W5500_Config(0x00, 0x12, 0x04, 252);
//Common register:interrupt low level interval register
PY_W5500_Config(0x00, 0x13, 0x04, 0x00);
PY_W5500_Config(0x00, 0x14, 0x04, 0x13);
//Common register:(connection) interrupt register
PY_W5500_Config(0x00, 0x15, 0x04, 0x00);
//Common register:(connection) interrupt mask register
PY_W5500_Config(0x00, 0x16, 0x04, 0xf0);
//Common register:(socket)interrupt register
PY_W5500_Config(0x00, 0x17, 0x04, 0x00);
//Common register:(socket) interrupt mask register
PY_W5500_Config(0x00, 0x18, 0x04, 0xc0);
//Common register:retry time-value register
PY_W5500_Config(0x00, 0x19, 0x04, 0x07);
PY_W5500_Config(0x00, 0x1a, 0x04, 0xd0);
//Common register:retry count register
PY_W5500_Config(0x00, 0x1b, 0x04, 0x07);


//Socket 0 register:mode register
PY_W5500_Config(0x00, 0x00, 0x0c, 0x21);
//Socket 0 register:source port number register
PY_W5500_Config(0x00, 0x04, 0x0c, 0x03); //Port:1000
PY_W5500_Config(0x00, 0x05, 0x0c, 0xe8);
//Socket 0 register:maxium segment size register
PY_W5500_Config(0x00, 0x12, 0x0c, 0x05);
PY_W5500_Config(0x00, 0x13, 0x0c, 0xb4);
//Socket 0 register:ip type of service register
PY_W5500_Config(0x00, 0x15, 0x0c, 0x5a);
//Socket 0 register:time to live register
PY_W5500_Config(0x00, 0x16, 0x0c, 64);
//Socket 0 register:rx buffer size register
PY_W5500_Config(0x00, 0x1e, 0x0c, 2);
//Socket 0 register:tx buffer size register
PY_W5500_Config(0x00, 0x1f, 0x0c, 2);
//Socket 0 register:keep alive time register
PY_W5500_Config(0x00, 0x2f, 0x0c, 0x18);

//Socket 1 register:mode register
PY_W5500_Config(0x00, 0x00, 0x2c, 0x21);
//Socket 1 register:source port number register
PY_W5500_Config(0x00, 0x04, 0x2c, 0x07); //Port:2000
PY_W5500_Config(0x00, 0x05, 0x2c, 0xD0);
//Socket 1 register:maxium segment size register
PY_W5500_Config(0x00, 0x12, 0x2c, 0x05);
PY_W5500_Config(0x00, 0x13, 0x2c, 0xb4);
//Socket 1 register:ip type of service register
PY_W5500_Config(0x00, 0x15, 0x2c, 0x5a);
//Socket 1 register:time to live register
PY_W5500_Config(0x00, 0x16, 0x2c, 64);
//Socket 1 register:rx buffer size register
PY_W5500_Config(0x00, 0x1e, 0x2c, 2);
//Socket 1 register:tx buffer size register
PY_W5500_Config(0x00, 0x1f, 0x2c, 2);
//Socket 1 register:keep alive time register
PY_W5500_Config(0x00, 0x2f, 0x2c, 0x18);

//interrupt mask registers
PY_W5500_Config(0x00, 0x16, 0x04, 0x00);
PY_W5500_Config(0x00, 0x18, 0x04, 0x01);
PY_W5500_Config(0x00, 0x2c, 0x0c, 0x04);


//Socket 0 : open
PY_W5500_Config(0x00, 0x01, 0x0c, 0x01);  //open socket
HAL_Delay(10);
PY_W5500_Config(0x00, 0x01, 0x0c, 0x02);  //socket server listening

//PY_W5500_Config(0x00, 0x01, 0x0c, 0x40);

//Socket 1 : open
PY_W5500_Config(0x00, 0x01, 0x2c, 0x01);  //open socket
HAL_Delay(10);
PY_W5500_Config(0x00, 0x01, 0x2c, 0x02);  //socket server listening


}

void PY_W5500_SOCKET0_CLEARRECINT(void)
{
 PY_W5500_Config(0x00, 0x02, 0x0c, 0x04);
}

main.c文件设计 

对于W5500,配置为只有接收数据中断发送到STM32的中断接收管脚(PD5)。STM32收到中断后,读取数据转发到虚拟串口,另外把预设的一组值发送到以太网口。

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>© Copyright (c) 2021 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */
//SPI1 DMA buffer address can't be arranged in the region of 0x20000000 ~ 0x20020000

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "spi.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "w5500.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t PY_W5500_Ver_Addr_SegH=0x00, PY_W5500_Ver_Addr_SegL=0x39;
uint8_t PY_W5500_Ver_Ctrl_Seg=0x00;

uint8_t* PY_CMD_Seg;
uint8_t* PY_DataR_Seg;
uint8_t* PY_DataW_Seg;

uint8_t PY_SPIDMA__Status = 0;

uint8_t cmd=0;

uint8_t rx_addr_h, rx_addr_l;
uint16_t rx_len;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
 /* USER CODE BEGIN 1 */
 PY_CMD_Seg = 0x38000000;
 PY_DataR_Seg = 0x38000004;
 PY_DataW_Seg = 0x30000000;

 /* 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_USB_DEVICE_Init();
 MX_SPI1_Init();
 /* USER CODE BEGIN 2 */
 PY_W5500_RST

 PY_CMD_Seg[0]=PY_W5500_Ver_Addr_SegH;
 PY_CMD_Seg[1]=PY_W5500_Ver_Addr_SegL;
 PY_CMD_Seg[2]=PY_W5500_Ver_Ctrl_Seg;

 PY_DataR_Seg[0]=0; PY_DataR_Seg[1]=0;

 PY_W5500_CS_EN
 PY_SPIDMA__Status=1;
 HAL_SPI_Transmit_DMA(&hspi1, PY_CMD_Seg, 3);
 while(PY_SPIDMA__Status==1) ;
 PY_SPIDMA__Status=1;
 HAL_SPI_Receive_DMA(&hspi1, PY_DataR_Seg, 1);
 while(PY_SPIDMA__Status==1) ;
 PY_W5500_CS_DEN

 if(PY_DataR_Seg[0]!=0x04)
 {
  while(1)
  {
   CDC_Transmit_FS(PY_DataR_Seg, 1);
   HAL_Delay(1000);
  }
 }

 PY_W5500_TCPSERVER_2SOCKETS();
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
  //CDC_Transmit_FS(PY_DataR_Seg, 2);
  HAL_Delay(1000);
  if(cmd==1)
  {
   cmd=0;
   PY_W5500_SOCKET0_CLEARRECINT();

   /*
    * Receiving
    */
   PY_W5500_Read(0x00, 0x28, 0x08, PY_DataR_Seg, 2);
   rx_addr_h=PY_DataR_Seg[0];rx_addr_l=PY_DataR_Seg[1];
   PY_W5500_Read(0x00, 0x26, 0x08, PY_DataR_Seg, 2);
   rx_len=(((uint16_t)PY_DataR_Seg[0])<<8)|((uint16_t)PY_DataR_Seg[1]);
   HAL_Delay(200);

   PY_W5500_Read(rx_addr_h, rx_addr_l, 0x18, PY_DataR_Seg, rx_len);
   CDC_Transmit_FS(PY_DataR_Seg, rx_len);

   PY_W5500_Config(0x00, 0x28, 0x0c, ((((uint16_t)(rx_addr_h))<<8)|((uint16_t)(rx_addr_l))+rx_len)>>8);
   PY_W5500_Config(0x00, 0x29, 0x0c, ((((uint16_t)(rx_addr_h))<<8)|((uint16_t)(rx_addr_l))+rx_len));
   PY_W5500_Config(0x00, 0x01, 0x0c, 0x40);
   HAL_Delay(200);

   /*
    * Sending
    */
   PY_DataW_Seg[0]=0;PY_DataW_Seg[1]=1;PY_DataW_Seg[2]=2;PY_DataW_Seg[3]=3;PY_DataW_Seg[4]=4;PY_DataW_Seg[5]=5;PY_DataW_Seg[6]=6;PY_DataW_Seg[7]=7;

   PY_W5500_Read(0x00, 0x22, 0x08, PY_DataR_Seg, 2);
   PY_W5500_Read(0x00, 0x24, 0x08, PY_DataR_Seg, 2);

   PY_W5500_Send(PY_DataR_Seg[0], PY_DataR_Seg[1], 0x14, PY_DataW_Seg, 8);

   PY_W5500_Config(0x00, 0x24, 0x0c, ((((uint16_t)(PY_DataR_Seg[0]))<<8)|((uint16_t)(PY_DataR_Seg[1]))+8)>>8);
   PY_W5500_Config(0x00, 0x25, 0x0c, ((((uint16_t)(PY_DataR_Seg[0]))<<8)|((uint16_t)(PY_DataR_Seg[1]))+8));
   HAL_Delay(1);

    PY_W5500_Read(0x00, 0x22, 0x08, PY_DataR_Seg, 2);
    PY_W5500_Read(0x00, 0x24, 0x08, PY_DataR_Seg, 2);


  HAL_Delay(1);
  PY_W5500_Config(0x00, 0x01, 0x0c, 0x20);
  HAL_Delay(1);

    PY_W5500_Read(0x00, 0x22, 0x08, PY_DataR_Seg, 2);
    PY_W5500_Read(0x00, 0x24, 0x08, PY_DataR_Seg, 2);

  }
   /* USER CODE END WHILE */

   /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /** Supply configuration update enable
 */
 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
 /** Configure the main internal regulator output voltage
 */
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
 /** Macro to configure the PLL clock source
 */
 __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
 /** Initializes the RCC Oscillators according to the specified parameters
 * in the RCC_OscInitTypeDef structure.
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = 4;
 RCC_OscInitStruct.PLL.PLLN = 480;
 RCC_OscInitStruct.PLL.PLLP = 2;
 RCC_OscInitStruct.PLL.PLLQ = 2;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
 RCC_OscInitStruct.PLL.PLLFRACN = 0;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
   Error_Handler();
 }
 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                             |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                             |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
 {
   Error_Handler();
 }
}

/* USER CODE BEGIN 4 */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
extern uint8_t PY_SPIDMA__Status;
PY_SPIDMA__Status = 0;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
extern uint8_t PY_SPIDMA__Status;
PY_SPIDMA__Status = 0;
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
extern uint8_t PY_SPIDMA__Status;
PY_SPIDMA__Status = 0;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
extern uint8_t cmd;

if(GPIO_Pin==GPIO_PIN_5){

 cmd=1;

}

}
/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
 /* USER CODE BEGIN Error_Handler_Debug */
 /* User can add his own implementation to report the HAL error return state */
 __disable_irq();
 while (1)
 {
 }
 /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

编译并完成下载程序。 

通讯测试

连接网线,并将本地IP做静态指定:

在这里插入图片描述

芯片重启跑起来后,网络接通,然后打开TCP测试工具,STM32是以太网Server角色,这里电脑端则设置为Client角色:

在这里插入图片描述
在这里插入图片描述

打开一个串口工具并连接:

在这里插入图片描述

TCP工具端连接STM32, 并发送“GOOD", 接收端设置为16进制接收:

在这里插入图片描述

这样,从电脑TCP发送端发送出去的"GOOD"被STM32收到后,转发到串口;STM32另外将十六进制00 01 02 03 04 05 06 07发送到电脑TCP接收端。

参考例程

上述设计的例程下载:
https://download.csdn.net/download/hwytree/22007730

–End–

 

Comments

Similar projects you might like

Comments