Enc28j60 Blinky

Intro

image of Enc28j60 Blinky There’s a few IP stacks available from Microchip, Microchip Libraries for Applications (MLA), or the TCP/IP Lite Stack from AN1921 download or extract a newer version from the Microchip Code Configurator (MCC). There’s also plenty of other TCP/IP implementation floating around the Microchip forum or other project sites, or the other option of make your own. The downloadable MLA doesn’t list 8-bit PICs as being supported, also it list “TCPIP (with Wi-Fi® support only),” but there is a header file for the ENC28J60 and an example TCP/IP project for an 18f PIC. I think the MLA frame work could be used in an ENC28J60 but may need some work. The MLA tcp/ip framework also has more features, mo features, mo flash. The MLA TCP/IP framework and TCP/IP Lite Stack are not interchangeable. I decided to go with the pre-made wheel, a working TCP/IP stack, so I downloaded the TCP/IP Lite Stack from Microchip. The goal of this project was simply, to test my ENC28J60 PCB, so using tested/working code is ideal. Initially I used the TCP Server Demo source from AN1921 with few changes, then I switched to the updated 2.1.1 available through MCC code configurator.


Components

Hardware

  • 3.3v Power supply
  • ENC28J60 breakout PCB
  • PIC18f4685
    • Chosen for its 96kb flash. The TCP/IP Lite stack says: “optimized (low Flash and RAM footprint) TCP/IP stacks for microcontrollers with ≥ 8KB Flash (UDP only) and ≥ 16KB Flash (TCP/IP).” But the free version of XC8 will use more flash. This simple tcp server will use ~30KB or more.
  • LED
    • A single green LED for proof of concept.
  • 180 ohm resistor
    • Current limiting resistor for LED. The forward voltage needed to run the LED (Vf) typically around 2v and maybe 10mA forward current (If). Power supply voltage is 3.3v so… (3.3v - 2v)/10mA = 130ohm. With that, a current limiting resistor can be chosen, 180 ohm will suffice.
  • 10k ohm resistor
    • Weak pull-up resistor for MCLR pin on the microcontroller (1k to 10k). Some 8-bit PIC’s have a built in weak pullup on MCLR, this chip doesn’t. (Always read the datasheet RTFDS)
  • jumper wires

Software

  • MPLABX
  • Hercules Utility from HW group
    • Nice tool with serial monitor, TCP client, TCP Server, UDP. In this project I use the serial monitor for viewing debug messages from the PIC18F4685, and the TCP client for connecting to the PIC18F4685 server and sending a 1 or 0 to turn on or off the LED.

    image of Hercules utility

  • Android TCP blinky client

Schematic

image of wiring diagram

ENC28j60 SPI wiring

image of SPI wiring diagram


Design

Notes

BSP

The board support package code contains all the specific configurations for PIC18F4685 and should be changed to reflect correct configuration bits and register configuration if a different micro controller is used.

Timer

The TCP IP Lite stack relies on a timer interrupt to be setup to supply one sec update. Time is used in managing the connection.

Uart

TCP IP Lite stack provides a syslog to output debug messages. Uart needs to be configured and putch() function setup to output through uart so that printf can be directed to uart.

SPI

Per ENC28J60 datasheet, configured to SPI mode 0,0. SCK (SPI clock) should be low on idle and transmit occurs on transitions of clock from active to idle. The ENC28J60 SPI clock rate can be as high as 20MHz, but mine didn’t run stable at higher SPI clock rate. For this test I went with SPI clock rate of fosc/16 (32/16 = 2MHz rate).

TCP/IP Lite Stack

The nice thing about using a stack or library, much of the work is already done. There’s one function to initialize the TCP/IP Lite stack: Network_Init(); and one for managing the connection: Network_Manage();

void main(void) {  

    Network_Init();

    while(1){     
        Network_Manage();
    }
    return;
}

Setup TCP server to listen on a port. This will open one socket on port 7, allowing one client to connect.

static tcpTCB_t port7TCB; //create a handle to the tcpTCB_t structure

TCP_SocketInit(&port7TCB);
TCP_Bind(&port7TCB, 7);  //set port to use as 7
TCP_Listen(&port7TCB);

Socket State should be used. The TCP server demo from AN1921 gives an example.

void TCP_Handler(void)
{
    // create the socket for the TCP Server
    static tcpTCB_t port7TCB;

    // create the TX and RX Server's buffers
    static uint8_t rxdataPort7[20];
    static uint8_t txdataPort7[20];

    uint16_t rxLen, txLen;
    socketState_t socket_state;

    socket_state = TCP_SocketPoll(&port7TCB); //get the state of port7TCB socket

    switch(socket_state)
    {
        case NOT_A_SOCKET:
            // Inserting and initializing the socket
            TCP_SocketInit(&port7TCB);
            break;
        case SOCKET_CLOSED:
            //configure the local port
            TCP_Bind(&port7TCB, 7);
            // add receive buffer
            TCP_InsertRxBuffer(&port7TCB, rxdataPort7, sizeof(rxdataPort7));
            // start the server
            TCP_Listen(&port7TCB);
            break;
        case SOCKET_CONNECTED:
            // check if the buffer was sent, if yes we can send another buffer
            if(TCP_SendDone(&port7TCB))
            {
                // check to see  if there are any received data
                rxLen = TCP_GetRxLength(&port7TCB);
                if(rxLen > 0)
                {
                    rxLen = TCP_GetReceivedData(&port7TCB);

                    //process received data.
                    //setup data to send back to client

                    // reuse the RX buffer
                    TCP_InsertRxBuffer(&port7TCB, rxdataPort7, sizeof(rxdataPort7));
                    //send a message back to client
                    TCP_Send(&port7TCB, txdataPort7, strlen(txdataPort7));
                }
            }
            break;
        default:
            // we should not end up here
            break;
    }
}

Source files

Enc28j60 Blinky