Toll-Free Customer Support 24/7

Ethernet Module

/*
* Project Name:
httpserver_example (Ethernet Library http server demo for ENC28J60 mcu)
* Copyright:
(c) Mikroelektronika, 2005-2010.
* Revision History:
2007/12/10:
- initial release; Author: Bruno Gavand.
2010/12/20:
- modified for PRO compilers (FJ);
2012/10/19:
Modifier pour usage personnel

* description :
* this code shows how to use the Spi_Ethernet mini library :
* the board will reply to ARP & ICMP echo requests
* the board will reply to HTTP requests on port 80, GET method with pathnames :
* / will return the HTML main page
* /s will return board status as text string
* /t0 ... /t7 will toggle PD0 to PD7 bit and return HTML main page
* all other requests return also HTML main page
* Test configuration:
MCU: PIC16F877A
http://ww1.microchip.com/downloads/en/DeviceDoc/41291D.pdf

Dev.Board: PIC-Ready1
http://www.mikroe.com/products/view/177/pic-ready-prototype-board/
http://www.mikroe.com/products/view/305/pic-ready1-board/

Oscillator: External Clock 8.0000 MHz
Ext. Modules: ac:Serial_Ethernet_board
http://www.mikroe.com/eng/products/view/14/serial-ethernet-board/

SW: mikroC PRO for PIC
http://www.mikroe.com/en/compilers/mikroc/pro/pic/
* NOTES:
- Connect Serial Ethernet Board on PortC (Board and MCU Specific)
- Since the ENC28J60 doesn't support auto-negotiation, full-duplex mode is
not compatible with most switches/routers. If a dedicated network is used
where the duplex of the remote node can be manually configured, you may
change this configuration. Otherwise, half duplex should always be used.
- External power supply should be used due to Serial Ethernet Board power consumption.
*/
/*
Pour voir l'états des variables tapper : 192.168.0.170/s

Pour faire une commande d'interrupteur faire :
192.168.0.170/dXo ouvre(OFF)
192.168.0.170/dXf ferme(ON)

avec X pour valeur : 0 a 7
*/
// duplex config flags
#define Spi_Ethernet_HALFDUPLEX 0x00 // half duplex
#define Spi_Ethernet_FULLDUPLEX 0x01 // full duplex

// mE ehternet NIC pinout
sfr sbit SPI_Ethernet_Rst at RC0_bit;
sfr sbit SPI_Ethernet_CS at RC1_bit;
sfr sbit SPI_Ethernet_Rst_Direction at TRISC0_bit;
sfr sbit SPI_Ethernet_CS_Direction at TRISC1_bit;
// end ethernet NIC definitions

typedef struct
{
unsigned canCloseTCP: 1; // flag which closes TCP socket (not relevant to UDP)
unsigned isBroadcast: 1; // flag which denotes that the IP package has been received via subnet broadcast address (not used for PIC16 family)
} TEthPktFlags;

/************************************************************
* ROM constant strings
*/
const unsigned char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ; // HTTP header
const unsigned char httpMimeTypeHTML[] = "text/html\n\n" ; // HTML MIME type
const unsigned char httpMimeTypeScript[] = "text/plain\n\n" ; // TEXT MIME type
unsigned char httpMethod[] = "GET /";
/*
* web page, splited into 2 parts :
* when coming short of ROM, fragmented data is handled more efficiently by linker
*
* this HTML page calls the boards to get its status, and builds itself with javascript
*/
//*************************************************************************
// Change the IP address of the page to be refreshed

const char *indexPageHEAD = "<meta http-equiv='refresh' content='10;url=http://192.168.1.170/'>\
<HTML><HEAD></HEAD><BODY>\
<h1>PIC 16F887 (8MHz) + ENC28J60 Mini Web Server,<p>avec MikroC PRO v5.6.1</h1>\
<p><a href=\"http://olivier.fournet.free.fr/e.html\">NOTICE</a><p>\
<p><a href=/>Reload</a><p>\
<script src=/s></script>";

const char *indexPageBODY = "<table><tr><td valign=top><table border=1 style='font-size:20px; font-family: terminal;'>\
<tr><th colspan=2>ADC</th></tr>\
<tr><td>AN2</td><td><script>document.write(AN2);</script></td></tr>\
<tr><td>AN3</td><td><script>document.write(AN3);</script></td></tr>\
</table></td><td><table border=1 style='font-size:20px; font-family: terminal;'>\
<tr><th colspan=2>PORTB (IN) : <script>document.write(PORTB);</script></th></tr>\
<script>\
var str,i;\
str='';\
for(i=0;i<8;i++)\
{\
str+='<tr><td bgcolor=#cccccc>BUTTON #'+i+'</td>';\
if(PORTB&(1<<i))\
{str+='<td bgcolor=green>ON';}\
else\
{str+='<td bgcolor=red>OFF';}\
str+='</td></tr>';}\
document.write(str);\
</script>";

const char *indexPageBODY2 = "</table></td><td>\
<table border=1 style='font-size:20px; font-family: terminal;'>\
<tr><th colspan=3>PORTD (OUT) : <script>document.write(PORTD);</script></th></tr>\
<script>\
var str,i;\
str='';\
for(i=0;i<8;i++)\
{\
str+='<tr><td bgcolor=#cccccc>LED #'+i+'</td>';\
if(PORTD&(1<<i))\
{\
str+='<td bgcolor=yellow>ON';\
}\
else\
{\
str+='<td bgcolor=#999999>OFF';\
}\
str+='</td></tr>';}\
document.write(str);\
</script>\
</table></td></tr></table>\
<p>This is HTTP request #<script>document.write(REQ)</script><p>\
</BODY></HTML>";

//*************************************************************************


/***********************************
* RAM variables
*/
unsigned char myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f}; // my MAC address
unsigned char myIpAddr[4] = {192, 168, 1, 170}; // my IP address
unsigned char getRequest[15]; // HTTP request buffer
unsigned char get_Request, digit_getRequest, etat_interrupteur;
unsigned char dyna[30]; // buffer for dynamic response
unsigned long httpCounter = 0; // counter of HTTP requests

/*******************************************
* functions
*/

/*
* put the constant string pointed to by s to the ENC transmit buffer.
*/
/*unsigned int putConstString(const char *s)
{
unsigned int ctr = 0 ;

while(*s)
{
Spi_Ethernet_putByte(*s++) ;
ctr++ ;
}
return(ctr) ;
}*/
/*
* it will be much faster to use library Spi_Ethernet_putConstString routine
* instead of putConstString routine above. However, the code will be a little
* bit bigger. User should choose between size and speed and pick the implementation that
* suites him best. If you choose to go with the putConstString definition above
* the #define line below should be commented out.
*
*/
#define putConstString SPI_Ethernet_putConstString

/*
* put the string pointed to by s to the ENC transmit buffer
*/
/*unsigned int putString(char *s)
{
unsigned int ctr = 0 ;

while(*s)
{
Spi_Ethernet_putByte(*s++) ;

ctr++ ;
}
return(ctr) ;
}*/
/*
* it will be much faster to use library Spi_Ethernet_putString routine
* instead of putString routine above. However, the code will be a little
* bit bigger. User should choose between size and speed and pick the implementation that
* suites him best. If you choose to go with the putString definition above
* the #define line below should be commented out.
*
*/
#define putString SPI_Ethernet_putString

/*
* this function is called by the library
* the user accesses to the HTTP request by successive calls to Spi_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
* the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
*
* if you don't need to reply to HTTP requests,
* just define this function with a return(0) as single statement
*
*/
unsigned int SPI_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort,
unsigned int localPort, unsigned int reqLength, TEthPktFlags *flags)
{
unsigned int len = 0 ; // my reply length
unsigned int i ; // general purpose integer

// should we close tcp socket after response is sent?
// library closes tcp socket by default if canClose flag is not reset here
// flags->canClose = 0; // 0 - do not close socket
// otherwise - close socket

if(localPort != 80)
{ // I listen only to web request on port 80
return(0) ;
}

// get 10 first bytes only of the request, the rest does not matter here
for(i = 0 ; i < 10 ; i++)
{
getRequest[i] = SPI_Ethernet_getByte() ;
}

getRequest[i] = 0 ;

if(memcmp(getRequest, httpMethod, 5))
{ // only GET method is supported here
return(0) ;
}

httpCounter++ ; // one more request done

get_Request = getRequest[5]; // s , d

if(get_Request == 's') // utiliser pour <script src=/s></script>
{
// if request path name starts with s, store dynamic data in transmit buffer
// the text string replied by this request can be interpreted as javascript statements
// by browsers
len = putConstString(httpHeader); // HTTP header
len += putConstString(httpMimeTypeScript); // with text MIME type

// add AN2 value to reply
IntToStr(ADC_Read(2), dyna);
len += putConstString("var AN2=");
len += putString(dyna);
len += putConstString(";");

// add AN3 value to reply
IntToStr(ADC_Read(3), dyna);
len += putConstString("var AN3=");
len += putString(dyna);
len += putConstString(";");

// add PORTB value (buttons) to reply
len += putConstString("var PORTB=");
IntToStr(PORTB, dyna);
len += putString(dyna);
len += putConstString(";");

// add PORTD value (LEDs) to reply
len += putConstString("var PORTD=");
IntToStr(PORTD, dyna);
len += putString(dyna);
len += putConstString(";");

// add HTTP requests counter to reply
IntToStr(httpCounter, dyna);
len += putConstString("var REQ=");
len += putString(dyna);
len += putConstString(";");
}
else
{
//
if(get_Request == 'd') // Commande PORTD
{
if( isdigit(getRequest[6]) )
{
digit_getRequest = getRequest[6] - '0'; // numéro de port 0 à 7

if( getRequest[7] == 'o' ) // Contact Ouvert (OFF)
etat_interrupteur = 0;

if( getRequest[7] == 'f' ) // Contact Fermer (ON)
etat_interrupteur = 1;

switch(digit_getRequest)
{
case 0: PORTD.B0 = etat_interrupteur; break;
case 1: PORTD.B1 = etat_interrupteur; break;
case 2: PORTD.B2 = etat_interrupteur; break;
case 3: PORTD.B3 = etat_interrupteur; break;
case 4: PORTD.B4 = etat_interrupteur; break;
case 5: PORTD.B5 = etat_interrupteur; break;
case 6: PORTD.B6 = etat_interrupteur; break;
case 7: PORTD.B7 = etat_interrupteur; break;
}
}
}
//
}

if(len == 0)
{ // what do to by default
len = putConstString(httpHeader); // HTTP header
len += putConstString(httpMimeTypeHTML); // with HTML MIME type
len += putConstString(indexPageHEAD); // HTML page first part
len += putConstString(indexPageBODY); // HTML page second part
len += putConstString(indexPageBODY2); // HTML page second part
}

return(len) ; // return to the library with the number of bytes to transmit
}

/*
* this function is called by the library
* the user accesses to the UDP request by successive calls to Spi_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
* the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
*
* if you don't need to reply to UDP requests,
* just define this function with a return(0) as single statement
*
*/
unsigned int SPI_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort,
unsigned int destPort, unsigned int reqLength, TEthPktFlags *flags)
{
return 0; // back to the library with the length of the UDP reply
}

/*
* main entry
*/
void main()
{
//ANSEL = 0x0C ; // AN2 and AN3 convertors will be used
//C1ON_bit = 0; // Disable comparators
//C2ON_bit = 0;
PORTA = 0 ;
TRISA = 0xff ; // set PORTA as input for ADC

//ANSELH = 0; // Configure other AN pins as digital I/O
PORTB = 0 ;
TRISB = 0xff ; // set PORTB as input for buttons

PORTD = 0 ;
TRISD = 0 ; // set PORTD as output

/*
* starts ENC28J60 with :
* reset bit on RC0
* CS bit on RC1
* my MAC & IP address
* full duplex
*/
SPI1_Init();
SPI_Ethernet_Init(myMacAddr, myIpAddr, Spi_Ethernet_FULLDUPLEX) ;

while(1)
{ // do forever
/*
* if necessary, test the return value to get error code
*/
SPI_Ethernet_doPacket() ; // process incoming Ethernet packets

/*
* add your stuff here if needed
* Spi_Ethernet_doPacket() must be called as often as possible
* otherwise packets could be lost
*/
}
}

Back to top