STM32+W5500+以太网应用开发+001_Ping 新建工程,移植驱动
1 概述
1.1 硬件介绍
使用W5500模块,经转接板插在Nucleo-F407ZG上进行开发
1.2 软件介绍
- STM32CubeMX 6.21;
- STM32Cube_FW_F4_V1.26.2;
- Keil 5.36
2 使用STM32CubeMX新建工程
2.1 选择芯片STM32F407ZG
2.2 配置工程
2.3 配置时钟
时钟配置需要和自己的硬件电路匹配
注意晶振频率和倍频频率
2.4 配置SWD
2.5 配置IO引脚
W5500引脚 | 描述 |
---|---|
PWDN | 连接PB8,普通IO即可,输出,高电平有效 |
CS | 连接PD14,普通IO即可,输出,低电平有效 |
RST | 连接PB9,普通IO即可,输出,上升沿有效 |
INT | 连接PD15,普通IO即可,输入 |
2.6 配置SPI
W5500引脚 | 描述 |
---|---|
SCK | 连接PA5,SPI1_SCK |
MISO | 连接PA6,SPI1_MISO |
MOSI | 连接PA7,SPI1_MOSI |
2.7 配置串口
打印信息需要使用到串口
2.8 生成代码
3 移植Wiznet最新驱动库
ioLibrary_Driver-4.0.0.zip
3.1 拷贝socket和wizchip_conf文件
wizchip_conf.h里面默认的是W5500芯片,如果使用该系列其他芯片修改定义即可
3.2 拷贝W5500文件夹(即w5500.c/.h文件)
3.3 新建硬件适配驱动文件w5500_spi.c/.h
w5500_spi.c
#include "w5500_spi.h"
#include "wizchip_conf.h"
#include "stdio.h"
extern SPI_HandleTypeDef hspi1;
uint8_t SPIReadWrite(uint8_t TxData)
{
uint8_t RxData;
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&TxData, &RxData, 1, 100);
return RxData;
}
void wizchip_select(void)
{
HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_RESET);
}
void wizchip_deselect(void)
{
HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_SET);
}
uint8_t wizchip_read(void)
{
uint8_t rb;
rb=SPIReadWrite(0x00);
return rb;
}
void wizchip_write(uint8_t wb)
{
SPIReadWrite(wb);
}
void wizchip_readburst(uint8_t* pBuf, uint16_t len)
{
for(uint16_t i=0;i<len;i++)
{
*pBuf=SPIReadWrite(0x00);
pBuf++;
}
}
void wizchip_writeburst(uint8_t* pBuf, uint16_t len)
{
for(uint16_t i=0;i<len;i++)
{
SPIReadWrite(*pBuf);
pBuf++;
}
}
void W5500IOInit(void)
{
//使用STM32Cube生成的IO引脚初始化
}
void w5500_enter_critical(void)
{
__disable_irq();
}
void w5500_exit_critical(void)
{
__enable_irq();
}
void W5500Init()
{
uint8_t tmp;
uint8_t memsize[2][8] = { { 2, 2, 2, 2, 2, 2, 2, 2 }, { 2, 2, 2, 2, 2, 2, 2, 2 } };
W5500IOInit();
HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_SET);//CS high by default
//Send a pulse on reset pin
HAL_GPIO_WritePin(W5500_NRST_GPIO_Port, W5500_NRST_Pin, GPIO_PIN_RESET);
tmp = 0xFF;
while(tmp--);
HAL_GPIO_WritePin(W5500_NRST_GPIO_Port, W5500_NRST_Pin, GPIO_PIN_SET);
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);
reg_wizchip_spiburst_cbfunc(wizchip_readburst, wizchip_writeburst);
reg_wizchip_cris_cbfunc(w5500_enter_critical, w5500_exit_critical);
/* WIZChip Initialize*/
if (ctlwizchip(CW_INIT_WIZCHIP, (void*) memsize) == -1) {
printf("WIZCHIP Initialized Failed.\r\n");
while (1);
}
printf("WIZCHIP Initialization Success.\r\n");
//Check if SPI is working
printf("Auto-detecting Ethernet Chip on SPI Port...");
if(WIZCHIP_READ(VERSIONR)==0x04)
{
printf("W5500 Found on SPI\r\n");
}
else
{
printf("W5500 NOT Found on SPI\r\n");
printf("Double Check SPI Cables\r\n");
while(1);
}
}
w5500_spi.h
/*
* w5500_spi.h
*
* Created on: Sep 29, 2021
* Author: Avinash
*/
#ifndef SRC_W5500_W5500_SPI_H_
#define SRC_W5500_W5500_SPI_H_
#include "main.h"
void W5500Init(void);
void wizchip_select(void);
void wizchip_deselect(void);
uint8_t wizchip_read(void);
void wizchip_write(uint8_t wb);
void wizchip_readburst(uint8_t* pBuf, uint16_t len);
void wizchip_writeburst(uint8_t* pBuf, uint16_t len);
#endif /* SRC_W5500_W5500_SPI_H_ */
3.4 添加文件到工程
3.5 添加头文件路径
4 main.c文件代码修改
4.1 头文件包含
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "w5500_spi.h"
#include "wizchip_conf.h"
#include "socket.h"
/* USER CODE END Includes */
4.2 变量定义和函数声明
#define LISTEN_PORT 5000
#define RECEIVE_BUFF_SIZE 128
wiz_NetInfo gWIZNETINFO = {
.mac = { 0x80, 0x80, 0x80,0x80,0x80,0x80 },//MSB - LSB
.ip = { 192, 168, 1, 10 },
.sn = { 255, 255, 255, 0 },
.gw = { 192, 168, 1, 1 },
.dns = { 8, 8, 8, 8 },
.dhcp = NETINFO_STATIC };
uint8_t receive_buff[RECEIVE_BUFF_SIZE];
static void PHYStatusCheck(void);
static void PrintPHYConf(void);
4.3 main函数修改
int main(void)
{
//其他省略
/* USER CODE BEGIN 2 */
printf("A simple Ping Application using W5500!\r\n");
W5500Init();
//配置网络参数
ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);
//配置PHY参数
wiz_PhyConf phyconf;
phyconf.by = PHY_CONFBY_SW;
phyconf.duplex = PHY_DUPLEX_FULL;
phyconf.speed = PHY_SPEED_10;
phyconf.mode = PHY_MODE_AUTONEGO;
ctlwizchip(CW_SET_PHYCONF, (void*)&phyconf); //PHY Configuration Command
PHYStatusCheck();
PrintPHYConf();
printf("Simple Ping Application\r\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
4.4 串口打印支持函数
#if (defined(__GNUC__) && !defined(__CC_ARM))
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART2 and Loop until the end of transmission */
while (HAL_OK != HAL_UART_Transmit(&huart3, (uint8_t *) &ch, 1, 30000))
{
;
}
return ch;
}
/**
* @brief Retargets the C library scanf function to the USART.
* @param None
* @retval None
*/
GETCHAR_PROTOTYPE
{
/* Place your implementation of fgetc here */
/* e.g. read a character on USART and loop until the end of read */
uint8_t ch = 0;
while (HAL_OK != HAL_UART_Receive(&huart3, (uint8_t *)&ch, 1, 30000))
{
;
}
return ch;
}
4.5 以太网状态打印函数
void PHYStatusCheck(void)
{
uint8_t tmp;
do
{
printf("\r\nChecking Ethernet Cable Presence ...");
ctlwizchip(CW_GET_PHYLINK, (void*) &tmp);
if(tmp == PHY_LINK_OFF)
{
printf("NO Cable Connected!");
HAL_Delay(1500);
}
}while(tmp == PHY_LINK_OFF);
printf("Good! Cable got connected!");
}
void PrintPHYConf(void)
{
wiz_PhyConf phyconf;
ctlwizchip(CW_GET_PHYCONF, (void*) &phyconf);
if(phyconf.by==PHY_CONFBY_HW)
{
printf("\r\nPHY Configured by Hardware Pins");
}
else
{
printf("\r\nPHY Configured by Registers");
}
if(phyconf.mode==PHY_MODE_AUTONEGO)
{
printf("\r\nAutonegotiation Enabled");
}
else
{
printf("\r\nAutonegotiation NOT Enabled");
}
if(phyconf.duplex==PHY_DUPLEX_FULL)
{
printf("\r\nDuplex Mode: Full");
}
else
{
printf("\r\nDuplex Mode: Half");
}
if(phyconf.speed==PHY_SPEED_10)
{
printf("\r\nSpeed: 10Mbps");
}
else
{
printf("\r\nSpeed: 100Mbps");
}
}
5 测试
5.1 打印信息
串口终端使用的MobaXterm,可以高亮显示log信息