PHY——LAN8720A 寄存器读写 (二)

news2025/4/2 3:39:07

文章目录

  • PHY——LAN8720A 寄存器读写 (二)
    • 工程配置
    • 引脚初始化代码
    • 以太网初始化代码
    • PHY 接口实现
    • LAN8720 接口实现
    • PHY 接口测试

PHY——LAN8720A 寄存器读写 (二)

工程配置

这里以野火电子的 F429 开发板为例,配置以太网外设
在这里插入图片描述
这里有一点需要注意原理图 RMII_TXD0, RMII_TXD1 使用的分别是 PG13, PG14,如下图

在这里插入图片描述
但是当 CubeMx 使能 ETH 外设的 RMII 时候,默认使用的引脚是 PB12 和 PB13
在这里插入图片描述
这里需要手动修改
在这里插入图片描述
这样 RMII 的引脚和以太网相关时钟就配置好了,这里我们只借助 CubeMx 配置这两个,PHY的驱动自己来实现

引脚初始化代码

void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(ethHandle->Instance==ETH)
  {
  /* USER CODE BEGIN ETH_MspInit 0 */

  /* USER CODE END ETH_MspInit 0 */
    /* ETH clock enable */
    __HAL_RCC_ETH_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();
    /**ETH GPIO Configuration
    PC1     ------> ETH_MDC
    PA1     ------> ETH_REF_CLK
    PA2     ------> ETH_MDIO
    PA7     ------> ETH_CRS_DV
    PC4     ------> ETH_RXD0
    PC5     ------> ETH_RXD1
    PB11     ------> ETH_TX_EN
    PG13     ------> ETH_TXD0
    PG14     ------> ETH_TXD1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /* USER CODE BEGIN ETH_MspInit 1 */

  /* USER CODE END ETH_MspInit 1 */
  }
}

以太网初始化代码

void MX_ETH_Init(void)
{

  /* USER CODE BEGIN ETH_Init 0 */

  /* USER CODE END ETH_Init 0 */

   static uint8_t MACAddr[6];

  /* USER CODE BEGIN ETH_Init 1 */

  /* USER CODE END ETH_Init 1 */
  heth.Instance = ETH;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;
  heth.Init.MACAddr = &MACAddr[0];
  heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
  heth.Init.TxDesc = DMATxDscrTab;
  heth.Init.RxDesc = DMARxDscrTab;
  heth.Init.RxBuffLen = 1524;

  /* USER CODE BEGIN MACADDRESS */

  /* USER CODE END MACADDRESS */

  if (HAL_ETH_Init(&heth) != HAL_OK)
  {
    Error_Handler();
  }

  memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
  TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
  /* USER CODE BEGIN ETH_Init 2 */

  /* USER CODE END ETH_Init 2 */

}

PHY 接口实现

ethernetif.c
这个文件其实主要实现了两个接口 ETH_PHY_IO_ReadRegETH_PHY_IO_WriteReg

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : ethernetif.c
  * Description        : This file provides code for the configuration
  *                      of the ethernetif.c MiddleWare.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "ethernetif.h"
#include "lan8720.h"
#include <string.h>

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* Private function prototypes -----------------------------------------------*/
int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit (void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void);

lan8720_Object_t LAN8720;
lan8720_IOCtx_t  LAN8720_IOCtx = {ETH_PHY_IO_Init,
                                  ETH_PHY_IO_DeInit,
                                  ETH_PHY_IO_WriteReg,
                                  ETH_PHY_IO_ReadReg,
                                  ETH_PHY_IO_GetTick};

/* USER CODE BEGIN 3 */

/* USER CODE END 3 */

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE END 6 */

/*******************************************************************************
                       PHI IO Functions
*******************************************************************************/
/**
  * @brief  Initializes the MDIO interface GPIO and clocks.
  * @param  None
  * @retval 0 if OK, -1 if ERROR
  */
int32_t ETH_PHY_IO_Init(void)
{
  /* We assume that MDIO GPIO configuration is already done
     in the ETH_MspInit() else it should be done here
  */

  /* Configure the MDIO Clock */
  HAL_ETH_SetMDIOClockRange(&heth);

  return 0;
}

/**
  * @brief  De-Initializes the MDIO interface .
  * @param  None
  * @retval 0 if OK, -1 if ERROR
  */
int32_t ETH_PHY_IO_DeInit (void)
{
  return 0;
}

/**
  * @brief  Read a PHY register through the MDIO interface.
  * @param  DevAddr: PHY port address
  * @param  RegAddr: PHY register address
  * @param  pRegVal: pointer to hold the register value
  * @retval 0 if OK -1 if Error
  */
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
  if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK)
  {
    return -1;
  }

  return 0;
}

/**
  * @brief  Write a value to a PHY register through the MDIO interface.
  * @param  DevAddr: PHY port address
  * @param  RegAddr: PHY register address
  * @param  RegVal: Value to be written
  * @retval 0 if OK -1 if Error
  */
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
  if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK)
  {
    return -1;
  }

  return 0;
}

/**
  * @brief  Get the time in millisecons used for internal PHY driver process.
  * @retval Time value
  */
int32_t ETH_PHY_IO_GetTick(void)
{
  return HAL_GetTick();
}
/* USER CODE BEGIN 8 */

/* USER CODE END 8 */


ethernetif.h 文件

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
  * File Name          : ethernetif.h
  * Description        : This file provides initialization code for LWIP
  *                      middleWare.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__

/* USER CODE BEGIN 0 */
#include "main.h"
#include "lan8720.h"
extern ETH_HandleTypeDef heth;
extern lan8720_Object_t LAN8720;
extern lan8720_IOCtx_t  LAN8720_IOCtx;
/* USER CODE END 0 */

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
#endif

LAN8720 接口实现

lan8720.c

/**
  ******************************************************************************
  * @file    lan8720.c
  * @author  MCD Application Team
  * @brief   This file provides a set of functions needed to manage the LAN742
  *          PHY devices.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "lan8720.h"

/** @addtogroup BSP
  * @{
  */

/** @addtogroup Component
  * @{
  */

/** @defgroup LAN8720 LAN8720
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup LAN8720_Private_Defines LAN8720 Private Defines
  * @{
  */
#define LAN8720_MAX_DEV_ADDR   ((uint32_t)31U)
/**
  * @}
  */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup LAN8720_Private_Functions LAN8720 Private Functions
  * @{
  */

/**
  * @brief  Register IO functions to component object
  * @param  pObj: device object  of LAN8720_Object_t.
  * @param  ioctx: holds device IO functions.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_ERROR if missing mandatory function
  */
int32_t  LAN8720_RegisterBusIO(lan8720_Object_t *pObj, lan8720_IOCtx_t *ioctx)
{
  if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
  {
    return LAN8720_STATUS_ERROR;
  }

  pObj->IO.Init = ioctx->Init;
  pObj->IO.DeInit = ioctx->DeInit;
  pObj->IO.ReadReg = ioctx->ReadReg;
  pObj->IO.WriteReg = ioctx->WriteReg;
  pObj->IO.GetTick = ioctx->GetTick;

  return LAN8720_STATUS_OK;
}

/**
  * @brief  Initialize the lan8720 and configure the needed hardware resources
  * @param  pObj: device object LAN8720_Object_t.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_ADDRESS_ERROR if cannot find device address
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  */
 int32_t LAN8720_Init(lan8720_Object_t *pObj)
 {
   uint32_t regvalue = 0, addr = 0;
   int32_t status = LAN8720_STATUS_OK;

   if(pObj->Is_Initialized == 0)
   {
     if(pObj->IO.Init != 0)
     {
       /* GPIO and Clocks initialization */
       pObj->IO.Init();
     }

     /* for later check */
     pObj->DevAddr = LAN8720_MAX_DEV_ADDR + 1;

     /* Get the device address from special mode register */
     for(addr = 0; addr <= LAN8720_MAX_DEV_ADDR; addr ++)
     {
       if(pObj->IO.ReadReg(addr, LAN8720_SMR, &regvalue) < 0)
       {
         status = LAN8720_STATUS_READ_ERROR;
         /* Can't read from this device address
            continue with next address */
         continue;
       }

       if((regvalue & LAN8720_SMR_PHY_ADDR) == addr)
       {
         pObj->DevAddr = addr;
         status = LAN8720_STATUS_OK;
         break;
       }
     }

     if(pObj->DevAddr > LAN8720_MAX_DEV_ADDR)
     {
       status = LAN8720_STATUS_ADDRESS_ERROR;
     }

     /* if device address is matched */
     if(status == LAN8720_STATUS_OK)
     {
       pObj->Is_Initialized = 1;
     }
   }

   return status;
 }

/**
  * @brief  De-Initialize the lan8720 and it's hardware resources
  * @param  pObj: device object LAN8720_Object_t.
  * @retval None
  */
int32_t LAN8720_DeInit(lan8720_Object_t *pObj)
{
  if(pObj->Is_Initialized)
  {
    if(pObj->IO.DeInit != 0)
    {
      if(pObj->IO.DeInit() < 0)
      {
        return LAN8720_STATUS_ERROR;
      }
    }

    pObj->Is_Initialized = 0;
  }

  return LAN8720_STATUS_OK;
}

/**
  * @brief  Disable the LAN8720 power down mode.
  * @param  pObj: device object LAN8720_Object_t.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_DisablePowerDownMode(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
  {
    readval &= ~LAN8720_BCR_POWER_DOWN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
    {
      status =  LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Enable the LAN8720 power down mode.
  * @param  pObj: device object LAN8720_Object_t.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_EnablePowerDownMode(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
  {
    readval |= LAN8720_BCR_POWER_DOWN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
    {
      status =  LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Start the auto negotiation process.
  * @param  pObj: device object LAN8720_Object_t.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_StartAutoNego(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
  {
    readval |= LAN8720_BCR_AUTONEGO_EN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
    {
      status =  LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Get the link state of LAN8720 device.
  * @param  pObj: Pointer to device object.
  * @param  pLinkState: Pointer to link state
  * @retval LAN8720_STATUS_LINK_DOWN  if link is down
  *         LAN8720_STATUS_AUTONEGO_NOTDONE if Auto nego not completed
  *         LAN8720_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
  *         LAN8720_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
  *         LAN8720_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
  *         LAN8720_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_GetLinkState(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;

  /* Read Status register  */
  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BSR, &readval) < 0)
  {
    return LAN8720_STATUS_READ_ERROR;
  }

  /* Read Status register again */
  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BSR, &readval) < 0)
  {
    return LAN8720_STATUS_READ_ERROR;
  }

  if((readval & LAN8720_BSR_LINK_STATUS) == 0)
  {
    /* Return Link Down status */
    return LAN8720_STATUS_LINK_DOWN;
  }

  /* Check Auto negotiation */
  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) < 0)
  {
    return LAN8720_STATUS_READ_ERROR;
  }

  if((readval & LAN8720_BCR_AUTONEGO_EN) != LAN8720_BCR_AUTONEGO_EN)
  {
    if(((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT) && ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE))
    {
      return LAN8720_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT)
    {
      return LAN8720_STATUS_100MBITS_HALFDUPLEX;
    }
    else if ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE)
    {
      return LAN8720_STATUS_10MBITS_FULLDUPLEX;
    }
    else
    {
      return LAN8720_STATUS_10MBITS_HALFDUPLEX;
    }
  }
  else /* Auto Nego enabled */
  {
    if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_PHYSCSR, &readval) < 0)
    {
      return LAN8720_STATUS_READ_ERROR;
    }

    /* Check if auto nego not done */
    if((readval & LAN8720_PHYSCSR_AUTONEGO_DONE) == 0)
    {
      return LAN8720_STATUS_AUTONEGO_NOTDONE;
    }

    if((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_100BTX_FD)
    {
      return LAN8720_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_100BTX_HD)
    {
      return LAN8720_STATUS_100MBITS_HALFDUPLEX;
    }
    else if ((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_10BT_FD)
    {
      return LAN8720_STATUS_10MBITS_FULLDUPLEX;
    }
    else
    {
      return LAN8720_STATUS_10MBITS_HALFDUPLEX;
    }
  }
}

/**
  * @brief  Set the link state of LAN8720 device.
  * @param  pObj: Pointer to device object.
  * @param  pLinkState: link state can be one of the following
  *         LAN8720_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
  *         LAN8720_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
  *         LAN8720_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
  *         LAN8720_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_ERROR  if parameter error
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_SetLinkState(lan8720_Object_t *pObj, uint32_t LinkState)
{
  uint32_t bcrvalue = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &bcrvalue) >= 0)
  {
    /* Disable link config (Auto nego, speed and duplex) */
    bcrvalue &= ~(LAN8720_BCR_AUTONEGO_EN | LAN8720_BCR_SPEED_SELECT | LAN8720_BCR_DUPLEX_MODE);

    if(LinkState == LAN8720_STATUS_100MBITS_FULLDUPLEX)
    {
      bcrvalue |= (LAN8720_BCR_SPEED_SELECT | LAN8720_BCR_DUPLEX_MODE);
    }
    else if (LinkState == LAN8720_STATUS_100MBITS_HALFDUPLEX)
    {
      bcrvalue |= LAN8720_BCR_SPEED_SELECT;
    }
    else if (LinkState == LAN8720_STATUS_10MBITS_FULLDUPLEX)
    {
      bcrvalue |= LAN8720_BCR_DUPLEX_MODE;
    }
    else
    {
      /* Wrong link status parameter */
      status = LAN8720_STATUS_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  if(status == LAN8720_STATUS_OK)
  {
    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, bcrvalue) < 0)
    {
      status = LAN8720_STATUS_WRITE_ERROR;
    }
  }

  return status;
}

/**
  * @brief  Enable loopback mode.
  * @param  pObj: Pointer to device object.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_EnableLoopbackMode(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
  {
    readval |= LAN8720_BCR_LOOPBACK;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
    {
      status = LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Disable loopback mode.
  * @param  pObj: Pointer to device object.
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_DisableLoopbackMode(lan8720_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
  {
    readval &= ~LAN8720_BCR_LOOPBACK;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
    {
      status =  LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Enable IT source.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT source to be enabled
  *         should be a value or a combination of the following:
  *         LAN8720_WOL_IT
  *         LAN8720_ENERGYON_IT
  *         LAN8720_AUTONEGO_COMPLETE_IT
  *         LAN8720_REMOTE_FAULT_IT
  *         LAN8720_LINK_DOWN_IT
  *         LAN8720_AUTONEGO_LP_ACK_IT
  *         LAN8720_PARALLEL_DETECTION_FAULT_IT
  *         LAN8720_AUTONEGO_PAGE_RECEIVED_IT
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_EnableIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_IMR, &readval) >= 0)
  {
    readval |= Interrupt;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_IMR, readval) < 0)
    {
      status =  LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Disable IT source.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT source to be disabled
  *         should be a value or a combination of the following:
  *         LAN8720_WOL_IT
  *         LAN8720_ENERGYON_IT
  *         LAN8720_AUTONEGO_COMPLETE_IT
  *         LAN8720_REMOTE_FAULT_IT
  *         LAN8720_LINK_DOWN_IT
  *         LAN8720_AUTONEGO_LP_ACK_IT
  *         LAN8720_PARALLEL_DETECTION_FAULT_IT
  *         LAN8720_AUTONEGO_PAGE_RECEIVED_IT
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  *         LAN8720_STATUS_WRITE_ERROR if cannot write to register
  */
int32_t LAN8720_DisableIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_IMR, &readval) >= 0)
  {
    readval &= ~Interrupt;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_IMR, readval) < 0)
    {
      status = LAN8720_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Clear IT flag.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT flag to be cleared
  *         should be a value or a combination of the following:
  *         LAN8720_WOL_IT
  *         LAN8720_ENERGYON_IT
  *         LAN8720_AUTONEGO_COMPLETE_IT
  *         LAN8720_REMOTE_FAULT_IT
  *         LAN8720_LINK_DOWN_IT
  *         LAN8720_AUTONEGO_LP_ACK_IT
  *         LAN8720_PARALLEL_DETECTION_FAULT_IT
  *         LAN8720_AUTONEGO_PAGE_RECEIVED_IT
  * @retval LAN8720_STATUS_OK  if OK
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  */
int32_t  LAN8720_ClearIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = LAN8720_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_ISFR, &readval) < 0)
  {
    status =  LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Get IT Flag status.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT Flag to be checked,
  *         should be a value or a combination of the following:
  *         LAN8720_WOL_IT
  *         LAN8720_ENERGYON_IT
  *         LAN8720_AUTONEGO_COMPLETE_IT
  *         LAN8720_REMOTE_FAULT_IT
  *         LAN8720_LINK_DOWN_IT
  *         LAN8720_AUTONEGO_LP_ACK_IT
  *         LAN8720_PARALLEL_DETECTION_FAULT_IT
  *         LAN8720_AUTONEGO_PAGE_RECEIVED_IT
  * @retval 1 IT flag is SET
  *         0 IT flag is RESET
  *         LAN8720_STATUS_READ_ERROR if cannot read register
  */
int32_t LAN8720_GetITStatus(lan8720_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = 0;

  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_ISFR, &readval) >= 0)
  {
    status = ((readval & Interrupt) == Interrupt);
  }
  else
  {
    status = LAN8720_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

lan8720.h
这个文件主要定义 PHY 的相关寄存器以及各个 bit,例如 LAN8720_BCRLAN8720_BSRLAN8720_BCR_SOFT_RESET

/**
  ******************************************************************************
  * @file    lan8720.h
  * @author  MCD Application Team
  * @brief   This file contains all the functions prototypes for the
  *          lan8720.c PHY driver.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */ 

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LAN8720_H
#define LAN8720_H

#ifdef __cplusplus
 extern "C" {
#endif   
   
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>

/** @addtogroup BSP
  * @{
  */ 

/** @addtogroup Component
  * @{
  */
    
/** @defgroup LAN8720
  * @{
  */    
/* Exported constants --------------------------------------------------------*/
/** @defgroup LAN8720_Exported_Constants LAN8720 Exported Constants
  * @{
  */ 
  
/** @defgroup LAN8720_Registers_Mapping LAN8720 Registers Mapping
  * @{
  */ 
#define LAN8720_BCR      ((uint16_t)0x0000U)
#define LAN8720_BSR      ((uint16_t)0x0001U)
#define LAN8720_PHYI1R   ((uint16_t)0x0002U)
#define LAN8720_PHYI2R   ((uint16_t)0x0003U)
#define LAN8720_ANAR     ((uint16_t)0x0004U)
#define LAN8720_ANLPAR   ((uint16_t)0x0005U)
#define LAN8720_ANER     ((uint16_t)0x0006U)
#define LAN8720_ANNPTR   ((uint16_t)0x0007U)
#define LAN8720_ANNPRR   ((uint16_t)0x0008U)
#define LAN8720_MMDACR   ((uint16_t)0x000DU)
#define LAN8720_MMDAADR  ((uint16_t)0x000EU)
#define LAN8720_ENCTR    ((uint16_t)0x0010U)
#define LAN8720_MCSR     ((uint16_t)0x0011U)
#define LAN8720_SMR      ((uint16_t)0x0012U)
#define LAN8720_TPDCR    ((uint16_t)0x0018U)
#define LAN8720_TCSR     ((uint16_t)0x0019U)
#define LAN8720_SECR     ((uint16_t)0x001AU)
#define LAN8720_SCSIR    ((uint16_t)0x001BU)
#define LAN8720_CLR      ((uint16_t)0x001CU)
#define LAN8720_ISFR     ((uint16_t)0x001DU)
#define LAN8720_IMR      ((uint16_t)0x001EU)
#define LAN8720_PHYSCSR  ((uint16_t)0x001FU)
/**
  * @}
  */

/** @defgroup LAN8720_BCR_Bit_Definition LAN8720 BCR Bit Definition
  * @{
  */    
#define LAN8720_BCR_SOFT_RESET         ((uint16_t)0x8000U)
#define LAN8720_BCR_LOOPBACK           ((uint16_t)0x4000U)
#define LAN8720_BCR_SPEED_SELECT       ((uint16_t)0x2000U)
#define LAN8720_BCR_AUTONEGO_EN        ((uint16_t)0x1000U)
#define LAN8720_BCR_POWER_DOWN         ((uint16_t)0x0800U)
#define LAN8720_BCR_ISOLATE            ((uint16_t)0x0400U)
#define LAN8720_BCR_RESTART_AUTONEGO   ((uint16_t)0x0200U)
#define LAN8720_BCR_DUPLEX_MODE        ((uint16_t)0x0100U) 
/**
  * @}
  */

/** @defgroup LAN8720_BSR_Bit_Definition LAN8720 BSR Bit Definition
  * @{
  */   
#define LAN8720_BSR_100BASE_T4       ((uint16_t)0x8000U)
#define LAN8720_BSR_100BASE_TX_FD    ((uint16_t)0x4000U)
#define LAN8720_BSR_100BASE_TX_HD    ((uint16_t)0x2000U)
#define LAN8720_BSR_10BASE_T_FD      ((uint16_t)0x1000U)
#define LAN8720_BSR_10BASE_T_HD      ((uint16_t)0x0800U)
#define LAN8720_BSR_100BASE_T2_FD    ((uint16_t)0x0400U)
#define LAN8720_BSR_100BASE_T2_HD    ((uint16_t)0x0200U)
#define LAN8720_BSR_EXTENDED_STATUS  ((uint16_t)0x0100U)
#define LAN8720_BSR_AUTONEGO_CPLT    ((uint16_t)0x0020U)
#define LAN8720_BSR_REMOTE_FAULT     ((uint16_t)0x0010U)
#define LAN8720_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
#define LAN8720_BSR_LINK_STATUS      ((uint16_t)0x0004U)
#define LAN8720_BSR_JABBER_DETECT    ((uint16_t)0x0002U)
#define LAN8720_BSR_EXTENDED_CAP     ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup LAN8720_PHYI1R_Bit_Definition LAN8720 PHYI1R Bit Definition
  * @{
  */
#define LAN8720_PHYI1R_OUI_3_18           ((uint16_t)0xFFFFU)
/**
  * @}
  */

/** @defgroup LAN8720_PHYI2R_Bit_Definition LAN8720 PHYI2R Bit Definition
  * @{
  */
#define LAN8720_PHYI2R_OUI_19_24          ((uint16_t)0xFC00U)
#define LAN8720_PHYI2R_MODEL_NBR          ((uint16_t)0x03F0U)
#define LAN8720_PHYI2R_REVISION_NBR       ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup LAN8720_ANAR_Bit_Definition LAN8720 ANAR Bit Definition
  * @{
  */
#define LAN8720_ANAR_NEXT_PAGE               ((uint16_t)0x8000U)
#define LAN8720_ANAR_REMOTE_FAULT            ((uint16_t)0x2000U)
#define LAN8720_ANAR_PAUSE_OPERATION         ((uint16_t)0x0C00U)
#define LAN8720_ANAR_PO_NOPAUSE              ((uint16_t)0x0000U)
#define LAN8720_ANAR_PO_SYMMETRIC_PAUSE      ((uint16_t)0x0400U)
#define LAN8720_ANAR_PO_ASYMMETRIC_PAUSE     ((uint16_t)0x0800U)
#define LAN8720_ANAR_PO_ADVERTISE_SUPPORT    ((uint16_t)0x0C00U)
#define LAN8720_ANAR_100BASE_TX_FD           ((uint16_t)0x0100U)
#define LAN8720_ANAR_100BASE_TX              ((uint16_t)0x0080U)
#define LAN8720_ANAR_10BASE_T_FD             ((uint16_t)0x0040U)
#define LAN8720_ANAR_10BASE_T                ((uint16_t)0x0020U)
#define LAN8720_ANAR_SELECTOR_FIELD          ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup LAN8720_ANLPAR_Bit_Definition LAN8720 ANLPAR Bit Definition
  * @{
  */
#define LAN8720_ANLPAR_NEXT_PAGE            ((uint16_t)0x8000U)
#define LAN8720_ANLPAR_REMOTE_FAULT         ((uint16_t)0x2000U)
#define LAN8720_ANLPAR_PAUSE_OPERATION      ((uint16_t)0x0C00U)
#define LAN8720_ANLPAR_PO_NOPAUSE           ((uint16_t)0x0000U)
#define LAN8720_ANLPAR_PO_SYMMETRIC_PAUSE   ((uint16_t)0x0400U)
#define LAN8720_ANLPAR_PO_ASYMMETRIC_PAUSE  ((uint16_t)0x0800U)
#define LAN8720_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define LAN8720_ANLPAR_100BASE_TX_FD        ((uint16_t)0x0100U)
#define LAN8720_ANLPAR_100BASE_TX           ((uint16_t)0x0080U)
#define LAN8720_ANLPAR_10BASE_T_FD          ((uint16_t)0x0040U)
#define LAN8720_ANLPAR_10BASE_T             ((uint16_t)0x0020U)
#define LAN8720_ANLPAR_SELECTOR_FIELD       ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup LAN8720_ANER_Bit_Definition LAN8720 ANER Bit Definition
  * @{
  */
#define LAN8720_ANER_RX_NP_LOCATION_ABLE    ((uint16_t)0x0040U)
#define LAN8720_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
#define LAN8720_ANER_PARALLEL_DETECT_FAULT  ((uint16_t)0x0010U)
#define LAN8720_ANER_LP_NP_ABLE             ((uint16_t)0x0008U)
#define LAN8720_ANER_NP_ABLE                ((uint16_t)0x0004U)
#define LAN8720_ANER_PAGE_RECEIVED          ((uint16_t)0x0002U)
#define LAN8720_ANER_LP_AUTONEG_ABLE        ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup LAN8720_ANNPTR_Bit_Definition LAN8720 ANNPTR Bit Definition
  * @{
  */
#define LAN8720_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
#define LAN8720_ANNPTR_MESSAGE_PAGE      ((uint16_t)0x2000U)
#define LAN8720_ANNPTR_ACK2              ((uint16_t)0x1000U)
#define LAN8720_ANNPTR_TOGGLE            ((uint16_t)0x0800U)
#define LAN8720_ANNPTR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
/**
  * @}
  */

/** @defgroup LAN8720_ANNPRR_Bit_Definition LAN8720 ANNPRR Bit Definition
  * @{
  */
#define LAN8720_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
#define LAN8720_ANNPRR_ACK               ((uint16_t)0x4000U)
#define LAN8720_ANNPRR_MESSAGE_PAGE      ((uint16_t)0x2000U)
#define LAN8720_ANNPRR_ACK2              ((uint16_t)0x1000U)
#define LAN8720_ANNPRR_TOGGLE            ((uint16_t)0x0800U)
#define LAN8720_ANNPRR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
/**
  * @}
  */

/** @defgroup LAN8720_MMDACR_Bit_Definition LAN8720 MMDACR Bit Definition
  * @{
  */
#define LAN8720_MMDACR_MMD_FUNCTION       ((uint16_t)0xC000U) 
#define LAN8720_MMDACR_MMD_FUNCTION_ADDR  ((uint16_t)0x0000U)
#define LAN8720_MMDACR_MMD_FUNCTION_DATA  ((uint16_t)0x4000U)
#define LAN8720_MMDACR_MMD_DEV_ADDR       ((uint16_t)0x001FU)
/**
  * @}
  */

/** @defgroup LAN8720_ENCTR_Bit_Definition LAN8720 ENCTR Bit Definition
  * @{
  */
#define LAN8720_ENCTR_TX_ENABLE             ((uint16_t)0x8000U)
#define LAN8720_ENCTR_TX_TIMER              ((uint16_t)0x6000U)
#define LAN8720_ENCTR_TX_TIMER_1S           ((uint16_t)0x0000U)
#define LAN8720_ENCTR_TX_TIMER_768MS        ((uint16_t)0x2000U)
#define LAN8720_ENCTR_TX_TIMER_512MS        ((uint16_t)0x4000U)
#define LAN8720_ENCTR_TX_TIMER_265MS        ((uint16_t)0x6000U)
#define LAN8720_ENCTR_RX_ENABLE             ((uint16_t)0x1000U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL       ((uint16_t)0x0C00U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_64MS  ((uint16_t)0x0000U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_1S    ((uint16_t)0x0C00U)
#define LAN8720_ENCTR_EX_CROSS_OVER         ((uint16_t)0x0002U)
#define LAN8720_ENCTR_EX_MANUAL_CROSS_OVER  ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup LAN8720_MCSR_Bit_Definition LAN8720 MCSR Bit Definition
  * @{
  */
#define LAN8720_MCSR_EDPWRDOWN        ((uint16_t)0x2000U)
#define LAN8720_MCSR_FARLOOPBACK      ((uint16_t)0x0200U)
#define LAN8720_MCSR_ALTINT           ((uint16_t)0x0040U)
#define LAN8720_MCSR_ENERGYON         ((uint16_t)0x0002U)
/**
  * @}
  */

/** @defgroup LAN8720_SMR_Bit_Definition LAN8720 SMR Bit Definition
  * @{
  */
#define LAN8720_SMR_MODE       ((uint16_t)0x00E0U)
#define LAN8720_SMR_PHY_ADDR   ((uint16_t)0x001FU)
/**
  * @}
  */

/** @defgroup LAN8720_TPDCR_Bit_Definition LAN8720 TPDCR Bit Definition
  * @{
  */
#define LAN8720_TPDCR_DELAY_IN                 ((uint16_t)0x8000U)
#define LAN8720_TPDCR_LINE_BREAK_COUNTER       ((uint16_t)0x7000U)
#define LAN8720_TPDCR_PATTERN_HIGH             ((uint16_t)0x0FC0U)
#define LAN8720_TPDCR_PATTERN_LOW              ((uint16_t)0x003FU)
/**
  * @}
  */

/** @defgroup LAN8720_TCSR_Bit_Definition LAN8720 TCSR Bit Definition
  * @{
  */
#define LAN8720_TCSR_TDR_ENABLE           ((uint16_t)0x8000U)
#define LAN8720_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
#define LAN8720_TCSR_TDR_CH_CABLE_TYPE    ((uint16_t)0x0600U)
#define LAN8720_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
#define LAN8720_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
#define LAN8720_TCSR_TDR_CH_CABLE_OPEN    ((uint16_t)0x0400U)
#define LAN8720_TCSR_TDR_CH_CABLE_MATCH   ((uint16_t)0x0600U)
#define LAN8720_TCSR_TDR_CH_STATUS        ((uint16_t)0x0100U)
#define LAN8720_TCSR_TDR_CH_LENGTH        ((uint16_t)0x00FFU)
/**
  * @}
  */

/** @defgroup LAN8720_SCSIR_Bit_Definition LAN8720 SCSIR Bit Definition
  * @{
  */
#define LAN8720_SCSIR_AUTO_MDIX_ENABLE    ((uint16_t)0x8000U)
#define LAN8720_SCSIR_CHANNEL_SELECT      ((uint16_t)0x2000U)
#define LAN8720_SCSIR_SQE_DISABLE         ((uint16_t)0x0800U)
#define LAN8720_SCSIR_XPOLALITY           ((uint16_t)0x0010U)
/**
  * @}
  */

/** @defgroup LAN8720_CLR_Bit_Definition LAN8720 CLR Bit Definition
  * @{
  */
#define LAN8720_CLR_CABLE_LENGTH       ((uint16_t)0xF000U)
/**
  * @}
  */

/** @defgroup LAN8720_IMR_ISFR_Bit_Definition LAN8720 IMR ISFR Bit Definition
  * @{
  */
#define LAN8720_INT_8       ((uint16_t)0x0100U)
#define LAN8720_INT_7       ((uint16_t)0x0080U)
#define LAN8720_INT_6       ((uint16_t)0x0040U)
#define LAN8720_INT_5       ((uint16_t)0x0020U)
#define LAN8720_INT_4       ((uint16_t)0x0010U)
#define LAN8720_INT_3       ((uint16_t)0x0008U)
#define LAN8720_INT_2       ((uint16_t)0x0004U)
#define LAN8720_INT_1       ((uint16_t)0x0002U)
/**
  * @}
  */

/** @defgroup LAN8720_PHYSCSR_Bit_Definition LAN8720 PHYSCSR Bit Definition
  * @{
  */
#define LAN8720_PHYSCSR_AUTONEGO_DONE   ((uint16_t)0x1000U)
#define LAN8720_PHYSCSR_HCDSPEEDMASK    ((uint16_t)0x001CU)
#define LAN8720_PHYSCSR_10BT_HD         ((uint16_t)0x0004U)
#define LAN8720_PHYSCSR_10BT_FD         ((uint16_t)0x0014U)
#define LAN8720_PHYSCSR_100BTX_HD       ((uint16_t)0x0008U)
#define LAN8720_PHYSCSR_100BTX_FD       ((uint16_t)0x0018U) 
/**
  * @}
  */
    
/** @defgroup LAN8720_Status LAN8720 Status
  * @{
  */    

#define  LAN8720_STATUS_READ_ERROR            ((int32_t)-5)
#define  LAN8720_STATUS_WRITE_ERROR           ((int32_t)-4)
#define  LAN8720_STATUS_ADDRESS_ERROR         ((int32_t)-3)
#define  LAN8720_STATUS_RESET_TIMEOUT         ((int32_t)-2)
#define  LAN8720_STATUS_ERROR                 ((int32_t)-1)
#define  LAN8720_STATUS_OK                    ((int32_t) 0)
#define  LAN8720_STATUS_LINK_DOWN             ((int32_t) 1)
#define  LAN8720_STATUS_100MBITS_FULLDUPLEX   ((int32_t) 2)
#define  LAN8720_STATUS_100MBITS_HALFDUPLEX   ((int32_t) 3)
#define  LAN8720_STATUS_10MBITS_FULLDUPLEX    ((int32_t) 4)
#define  LAN8720_STATUS_10MBITS_HALFDUPLEX    ((int32_t) 5)
#define  LAN8720_STATUS_AUTONEGO_NOTDONE      ((int32_t) 6)
/**
  * @}
  */

/** @defgroup LAN8720_IT_Flags LAN8720 IT Flags
  * @{
  */     
#define  LAN8720_WOL_IT                        LAN8720_INT_8
#define  LAN8720_ENERGYON_IT                   LAN8720_INT_7
#define  LAN8720_AUTONEGO_COMPLETE_IT          LAN8720_INT_6
#define  LAN8720_REMOTE_FAULT_IT               LAN8720_INT_5
#define  LAN8720_LINK_DOWN_IT                  LAN8720_INT_4
#define  LAN8720_AUTONEGO_LP_ACK_IT            LAN8720_INT_3
#define  LAN8720_PARALLEL_DETECTION_FAULT_IT   LAN8720_INT_2
#define  LAN8720_AUTONEGO_PAGE_RECEIVED_IT     LAN8720_INT_1
/**
  * @}
  */

/**
  * @}
  */

/* Exported types ------------------------------------------------------------*/ 
/** @defgroup LAN8720_Exported_Types LAN8720 Exported Types
  * @{
  */
typedef int32_t  (*lan8720_Init_Func) (void); 
typedef int32_t  (*lan8720_DeInit_Func) (void);
typedef int32_t  (*lan8720_ReadReg_Func)   (uint32_t, uint32_t, uint32_t *);
typedef int32_t  (*lan8720_WriteReg_Func)  (uint32_t, uint32_t, uint32_t);
typedef int32_t  (*lan8720_GetTick_Func)  (void);

typedef struct 
{                   
  lan8720_Init_Func      Init; 
  lan8720_DeInit_Func    DeInit;
  lan8720_WriteReg_Func  WriteReg;
  lan8720_ReadReg_Func   ReadReg; 
  lan8720_GetTick_Func   GetTick;   
} lan8720_IOCtx_t;  

  
typedef struct 
{
  uint32_t            DevAddr;
  uint32_t            Is_Initialized;
  lan8720_IOCtx_t     IO;
  void               *pData;
}lan8720_Object_t;
/**
  * @}
  */ 

/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup LAN8720_Exported_Functions LAN8720 Exported Functions
  * @{
  */
int32_t LAN8720_RegisterBusIO(lan8720_Object_t *pObj, lan8720_IOCtx_t *ioctx);
int32_t LAN8720_Init(lan8720_Object_t *pObj);
int32_t LAN8720_DeInit(lan8720_Object_t *pObj);
int32_t LAN8720_DisablePowerDownMode(lan8720_Object_t *pObj);
int32_t LAN8720_EnablePowerDownMode(lan8720_Object_t *pObj);
int32_t LAN8720_StartAutoNego(lan8720_Object_t *pObj);
int32_t LAN8720_GetLinkState(lan8720_Object_t *pObj);
int32_t LAN8720_SetLinkState(lan8720_Object_t *pObj, uint32_t LinkState);
int32_t LAN8720_EnableLoopbackMode(lan8720_Object_t *pObj);
int32_t LAN8720_DisableLoopbackMode(lan8720_Object_t *pObj);
int32_t LAN8720_EnableIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_DisableIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_ClearIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_GetITStatus(lan8720_Object_t *pObj, uint32_t Interrupt);
/**
  * @}
  */ 

#ifdef __cplusplus
}
#endif
#endif /* LAN8720_H */


/**
  * @}
  */ 

/**
  * @}
  */

/**
  * @}
  */ 

/**
  * @}
  */       

PHY 接口测试

前面分别实现了 PHY 的读写接口,以及 LAN8720 相关的接口,这里简单测试一下,LAN8720 寄存器的读写功能

/* USER CODE BEGIN 0 */
static void print_binary(int value, int bits)
{
  for (int i = bits - 1; i >= 0; i--)
  {
    printf("%d", (value >> i) & 1);
  }
  printf("b\r\n");
}

static void MY_PHY_LAN8720_INIT(void)
{
  /* Set PHY IO functions */
  LAN8720_RegisterBusIO(&LAN8720, &LAN8720_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  if(LAN8720_Init(&LAN8720) != LAN8720_STATUS_OK)
  {
    printf("init lan8720 error\r\n");
    while(1);
  }

  printf("my phy addr = %d\r\n", LAN8720.DevAddr);

  uint32_t readval = 0;
  if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_PHYI1R, &readval) < 0)
  {
    printf("read lan8720 error\r\n");
    while(1);
  }
  printf("LAN8720_PHYI1R PHY ID Number = %d\r\n", readval);

  readval = 0;
  if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_PHYI2R, &readval) < 0)
  {
    printf("read lan8720 error\r\n");
    while(1);
  }

  uint32_t bits_15_10 = (readval >> 10) & 0x3F; // 提取 bit15:10
  printf("LAN8720_PHYI2R PHY ID Number = ");
  print_binary(bits_15_10, 6); // bit15:10 共 6 位

  uint32_t bits_9_4 = (readval >> 4) & 0x3F; // 提取 bit9:4 (6 位)
  printf("LAN8720_PHYI2R Model Number  = ");
  print_binary(bits_9_4, 6); // bit15:10 共 6 位


  readval = 0;
  if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_BCR, &readval) < 0)
  {
    printf("read lan8720 error\r\n");
    while(1);
  }
  printf("before write: %d\r\n", readval);

  readval |= LAN8720_BCR_LOOPBACK;
  if(LAN8720_IOCtx.WriteReg(LAN8720.DevAddr, LAN8720_BCR, readval) < 0)
  {
    printf("write lan8720 error\r\n");
    while(1);
  }

  readval = 0;
  if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_BCR, &readval) < 0)
  {
    printf("read lan8720 error\r\n");
    while(1);
  }
  printf("after bit14 set = ");
  print_binary(readval, 16); // 共 16 位
}
/* USER CODE END 0 */
  /* USER CODE BEGIN 2 */
  MY_PHY_LAN8720_INIT();

  printf("this is eht example\r\n");

  /* USER CODE END 2 */
  • 代码中先读取了 PHY 的地址
  • 读取 LAN8720_PHYI1R 寄存器获取 PHY ID Number
  • 读取 LAN8720_PHYI2R 寄存器获取 PHY ID NumberModel Number
  • 最后对 LAN8720_BCRbit14 进行了读写

部分地址的描述如下
在这里插入图片描述

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

效果如下

my phy addr = 0
PHY ID Number = 110000b
Model Number  = 001111b
before write: 0
after bit14 set = 0100000000000000b
this is eht example

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter_学习记录_AppBar中取消leading的占位展示

将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明&#xff1a; Controls whether we should try to imply the leading widget if null. If true and [AppBar.leading] is null, automatically try to deduce what the leading…

未来派几何风格包装徽标品牌海报标牌logo设计无衬线英文字体安装包 Myfonts – Trakya Sans Font Family

Trakya Sans 是一种具有几何风格的现代无衬线字体。Futura、Avant Garde 等。它具有现代条纹&#xff0c;这是宽度和高度协调的结果&#xff0c;尤其是在小写字母中&#xff0c;以支持易读性。 非常适合广告和包装、编辑和出版、徽标、品牌和创意产业、海报和广告牌、小文本、寻…

C语言深度解析:从零到系统级开发的完整指南

一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性&#xff0c;成为系统级开发的首选语言。例如&#xff0c;Linux内核通过C语言直接操作内存和硬件寄存器&#xff0c;实现高效进程调度。 关键点&#xff1a; malloc/free直接管理内存&#…

ctfshow WEB web8

首先确定注入点&#xff0c;输入以下payload使SQL恒成立 ?id-1/**/or/**/true 再输入一下payload 使SQL恒不成立 ?id-1/**/or/**/false 由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示 由以上返回结果可知&#xff0c;该页面存在SQL注入&#xff0c;注入点…

【Linux】U-Boot 加载并启动 Linux 系统程序

U-Boot 加载并启动 Linux 系统程序 零、介绍 最近在玩一些嵌入式的开发板&#xff0c;在引导操作系统时需要用到U-Boot&#xff0c;故此研究一下。 U-Boot&#xff08;Universal Bootloader&#xff09;是一款开源的通用引导加载程序&#xff0c;专为嵌入式系统设计&#xff…

jarvisoj API调用 [JSON格式变XXE]

http://web.jarvisoj.com:9882/ 题目要求&#xff1a;请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到&#xff1a; POST /api/v1.0/try HTTP/1.1 Host: web.jarvisoj.com:9882 Content-Length: 36 Accept-Language: zh-CN,zh;q0.9 User-Agent: Mozilla/5.0 (W…

机器学习的一百个概念(4)下采样

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

NNI 适配 TensorRT10教程

引言 本文涉及两个框架及其版本分别为 NNI (Neural Network Intelligence) &#xff1a;3.0TensorRT&#xff1a;10.9.0.34 NNI 在文档 Speed Up Quantized Model with TensorRT里描述了如何使用 TensorRT 为NNI量化的模型实现加速&#xff0c;但是从NNI 的源代码https://gi…

多路径 TCP 调度的另一面

参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演&#xff0c;一直都破而不立&#xff0c;不能光说怎样不好&#xff0c;还得说说现状情况下&#xff0c;该如何是好。 如果 receiver 乱序重排的能力有限(拜 TCP 所赐)&#xff0c;如果非要在多路径上传输 TCP&…

vcpkg安装指定版本的库

一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录&#xff08;D:\vcpkg&#xff09;&#xff0c;并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图&#xff1a; 二.安…

【工具变量】上市公司供应链稳定性数据两个维度(2013-2023年)

供应链稳定性是指供应链在面对各种内外部因素的冲击和不确定性时&#xff0c;能够保持持续、顺畅运作的能力&#xff0c;而供应链稳定性指数是用于评估企业在其供应链管理中保持稳定性的一个重要指标。本分享数据参考钟涛&#xff08;2022&#xff09;、董浩和闫晴&#xff08;…

Redis场景问题2:缓存击穿

Redis 缓存击穿是指在缓存系统中&#xff0c;大量请求&#xff08;高并发访问&#xff09;同时访问一个不存在于缓存中&#xff08;一般是因为缓存过期或者数据未被加载到缓存&#xff09;但在数据库中存在的热点数据&#xff0c;从而导致这些请求直接穿透缓存层&#xff0c;涌…

RocketMQ - 从消息可靠传输谈高可用

先稍微介绍下RocketMQ架构。 主从架构 Broker 集群&#xff1a;每个 Broker 分为 Master 和 Slave 角色&#xff0c;Master 负责读写&#xff0c;Slave 作为热备。 同步复制&#xff08;SYNC_MASTER&#xff09;&#xff1a;消息写入 Master 后&#xff0c;需等待 Slave 同步完…

ES拼音分词自动补全实现

#测试拼音分词 POST /_analyze { "text":"如家酒店真不错", "analyzer": "pinyin" } #这里把拼音的首字母放到这里&#xff0c;也说明了这句话没有被分词&#xff0c;而是作为一个整体出现的 #还把每一个字都形成了一个拼音&#…

EFISH-SBC-RK3576 + 5G模组:无线工业相机与分布式AI质检‌

在智能制造与仓储物流场景中&#xff0c;传统有线工业相机存在部署成本高、灵活性差等痛点。‌eFish-SBC-RK3576‌ 通过 ‌5G无线传输 分布式NPU协同‌&#xff0c;实现跨产线、跨工厂的AI质检系统&#xff0c;检测效率提升300%&#xff0c;布线复杂度降低90%。 ‌1. 系统架构…

C/C++ 基础 - 回调函数

目录 前言 回调函数预备知识 函数指针 什么是函数指针 函数指针的语法 如何用函数指针调用函数 函数指针作为函数的参数 函数指针作为函数返回类型 函数指针数组 回调函数 什么是回调函数 为什么要用回调函数 怎么使用回调函数 总结 前言 在写项目的时候&#x…

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的消息队列:使用 RabbitMQ 实现异步处

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…

DeepSeek分析仿写选题应该怎么做?

目录 选题分析&#xff1a;AIGC在学术写作中的应用及其与作者背景的关系 1. 选题背景与意义 2. 研究问题 3. 研究方法 4. 主要发现 5. 研究贡献 6. 研究局限与未来方向 7. 结论 8. 未来研究方向 大家好这里是AIWritePaper官方账号&#xff0c;官网&#x1f449;AIWrit…

19840 Dijkstra求最短路2

19840 Dijkstra求最短路2 相较于1&#xff0c;数据增强了&#xff0c;要用堆来优化&#xff0c;也就是优先队列。 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;Dijkstra、最短路问题 &#x1f4d6; &#x1f4da; import java.util.*;public class Main {static…

Redis-08.Redis常用命令-有序集合操作命令

一.有序集合操作命令 ZADD key score 1 member1 [score2 member2]&#xff1a; zadd zset 10.0 a 10.5 b ZRANGE key start stop [WITHSCORES]: zrange zset 0 -1 为何顺序为a&#xff0c;c&#xff0c;b&#xff1f; 因为 zrange zset 0 -1 withscores zrange key start …