How to integrate ENC28J60 with lwIP using STM32 Microcontroller
Hardware and Software Requirements
To complete the project successfully, you need the below items:
- Any microcontroller that has SPI
- Any ENC28J60-based breakout board
- RJ45 for Ethernet connection for local communication
The STM32F401RE Nucleo Board was used for this demonstration.
The ENC28J60 board was used for Ethernet connection.
I used KiCad to design my own interface module to avoid using a breadboard or having wires all over the place. The KiCad files can be shared upon request.
Hardware Setup
| Signal | Connection |
|---|---|
| 3.3V | NUCLEO 3V3 → ENC28J60 VCC |
| GND | NUCLEO GND → ENC28J60 GND |
| MOSI | PA7 (SPI1 MOSI) → SI |
| MISO | PA6 (SPI1 MISO) → SO |
| SCK | PA5 (SPI1 SCK) → SCK |
| CS | PB6 (GPIO Output) → CS |
| INT | PC7 (EXTI7) → INT |
ENC28J60 Driver Development
void enc28j60_initDr(enc28j60Drv * dev, spiChipSel cs, spiChipDSl dCS,
slaveRead rd, slaveWrite wr, intHandler hdle, delayMs delay);
void enc28j60_strtDr(enc28j60Drv * dev);
void enc28j60_sftRst(enc28j60Drv * dev);
bool enc28j60_intPnd(enc28j60Drv * dev);
void enc28j60_intSet(enc28j60Drv * dev);
void enc28j60_intCls(enc28j60Drv * dev);
bool enc28j60_etherReceive(enc28j60Drv * dev, uint8_t * data, uint16_t length);
bool enc28j60_etherTransmit(enc28j60Drv * dev, uint8_t * data, uint16_t length);
lwIP Integration
static uint8_t enc28j60_buffer[1500];
err_t enc28j60_translate(struct netif *netif, struct pbuf *p)
{
uint16_t length = p->len;
memcpy(enc28j60_buffer, (uint8_t *)p->payload, length);
enc28j60_etherTransmit(&dev, enc28j60_buffer, length);
return ERR_OK;
}
void ethernet_do_translation_to_pbub(enc28j60Drv * dev, struct pbuf *p)
{
p->next = NULL;
p->len = dev->rxPkt.rxPktLen.u16PktLen;
p->payload = dev->rxPkt.data;
memcpy((uint8_t *)p->payload,
dev->rxPkt.data,
dev->rxPkt.rxPktLen.u16PktLen);
p->ref = 1;
}
DHCP Client Specific Code
enc28j60_initDr(&dev, spi1ChipSelect, spi1ChipDeSelect,
spi1Read, spi1Write, NULL, delayMsFunction);
enc28j60_strtDr(&dev);
lwip_init();
netif_add_noaddr(&my_netif, NULL, ethernet_init, ethernet_input);
netif_set_default(&my_netif);
netif_set_up(&my_netif);
dhcp_set_struct(&my_netif, &myDhcpClient);
dhcp_start(&my_netif);
while(true)
{
if(u32FinerTimer >= 1)
{
u32FinerTimer -= 1;
dhcp_fine_tmr();
HAL_GPIO_TogglePin(GreenLED1_GPIO_Port, GreenLED1_Pin);
}
if(u32CoarseTimer >= 120)
{
u32CoarseTimer -= 120;
dhcp_coarse_tmr();
}
}
Ping Terminal Outputs
[... your ping output remains unchanged ...]
Source Code
The source code for the project can be found here — checkout the dhcpClient tag.