LAN8720 Ethernet Module Library for Proteus: the module on the LAN with the ESP32 page on the phone and the ETH events in the monitor

LAN8720 Ethernet Module Library for Proteus: ESP32 Wired Ethernet

2.5K Views
40
700
60
25
60
PCBWay

Hello friends, I hope you all are doing great. Today, I am going to share the LAN8720 Ethernet Module Library for Proteus. The LAN8720 module is the cheapest way to give an ESP32 a wired network: a small board with a Microchip LAN8720A Ethernet PHY, a 50 MHz oscillator and an RJ45 jack. The ESP32 already has an Ethernet controller inside, so the module only connects that controller to the cable, and your sketch uses the ETH library instead of WiFi.

Updates

LAN8720 Ethernet Module Library for Proteus

Latest version: V1.0 (October 2026, this tutorial)

Helping Tools

This is the thirty-fifth library of our Wi-Fi / Ethernet series and the eighth of its Ethernet group, and the first one for the ESP32 boards. In Proteus it works with our ESP32 boards: ETH.begin() finds the module by its wiring, the ETH events arrive as on a real ESP32, and the demo shows them on a web page for our Laptop WiFi Monitor and Mobile WiFi Monitor - with the cable pulled out and plugged back in.

NOTICE: the PANEL pad, the panel and the virtual router are TEP additions. The ESP32 board in Proteus runs your sketch on a hidden ATmega2560 (Proteus has no ESP32 model), so the sketch is compiled with our free TEP Boards for Proteus add-on (included). Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the LAN8720 Ethernet Module board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the LAN8720 Ethernet Module Library for Proteus:

LAN8720 Ethernet Module Library for Proteus: the module on the LAN with the ESP32 page on the phone and the ETH events in the monitor
Figure: The LAN8720 Ethernet Module Library for Proteus: the module (U2) on the LAN - PWR, LINK / ACT and 100M lit, the cable plugged in; the phone's page after LED ON and the ESP32's monitor with the ETH events.

What is the LAN8720 Ethernet Module?

An Ethernet port needs two parts: a MAC, which builds and checks the frames, and a PHY, which turns them into signals on the cable. Chips like the W5500 or the ENC28J60 have both and talk to a microcontroller over SPI. The ESP32 is different: its Ethernet MAC is built in, and it only needs a PHY. The LAN8720A from Microchip is that PHY - a 10/100 Mbit/s transceiver that talks to the ESP32 over RMII (the Reduced Media Independent Interface).

The LAN8720 module puts the chip on a small board with everything it needs: the 50 MHz oscillator that clocks the RMII, an RJ45 MagJack with its transformer and two LEDs, a few resistors and capacitors, and a 2x7 header. It is about 56 x 27 mm - roughly the size of an ESP32-DevKitC - and runs from 3.3 V. Many makers sell it, often as a "LAN8720 ETH Board".

The real LAN8720 module and the module in Proteus
Real LAN8720 moduleThis library in Proteus
ChipMicrochip LAN8720A, 10/100 PHYthe module as one part, with the LAN8720A as the ETH driver sees it
InterfaceRMII to the ESP32's MAC, MDC / MDIOthe same pins, checked by ETH.begin()
Clock50 MHz oscillator to the ESP32's GPIO0nINT/REFCLK must be wired to GPIO0
ESP32 libraryETH (Arduino-ESP32 core)ETH in our TEP Boards for Proteus add-on 1.14.0
Networkan RJ45 cable to your routera virtual cable to our router, shared with our Wi-Fi parts
LEDslink / activity, speedLINK / ACT, 100M and a PWR LED, all working

RMII: Seven Wires and a Clock

RMII moves the frames two bits at a time. The ESP32 sends on TX_EN, TX0 and TX1 (GPIO21, GPIO19 and GPIO22) and receives on RX0, RX1 and CRS_DV (GPIO25, GPIO26 and GPIO27). These pins are fixed inside the ESP32 - you cannot move them. The 50 MHz reference clock times them all; on this module it comes from the module's own oscillator, out of the nINT/REFCLK pin and into the ESP32's GPIO0. In the ETH library that is ETH_CLOCK_GPIO0_IN.

Two more wires form the management bus: MDC (the clock) and MDIO (the data). Through them the driver reads the PHY's registers - its identity, the link, the speed. They can go to any free GPIO; the usual choice is GPIO23 and GPIO18, the defaults of the ETH library.

Why GPIO0 Matters

GPIO0 is the clock input, so the ESP32 board must have GPIO0 on its header. Our ESP32-DevKitC V4 Library for Proteus has it, so the demo uses that board; the 30-pin ESP32 DevKit V1 does not bring GPIO0 out. On a real board, GPIO0 is also a boot pin: a clock already running when the ESP32 starts can keep it in its download mode. That is why many designs switch the oscillator on only after the boot, with a GPIO given to the library as ETH_PHY_POWER.

The PHY Address

Several PHYs can share one MDC / MDIO bus, so each has an address. The LAN8720A takes 0 or 1 from a pin at power-up (PHYAD0). The sketch must use the same address with ETH_PHY_ADDR, or -1 to let the driver look for it. Our module answers at 1; the PHYADDR property changes it.

Features of the LAN8720 Ethernet Module Library for Proteus

  • The module as it looks: the black board, the silver RJ45 jack with its green and yellow LEDs at the left end, two mounting holes, the LAN8720A with its 50 MHz oscillator, the 2x7 header at the right end, a red PWR LED and our PANEL pad.
  • ETH.begin() checks the wiring: it finds the module only when MDC and MDIO go to the sketch's pins, the module has power, the PHY address matches and the clock mode is ETH_CLOCK_GPIO0_IN - and Proteus's simulation log says what is wrong.
  • The ETH events: ETH_START, ETH_CONNECTED, ETH_GOT_IP, ETH_DISCONNECTED, ETH_LOST_IP and ETH_STOP reach WiFi.onEvent() or Network.onEvent() handlers, as on a real ESP32.
  • The ETH library: both the core 2.x and 3.x forms of ETH.begin(), ETH.config(), localIP(), macAddress(), linkUp(), linkSpeed(), fullDuplex() and setHostname(); WiFiClient, WiFiServer, WiFiUDP and WebServer run over the cable.
  • Working LEDs: LINK / ACT (it blinks with the traffic), the 100 Mbit/s LED and PWR.
  • The cable: pull it with a click on the jack, the CABLE property or the panel; the connections wait 20 s for it.
  • Our Laptop and Mobile WiFi Monitors: a laptop and a phone with browsers on the same network - included in the package.
  • Our pop-up panel: the phone, the MODULE and ETHERNET cards, an RMII page with what the ETH driver read over MDIO, a Test page, Settings and Help - with our TEP header, not a Windows title bar.
  • A complete package: about 2.49 MB with the ESP32-DevKitC V4 part and the add-on, without the C++ source code of the models.

The LAN8720 Module in Proteus

LAN8720 Ethernet Module in Proteus: the RJ45 jack, the LAN8720A, the 50 MHz oscillator, the 2x7 header and the pins
Figure: The part as the library draws it (running): the RJ45 jack with the cable's plug and its two LEDs, the mounting holes, the LAN8720A, the 50 MHz oscillator, the PWR LED, the PANEL pad and the 2x7 header; the pins named at the right edge.

Search LAN8720 in Pick Devices; the device LAN8720 ETHERNET MODULE is in TEPLAN8720.LIB. Its pins leave the right edge in the header's order: TX1, TX_EN, TX0, RX0, RX1, nINT/REFCLK, CRS_DV, MDIO, MDC, GND and VCC 3.3V. Click the PANEL pad or the LAN8720A to open the panel and the RJ45 jack to pull or plug the cable.

LAN8720 Ethernet Module in Proteus before Run: the LEDs off, no cable
Figure: The module before Run: the LEDs off, the port empty; the net labels at its pins go to the ESP32.

Every State of the Module

We ran the demo and paused the simulation for each picture. As soon as the sketch calls ETH.begin(), the module is found, the cable's plug appears and the PWR LED is on; the PHY then negotiates the link:

LAN8720 Ethernet Module in Proteus just after ETH.begin(): PWR on, the link not up yet
Figure: ETH_START: PWR on, the cable in, the link still negotiating - the jack's LEDs dark.
LAN8720 Ethernet Module in Proteus on the LAN with LINK / ACT and 100M lit
Figure: On the LAN: the green LINK / ACT LED and the yellow 100M LED lit, the address from DHCP.
LAN8720 Ethernet Module in Proteus with the cable out
Figure: The cable out: the port empty, both jack LEDs dark, PWR still on.

Download LAN8720 Ethernet Module Library for Proteus

Click the button below to download LAN8720-Ethernet-Module-Library-for-Proteus-v1.0.zip (about 2.49 MB, without the C++ source code of the models):

LAN8720 Ethernet Module Library for Proteus V1.0
  • README.txt: the device, installation, the demo, the pins, the properties, troubleshooting and the limits.
  • Proteus Library Files: TEPLAN8720.LIB (the module), TEPESP32DEVKITC.LIB (our ESP32-DevKitC V4), TEPLAPTOP.LIB and TEPMOBILE.LIB (our Laptop and Mobile WiFi Monitors).
  • Proteus Model Files: TEPNET.DLL (the module, the ESP32 boards, the two monitors and the network).
  • Proteus Simulation: the demo project, its HEX file and a copy of the DLL.
  • Arduino Code: the demo sketch and the TEP Boards for Proteus add-on 1.14.0 for the Arduino IDE, with the ETH library.

No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.

How to Install LAN8720 Ethernet Module Library for Proteus

  1. Close Proteus and extract the whole zip file, for example to your Desktop.
  2. Copy the four files from Proteus Library Files into the LIBRARY folder of Proteus (usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy TEPNET.DLL from Proteus Model Files into the MODELS folder - replace older copies (this TEPNET.DLL is the first one with the LAN8720 and Ethernet for the ESP32 boards, and it still runs every part of the series).
  4. Delete TEPLAN8720.IDX, TEPESP32DEVKITC.IDX, TEPLAPTOP.IDX and TEPMOBILE.IDX from the LIBRARY folder if they are there.
  5. Start Proteus, press P and search for LAN8720.

For your own sketches, copy the hardware folder from Arduino Code\TEP Boards for Proteus into your sketchbook folder (Documents\Arduino\hardware\tep\avr\boards.txt is the result) and replace any older copy - version 1.14.0 is the first one with the ETH library and the events. Restart the IDE, choose Tools > Board > TEP Boards for Proteus > ESP32-DevKitC V4 (TEP Proteus) and use Sketch > Export Compiled Binary. Double-click the board in Proteus and set its Program File to the HEX (see How to get the HEX file from Arduino).

Demo: ETH Events and a Web Page over the Cable

Open LAN8720-ETH-Events-with-Laptop-and-Mobile.pdsprj. The ESP32-DevKitC V4 (U1) is on the left, the LAN8720 module (U2) in the middle, the phone (MOB1) and the laptop (PC1) at the sides - they are on the router's network, like the real ones, so they have no wires.

LAN8720 Ethernet Module Proteus simulation: an ESP32-DevKitC V4 with the module, the Laptop WiFi Monitor and the Mobile WiFi Monitor
Figure: The whole demo: the titles, MOB1 the Mobile WiFi Monitor, U1 the ESP32-DevKitC V4 with D1 lit, U2 the LAN8720 module and PC1 the Laptop WiFi Monitor.

The module is wired to the board with net labels - a label on the board's pin and the same label on the module's pin are one wire. An LED with a 220R resistor sits on GPIO13:

The wiring of the demo
ESP32-DevKitC V4LAN8720 moduleNet label
GPIO21TX_ENTX_EN
GPIO19TX0TX0
GPIO22TX1TX1
GPIO25RX0RX0
GPIO26RX1RX1
GPIO27CRS_DVCRS_DV
GPIO0nINT/REFCLKREFCLK
GPIO23MDCMDC
GPIO18MDIOMDIO
3V3VCC 3.3V3V3
-GNDground
ESP32-DevKitC V4 on the Proteus sheet with the LED on GPIO13 and the net labels to the LAN8720
Figure: U1 on the sheet: the labels at its pins and D1 with R1 on GPIO13, lit from the phone.

The laptop and the phone come from our Laptop WiFi Monitor Library for Proteus and Mobile WiFi Monitor Library for Proteus. In this project the laptop's home page is http://192.168.1.101/events and the phone's http://192.168.1.101/ - the address the router gives U1. The laptop is 192.168.1.21 and the phone 192.168.1.41.

The Sketch: Six Lines before ETH.h

The ETH library reads its settings from defines placed before the include - the PHY type, its address, the MDC / MDIO pins, the power pin (none here) and the clock mode:

#define ETH_PHY_TYPE  ETH_PHY_LAN8720
#define ETH_PHY_ADDR  1                  // the module's PHY address (its PHYAD0 strap)
#define ETH_PHY_MDC   23
#define ETH_PHY_MDIO  18
#define ETH_PHY_POWER -1                 // no power / oscillator enable pin
#define ETH_CLK_MODE  ETH_CLOCK_GPIO0_IN // the module's 50 MHz clock into GPIO0

#include <ETH.h>
#include <WebServer.h>

Every event is kept in a small log with its time, so the page and the monitor can show it:

struct LogLine {
  unsigned long ms;
  arduino_event_id_t id;
};
String seconds(unsigned long ms) {
  return String(ms / 1000) + "." + String((ms / 100) % 10) + " s";
}

The heart of the sketch is the event handler. It stores and prints each event, then does what the event asks: the host name at ETH_START (before DHCP asks for an address), the link at ETH_CONNECTED, the address and the MAC at ETH_GOT_IP:

void onEvent(arduino_event_id_t event) {
  eventLog[eventCount % LOG_SIZE] = {millis(), event};
  eventCount++;
  Serial.print("[");
  Serial.print(seconds(millis()));
  Serial.print("] ");
  Serial.println(eventName(event));
  switch (event) {
    case ARDUINO_EVENT_ETH_START:
      ETH.setHostname("esp32-lan8720");  // before DHCP asks for an address
      break;
    case ARDUINO_EVENT_ETH_CONNECTED:
      Serial.printf("  link up: %u Mbit/s, %s duplex\n", (unsigned)ETH.linkSpeed(), ETH.fullDuplex() ? "full" : "half");
      break;
    case ARDUINO_EVENT_ETH_GOT_IP:
      Serial.print("  IP ");
      Serial.print(ETH.localIP());
      Serial.print(", MAC ");
      Serial.println(ETH.macAddress());
      ethReady = true;
      readySince = millis();
      break;
    case ARDUINO_EVENT_ETH_DISCONNECTED:
      Serial.println("  no link - the cable is out");
      ethReady = false;
      break;
    case ARDUINO_EVENT_ETH_STOP:
      ethReady = false;
      break;
    default:
      break;
  }
}

setup() adds the handler first, then starts Ethernet. If the module is missing, unpowered or wired wrong, ETH.begin() returns false:

  WiFi.onEvent(onEvent);                 // (Arduino-ESP32 3.x: Network.onEvent(onEvent) does the same)
  if (!ETH.begin()) {                    // the PHY, MDC / MDIO and the clock mode of the #defines above
    Serial.println("ETH.begin() failed - check the LAN8720's wiring, its 3.3 V and ETH_PHY_ADDR");
    while (true) delay(1000);
  }

Press Run and open the board's serial monitor (click its USB socket). The events arrive one by one - the link after the PHY's auto-negotiation, the address after DHCP:

ESP32 serial monitor in Proteus: ETH_START, ETH_CONNECTED at 100 Mbit/s full duplex and ETH_GOT_IP with the IP and MAC address
Figure: The ESP32's monitor at 115200 baud: ETH_START, ETH_CONNECTED (100 Mbit/s, full duplex) and ETH_GOT_IP with 192.168.1.101 and the MAC 24:0A:C4:00:00:04.
ESP32 + LAN8720 Ethernet: ETH events
Web server on port 80: /  /on  /off  /events
[0.0 s] ETH_START
[1.1 s] ETH_CONNECTED
  link up: 100 Mbit/s, full duplex
[2.0 s] ETH_GOT_IP
  IP 192.168.1.101, MAC 24:0A:C4:00:00:04

The MAC address of the Ethernet port is the ESP32's base MAC plus 3, as on a real chip. The panel opens at Run and shows the module on the LAN:

LAN8720 Ethernet Module panel in Proteus: the MODULE, ETHERNET and TRAFFIC cards on the LAN
Figure: On the LAN: the LAN8720A, the ESP32's Ethernet MAC, the LEDs; 192.168.1.101 from DHCP 0.90 s after the link, 100 Mbit/s full duplex.

Its RMII page shows what the ESP32's ETH driver did, newest first. Read it from the bottom: ETH.begin found the LAN8720 at PHY address 1, the driver read its ID over MDIO, switched auto-negotiation on, read the link and the speed, and DHCP gave the address. The server on port 80 is listening:

LAN8720 Ethernet Module panel in Proteus: the RMII page with the MDIO reads and DHCP
Figure: The RMII page: ETH.begin, the PHY ID 0x0007 0xC0F1, BCR, BSR (link up), PSCSR (100BASE-TX full duplex) and DHCP; the ESP32's server on port 80.

The Web Page

The sketch uses the same WebServer class as on Wi-Fi - the network underneath does not matter to it:

  server.on("/", handleRoot);
  server.on("/on", handleOn);
  server.on("/off", handleOff);
  server.on("/events", handleEvents);
  server.begin();

sendPage() builds the page from the ETH library's own answers - the link, the speed, the address, the MAC:

void sendPage() {
  String h = F("<html><head><title>LAN8720 Ethernet</title></head><body><h1>ESP32 + LAN8720</h1><p>Link: ");
  if (ETH.linkUp()) {
    h += ETH.linkSpeed();
    h += ETH.fullDuplex() ? F(" Mbit/s full duplex") : F(" Mbit/s half duplex");
  } else {
    h += F("down");
  }

and adds the last three events, newest first:

  const int first = eventCount > 3 ? eventCount - 3 : 0;   // the last three events, newest first
  for (int i = eventCount - 1; i >= first; i--) {
    h += F("<p>");
    h += seconds(eventLog[i % LOG_SIZE].ms);
    h += F("  ");
    h += eventName(eventLog[i % LOG_SIZE].id);
    h += F("</p>");
  }

Press Go in the phone's Browser:

Mobile WiFi Monitor in Proteus showing the ESP32 Ethernet page from the LAN8720
Figure: The phone: Link 100 Mbit/s full duplex, the IP and MAC, the time on the LAN, the LED on GPIO13 with LED ON, LED OFF and EVENTS, and the last three events; HTTP 200, 499 bytes in 0.05 s.

The LED from the Phone

/on and /off switch the LED and send the page again:

void handleOn() { requests++; setLed(true, "the web page"); sendPage(); }
void handleOff() { requests++; setLed(false, "the web page"); sendPage(); }

Tap LED ON. The page answers "LED on GPIO13: ON" and D1 lights up on the sheet:

Mobile WiFi Monitor in Proteus after LED ON: the LED on GPIO13 is ON
Figure: The phone after LED ON: http://192.168.1.101/on, "LED on GPIO13: ON".
LAN8720 Ethernet Module Proteus simulation running: the LED lit from the phone over the cable
Figure: The demo running after LED ON: D1 lit on U1, the module on the LAN, the phone's page on MOB1 and the laptop on PC1.

The monitor logs the request and the LED:

ESP32 serial monitor in Proteus: the phone's request and LED ON
Figure: The ESP32's monitor: GET / from the phone, then LED ON (the web page).
GET / from 192.168.1.41
LED ON (the web page)

The Event Log as Text

/events sends the whole log as text/plain - easy to read for a program, or for a person:

void handleEvents() {
  requests++;
  String t = F("LAN8720 ETH events (oldest first)\n");
  const int first = eventCount > LOG_SIZE ? eventCount - LOG_SIZE : 0;
  for (int i = first; i < eventCount; i++) {
    t += seconds(eventLog[i % LOG_SIZE].ms);
    t += "  ";
    t += eventName(eventLog[i % LOG_SIZE].id);
    t += "\n";
  }
  t += String(eventCount) + " events, " + (ethReady ? "on the LAN as " + ETH.localIP().toString() : String("not on the LAN")) + "\n";
  server.send(200, "text/plain", t);
}

The laptop's home page is /events, so its Go button shows the log:

Laptop WiFi Monitor in Proteus showing the ETH event log of the ESP32
Figure: The laptop: ETH_START, ETH_CONNECTED and ETH_GOT_IP with their times, "3 events, on the LAN as 192.168.1.101".
LAN8720 ETH events (oldest first)
0.0 s  ETH_START
1.1 s  ETH_CONNECTED
2.0 s  ETH_GOT_IP
3 events, on the LAN as 192.168.1.101

Pull the Cable

Now the part Wi-Fi demos cannot show. Click CABLE OUT in the panel (or the RJ45 jack). The PHY loses the link at once, both jack LEDs go dark and the sketch gets ETH_DISCONNECTED:

ESP32 serial monitor in Proteus: ETH_DISCONNECTED when the LAN8720 cable is pulled out
Figure: The ESP32's monitor: ETH_DISCONNECTED, "no link - the cable is out".
[12.7 s] ETH_DISCONNECTED
  no link - the cable is out

The address stays and the open connections wait. Put the cable back with CABLE IN: after the 1.2 s auto-negotiation comes ETH_CONNECTED, and 0.9 s later ETH_GOT_IP with the same address. If the cable stays out for more than 20 s, the connections are dropped and ETH_LOST_IP arrives. The laptop's /events now tells the whole story:

Laptop WiFi Monitor in Proteus: the ETH event log after the cable was pulled and plugged back
Figure: The laptop after the cable test: six events, the cable out at 12.7 s, the link back at 14.1 s and the address at 15.0 s.
LAN8720 ETH events (oldest first)
0.0 s  ETH_START
1.1 s  ETH_CONNECTED
2.0 s  ETH_GOT_IP
12.7 s  ETH_DISCONNECTED
14.1 s  ETH_CONNECTED
15.0 s  ETH_GOT_IP
6 events, on the LAN as 192.168.1.101

The Monitor's Commands

The monitor takes STATUS (the link, the address, the gateway, the MAC, the LED and the counts), EVENTS (the log), ON, OFF and HELP. The loop only serves the web clients and the monitor; the events come by themselves:

void loop() {
  server.handleClient();
  monitor();
}
ESP32 serial monitor in Proteus: STATUS, EVENTS and HELP of the LAN8720 demo
Figure: The ESP32's monitor: the end of STATUS, EVENTS with the six events, and HELP.
LED ON, 4 requests, 6 events
EVENTS
  0.0 s  ETH_START
  1.1 s  ETH_CONNECTED
  2.0 s  ETH_GOT_IP
  12.7 s  ETH_DISCONNECTED
  14.1 s  ETH_CONNECTED
  15.0 s  ETH_GOT_IP
HELP
Commands: STATUS, EVENTS, ON, OFF, HELP

Event names come from one small function - the same names the ESP32 core uses:

const char *eventName(arduino_event_id_t id) {
  switch (id) {
    case ARDUINO_EVENT_ETH_START: return "ETH_START";
    case ARDUINO_EVENT_ETH_STOP: return "ETH_STOP";
    case ARDUINO_EVENT_ETH_CONNECTED: return "ETH_CONNECTED";
    case ARDUINO_EVENT_ETH_DISCONNECTED: return "ETH_DISCONNECTED";
    case ARDUINO_EVENT_ETH_GOT_IP: return "ETH_GOT_IP";
    default: return "OTHER";
  }
}

The LAN8720 Panel

The panel opens at Run, in the look of our TEP Serial Monitor Advance for Proteus - our own TEP header, no Windows title bar. Its first page has a small phone of its own with the CABLE IN and CABLE OUT buttons, and three cards: MODULE with the chip, the ESP32's Ethernet MAC, the MDIO reads and the LEDs, ETHERNET with the router, the status, the address, the link and how long DHCP took, and TRAFFIC. OPEN ESP32 PAGE lets the panel's phone open the page the ESP32 serves:

LAN8720 Ethernet Module panel in Proteus: the panel phone opening the ESP32 page
Figure: The panel's phone with the ESP32's page; the requests of the laptop and the phone in TRAFFIC.

The ROUTER tab lists the router's clients - the ESP32 among them as a LAN client:

LAN8720 Ethernet Module panel in Proteus: the router tab with the ESP32 as a LAN client
Figure: The phone's ROUTER tab: the mobile, the laptop, ESP32 U1 (LAN) and the panel's phone.

The Test page measures the running model: the web request test lets the panel's phone open the page three times, and the cable test pulls the cable for 3 seconds, three times:

LAN8720 Ethernet Module Test page in Proteus: web requests and the cable test
Figure: The Test page: 3 of 3 pages answered (connect 4.0 ms, first byte 35.8 ms, full page 50.8 ms, 509 bytes); 3 cable pulls - back on the LAN 2.110 s after the cable went back in.

After the tests the RMII page shows each cable pull: the link down in reg 1, auto-negotiation, the link and the speed again, and the DHCP renewal with the same address:

LAN8720 Ethernet Module panel in Proteus: the RMII page after the cable tests
Figure: The RMII page at the end: the MDIO reads of every cable pull and the DHCP renewals; the clock and the PHY address below.

Pins of the LAN8720 Module

The Proteus pins of the LAN8720 module
PinESP32 pinWhat it does
TX_EN, TX0, TX1GPIO21, GPIO19, GPIO22 (fixed)the ESP32 sends
RX0, RX1, CRS_DVGPIO25, GPIO26, GPIO27 (fixed)the ESP32 receives; CRS_DV = carrier sense / data valid
nINT/REFCLKGPIO0the 50 MHz reference clock into the ESP32 (ETH_CLOCK_GPIO0_IN)
MDC, MDIOGPIO23, GPIO18 (the defaults)the management bus: the driver reads the PHY's registers
VCC 3.3V, GND3V3, GNDpower - the module has no regulator

Properties of the LAN8720 Module

Double-click the module to change them; every run starts again from the properties
PropertyWhat it does
ROUTERthe router the cable goes to - the network name of the Wi-Fi parts (TEP-WiFi)
CABLEthe Ethernet cable at Run: IN or OUT
PHYADDRthe PHY address the module answers at: 1 (its PHYAD0 strap) or 0
PANEL, PAGEPORTthe phone's tab at start; the port OPEN ESP32 PAGE opens (80)

With DHCP the address follows the board's number: U1 gets 192.168.1.101, U2 .102 and so on. In this model a board uses one network at a time - the cable (ETH) or Wi-Fi.

Troubleshooting

  • ETH.begin() returns false: read Proteus's simulation log - it names the reason: MDC / MDIO not on the sketch's pins, no power on VCC, ETH_PHY_ADDR not the module's address (use the PHYADDR value or -1), or a clock mode other than ETH_CLOCK_GPIO0_IN.
  • ETH_CONNECTED comes but ETH_GOT_IP never: an RMII pin or REFCLK is not wired - the log lists the missing ones.
  • No events at all: add the handler with WiFi.onEvent() before ETH.begin(), and let loop() return or call delay() now and then - the events are delivered there.
  • The page never opens: the cable is out (the panel shows CABLE OUT) or the board is not on the LAN yet.
  • ETH.h not found: the TEP Boards for Proteus add-on is older than 1.14.0 - replace it with the one in the zip.
  • No panel: click the PANEL pad or the LAN8720A, or turn "Open the panel at Run" back on in Settings.

Things to Know Before Using a Real LAN8720 Module

  • The clock and GPIO0: the module's oscillator runs as soon as it has power, and GPIO0 decides the ESP32's boot mode. If your ESP32 starts in its download mode, switch the oscillator's enable with a GPIO and give that pin to ETH_PHY_POWER, or let the ESP32 make the clock on GPIO17 (ETH_CLOCK_GPIO17_OUT) on a board wired for it.
  • The PHY address: boards differ - 0 or 1. If ETH.begin() fails, try the other one, or -1.
  • Short wires: RMII runs at 50 MHz. Keep the wires between the module and the ESP32 short, ideally a few centimetres, with a solid ground.
  • Power: 3.3 V only, and enough current for the PHY and the jack's LEDs.
  • The header: pin orders differ between makers - wire by the names printed on your board.
  • A real sketch: the demo compiles for a real ESP32 with Espressif's core ("ESP32 Dev Module") - set ETH_PHY_ADDR to your module's address.

Limitations of the Simulation

  • The ESP32 board in Proteus is NOT a real ESP32 chip: your sketch runs on a hidden ATmega2560 at 16 MHz with 8 KB of RAM, int is 16 bits, and there are no FreeRTOS tasks.
  • The module is the ESP32's link to the LAN, not a bit-by-bit RMII model: the 50 MHz clock and the MDIO waveform are not on the pins, the link is always 100 Mbit/s full duplex, and other PHYs or SPI Ethernet chips on ETH are not modelled.
  • The router, the phone, the internet host, the PANEL pad, the panel and the two monitors are TEP additions.
  • LAN8720 and Microchip are names of Microchip Technology, ESP32 of Espressif Systems; this library is not made or endorsed by Microchip, Espressif or Labcenter.
  • Tested in Proteus 8.5 in October 2026 (the demo as shipped, the board, the module, the laptop and the phone together at about 0.3 x real time on our PC). Proteus 7 is not supported.

So, that was all about the LAN8720 Ethernet Module Library for Proteus. I hope it helps you try wired Ethernet on the ESP32 before you touch the hardware - the RMII wiring, the 50 MHz clock on GPIO0, the PHY address and every ETH event, with the cable pulled and plugged back in. If your project uses an Arduino instead, our W5500 Ethernet Module Library for Proteus and ENC28J60 Ethernet Module Library for Proteus bring Ethernet over SPI. If you use the LAN8720 Ethernet Module Library for Proteus in a project, please share it in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!


Comments

0

Join the conversation