3. With Pic 16F877A
PIN CONNECTION
code
/*
*
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.15/'>\
<HTML><HEAD></HEAD><BODY>\
<h1>RESEARCH DESIGN
LAB,<p></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] = {0x54, 0x55, 0x58, 0x10,
0x00, 0x24}; // my MAC address
unsigned char myIpAddr[4]
= {192, 168, 1, 15};
// 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
*/
}