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.
ENC28j60 SPI wiring
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.
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.
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.
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).
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;
}
}