Serial to ethernet

The serial to ethernet module adds TCP/UDP connectivity to your project. I took on this project after testing several cheap modules from eBay, that did not perform as expected.


The ENC28J60 module is from eBay, the only addition is the STM32F100 ARM microcontroller, making this a lot more a software project than hardware. The module works @3.3V. Since the ENC module makes 6.25 MHz clock available on one of its pins, the MCU uses that for system clock so an extra crystal is not required. The module draws about 90mA.

The module is driven by AT commands. Starting baud rate is 38400.


  • IP configuration is available with DHCP only. Static configuration is achievable by configuring the module with DHCP first and then saving/loading the configuration from flash.
  • Only a single simultaneous TCP/UDP connection is possible.
  • No higher level protocols (http,smtp,...) are implemented. You're expected to do that in the application using the module.
  • MAC is set using the MCU's unique identifier
  • The send/receive protocol is designed to handle ASCII data, not binary.

General commands:

Command Description
AT Returns OK
Echo on/off
ATI Returns ID string
AT+IPR=baud Change baud rate

IF configuration commands (pre TCP/UDP/DNS):

Command Description
AT+LWIPINIT Init lwIP and hw interface
AT+LWIPMAC=? Returns hw interface MAC
AT+LWIPDHCP Starts automatic IP configuration via DHCP
AT+LWIPIP=? Returns currently configured own IP
AT+LWIPNM=? Returns currently configured netmask
AT+LWIPGW=? Returns currently configured gateway
AT+LWIPSAVE Stores current IP configuration to flash
AT+LWIPLOAD Restores IP configuration from flash

TCP commands:

Command Description
AT+TCPCONNECT=dst_ip,dst_port,src_port Connect to dst_ip:dst_port from src_port
AT+TCPLISTEN=port Start listening on port
AT+TCPSEND Send data over established connection
AT+TCPCLOSE Close connection

UDP commands:

Command Description
AT+UDPCONNECT=dst_ip,dst_port Set peer IP and port
AT+UDPLISTEN=port Start listening for packets on port
AT+UDPSEND Send packet to peer
AT+UDPCLOSE Forget peer IP and port

DNS commands

Command Description
AT+DNS=? Returns currently configured DNS servers
AT+DNSLOOKUP=hostname Resolves hostname to IP using the configured DNS server


After powerup, the hardware and lwIP library need to be initialized with AT+LWIPINIT. Next the IF needs to be configured by either calling AT+LWIPDHCP or, if the IP settings have been previously saved to flash, AT+LWIPLOAD. At this point TCP/UDP connections are ready to be made.

Connections are initiated by the module with AT+[TCP/UDP]CONNECT command. The TCP version does actual connection handshaking with the peer and signals a successfully established connection with +LWIP: CONNECT. The UDP version simply sets internal peer IP and port variables and immediately returns with OK. The UDP connection is therefore virtual - no data is actually being sent on the wire. Note that the CONNECT commands accept peer parameter in the form of an IP address only. If you want to use hostnames, you need to manually lookup your peer's IP using the AT+DNSLOOKUP command.

To listen for incoming connections use AT+[TCP/UDP]LISTEN. The TCP version behaves exactly like the outbound version, i.e. when a client connects the module will signal so with +LWIP: CONNECT. The UDP version treats the first received packet as a virtual connection opener - upon reception, the peer IP and port will be remembered and the packet contents output.

To send data, use AT+[TCP/UDP]SEND. Upon command reception, the module outputs > and waits for data. Character 0x1a (Ctrl-Z) is data terminator. The protocol is designed to transfer ASCII data and not binary.

All received TCP/UDP data is sent over the serial interface immediately.

To close a connection (and possibly begin a new one), use AT+[TCP/UDP]CLOSE. The TCP version will inform the peer to gracefully close the connection and signal completion with +LWIP: CLOSE. For UDP this simply means the stored peer IP and port are forgotten and OK is returned immediately.

Init example

Command Reponse Comment
MK ser2eth v1.5
+LWIP: IFSTAT Sent after DHCP completes

TCP example

Command Reponse Comment
+LWIPDNS: Sent after DNS resolution completes
+LWIP: CONNECT Sent after connection is established
512> Number before > is bytes of buffer free
GET / HTTP/1.1
Host: google.com
Send 0x1a (Ctrl-Z) to end data entry
HTTP/1.1 302 Found
Location: http://www.google.si/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
(removed the rest of reply)
Server response is sent immediately upon reception
+LWIP: CLOSE Sent after connection is closed

To listen instead of connecting, simply replace AT+TCPCONNECT=ip,port,srcport with AT+TCPLISTEN=port. In both cases +LWIP: CONNECT signals that the connection was established.

UDP example

Command Reponse Comment
AT+UDPCONNECT=,1234 OK Begin a virtual UDP connection.
512> Number before > is max packet size
hello world Send 0x1a (Ctrl-Z) to end data entry

To listen instead of connecting, replace AT+UDPCONNECT=ip,port with AT+UDPLISTEN=port and wait for the first packet to arrive.

Bill of materials

ser2eth board ser2eth schematics

Qty Value / Farnell code Device Size Parts
1 1838512 STM32F100 LQFP48 IC1
4 100n multilayer 0805 C1, C2, C3, C4


Gerbers | HEX v1.5 | Source on GitHub

To compile the sources, my STM32F10x library is required.